GNU汇编语法和Cortex-A7常用汇编指令

GNU汇编语法

GNU汇编语法适用于所有架构,并不只被ARM独享,GNU语句的格式如下:

bash 复制代码
label: instruction @ comment
#label即标号,指的是地址位置,有些指令前面有标号,代表这个指令的地址
#任何以:作为结尾的标识符都会被识别为一个标号
#instruction指的是伪指令或者汇编指令
#comment表示注释
#ARM中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用

伪操作

.section:用户可以使用.section来定义一个段,语法格式:

bash 复制代码
.section .testsection @定义了一个testsection段

汇编系统也预先定义了一些段名,比如说:.text表示代码段,.data表示初始化的数据段,.bss表示未初始化的数据段,.rodata表示只读数据段。
其他

  1. .byte定义单字节数据,比如.byte 0x12
  2. .short定义双字节数据,比如.short 0x1234
  3. .long定义一个四字节数据,比如.long 0x12345678
  4. .equ赋值语句,格式为:.equ 变量名,表达式,比如说.equ num 0x12,表示num=0x12
  5. .align表示数据字节对齐,比如.align 4表示4字节对齐
  6. .end表示源文件结束
  7. .global定义一个全局符号,比如说.global _start
    函数
    GNU汇编支持函数:
bash 复制代码
函数名:
	函数体
	返回语句(不是必须的)
@举例
Undefined_Handler:
	ldr r0,=Undefined_Handler
	bx r0

Cortex-A7常用汇编指令

处理器内部数据传输指令

处理器内部来回传递数据,常见的操作有三个,第一个是将数据从一个寄存器传到另外一个寄存器,第二种是将数据从一个寄存器传到特殊寄存器,如CPSR和SPSR寄存器,第三种是将立即数传到寄存器里。
MOV指令:将源寄存器里的数据拷贝到目的寄存器里,或者将一个立即数传递到寄存器里。

bash 复制代码
MOV R0,R1 @将寄存器R1的数据传递给寄存器R0,即R0=R1
MOV R0,#0X12 @将立即数0X12传递给R0寄存器,即R0=0X12

MRS指令:用于将特殊寄存器里的数据传递给通用寄存器,要读取特殊寄存器里的数据只能使用MRS指令。

bash 复制代码
MRS R0,CPSR @将特殊寄存器CPSR里的数据传递给R0,即R0=CPSR

MSR指令:将普通寄存器的数据传递给特殊寄存器,写特殊寄存器只能使用MSR。

bash 复制代码
MSR CPSR,R0 @将普通寄存器的数据传递给通用寄存器,即CPSR=R0

存储器访问指令

ARM不能直接访问存储器,我们用汇编来配置IMX6UL的时候需要借助存储器访问指令,一般先将要配置的值写入到Rx寄存器中,然后借助存储器访问指令将Rx寄存器里的数据写入到存储器中,
LDR指令:LDR主要用于从存储器里加载数据到寄存器Rx中,也可以将一个立即数加载到寄存器Rx中,LDR加载立即数的时候要用=,而不是#,LDR最常用的场景就是读取一个寄存器里的数据了,比如说我们有个寄存器GPIO1_GPIR,地址为0X12345678,那么我们可以通过如下的方式读取寄存器的数据。

bash 复制代码
LDR Rd, [Rn , #offset]
bash 复制代码
LDR R0,=0X12345678 @将寄存器地址0X12345678加载到R0中
LDR R1,[R0]	@读取0X12345678位置的数据到R1中
#上述代码的offset为0

STR指令:STR主要用于把数据写入存储器中。

bash 复制代码
STR Rd, [Rn, #offset]
bash 复制代码
LDR R0,=0X12345678 @将寄存器的地址写入R0中
LDR R1,=0X87654321 @将要写入内存的数据写入R1中
STR R1,[R0] @将R1中的值写入R0保存的地址中

LDR和STR都是按照字写入数据的,如果需要按照字或者半字写入数据,可以在指令后面加入B或者H,比如说LDRB,LDRH,STRB,STRH。

压栈和出栈

C语言里经常在一个函数里调用另外一个函数,如果在调用函数A期间我们需要调用函数B,那么就要对函数A的现场进行保护,保存函数A的上下文,当函数B执行完之后,再恢复执行函数A时候的寄存器即可,现场保护需要用到入栈操作,恢复现场需要用到出栈操作。

PUSH:将寄存器列表存入栈中,假设我们现在要将R0~R3和R12寄存器压入堆栈里,处理器的堆栈是向下生长的。

bash 复制代码
PUSH {R0~R3,R12} @将R0~R3,R12压栈
#还有一种写法
STMFD SP!,{R0~R3,R12}


POP:从栈中恢复寄存器列表,如果我们要出栈的话可以使用如下代码。

bash 复制代码
POP {R0~R3,R12}
#还有另外一种写法
LDMFD SP!,{R0~R3,R12}

出栈的位置是栈顶,也就是SP指针当前的位置,向上增长。

跳转

B指令:B指令会将PC寄存器里的值设置为目标跳转地址,一旦执行B指令,ARM处理器就会立刻跳转到目标地址,如果不再返回原来的位置,就可以使用B指令。

bash 复制代码
_start:
	ldrsp,=0x80200000 @设置栈顶指针
	b main @跳转到main函数

BL指令:BL指令在跳转之前会在LR中保存当前PC寄存器的值,所以可以将LR寄存器里的值重新加载到PC中跳转到之前的代码继续运行。

bash 复制代码
push {R0,R1}
cps #0x13 @允许中断再次进去
bl system_irqhandler @加载C语言中断程序到R2寄存器里
cps #0x12 @进入irq模式
pop {R0,R1}
str R0,[R1,#0X10] @中断执行完成

运算符指令

算数运算

逻辑运算

相关推荐
小诗懂技术13 小时前
【网络通信UDP】基础 进程间不同主机的通信
运维·服务器·网络
weixin_4407305013 小时前
selenium实战记录-从登陆-首页-进入应用流程用例三种参数化+日志+报告
服务器·selenium·测试工具
Hstar_chen14 小时前
开源一款 HarmonyOS 服务器监控客户端:星辰云巡 1.0.3
服务器·华为·harmonyos
开心大爆炸18 小时前
xrdp 连接 登录对话框输入密码后闪退
linux·运维·服务器
苏生Susheng19 小时前
【软件实施】Linux系统Shell脚本教程
linux·运维·服务器·chrome·spring boot·学习·实施
曹牧19 小时前
C#:文本文件读取
服务器·前端·c#
Ruiery19 小时前
Linux 6.6内核 IOMMU 深度解析(七):DMA API 与 IOMMU 集成 — 从 dma_map_single 到 iommu_map
linux·运维·服务器
snow@li20 小时前
服务器运维:Alibaba Cloud Linux 4 LTS 64位 根目录全景深度解析文章
linux·运维·服务器
苏生Susheng20 小时前
【软件实施】Linux企业运维常用命令手册
java·linux·运维·服务器·springboot·springcloud·软件实施
西索斯coding20 小时前
doubao-seed-2.1-turbo 调用一直 401 怎么办?pro 版同样的 Key 却正常——5 分钟排查定位指南
java·服务器·数据库·ai