注意!ARM 中的指令、伪指令、伪操作、寄存器名等可以全部使用大写,也可以全部使用小写,但是不能大小写混用。
目录
伪操作、段
label:instruction@comment
标号(地址位置):指令@注释
add:
MOVS R0,#0x12 @设置 R0=0x12
.test 表示代码段
.data初始化的数据段
.bss未初始化的数据段
.rodata 只读数据段
用户可以使用 . section 来定义一个段 每个段以段名开始以下一个段段名或文件结尾结束
.section .testsection @定义一个testsection段
汇编程序的默认入口标号是_start,不过我们也可以在链接脚本中使用 ENTRY 来指明其它的入口点,下面的代码就是使用_start 作为入口标号:
.global _start
_start:
ldr r0,=0x12 @r0=0x12
上面代码中.global 是伪操作,表示_start 是一个全局标号,类似 C 语言里面的全局变量一样,常见的伪操作有:
.byte 定义单字节数据,比如.byte 0x12。
.short 定义双字节数据,比如.short 0x1234。
.long 定义一个 4 字节数据,比如.long 0x12345678。
.equ 赋值语句,格式为:.equ 变量名,表达式,比如.equ num, 0x12,表示 num=0x12。
.align 数据字节对齐,比如:.align 4 表示 4 字节对齐。
.end 表示源文件结束。
.global 定义一个全局符号,格式为:.global symbol,比如:.global _start。
GNU 汇编也支持函数,函数格式如下: GNU 汇编函数返回语句不是必须的
函数名:
函数体
返回语句
一、处理器常用指令
MOV指令 将数据从一个寄存器拷贝到另外一个寄存器
MOV R0,R1 @将R1的数据复制到R0 即 R0=R1
MOV R0,#0x12 @将立即数0x12传递给R0寄存器 即R0=0X12
MRS指令 用于将特殊寄存器 如 CPSR、SPSR 中的数据传递给通用寄存器,要读特殊寄存器的只能用MRS指令
MRS R0 , CPSR
MSR指令 用来将通用寄存器的值传递给特殊寄存器,也就是写特殊寄存器 ,写特殊寄存器只能用MSR
MSR CPSR , R0
二、存储器访问指令
ARM不能直接访问存储器,比如RAM中的数据 I.MX6ul中的寄存器就是RAM类型的 我们用汇编来配置 I.MX6UL 寄存器的时候需要借助存储器访问指令,一般先将要配置的值写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到 I.MX6UL 寄存器 读取也是一样的
LDR指令 LDR用于从存储加载数据到Rx中,LDR最长用的就是读取CPU的寄存器值
LDR R0, =0x0209c004 @将寄存器地址0x0209c004加载到R0中 即R0= 0x0209c004
LDR R1, 【R0】 @读取地址0x0209c004中的地址到R1寄存器中
STR 用于写数据到存储器中
LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C0042
LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X200000023
STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中
LDR 和 STR 都是按照字进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、半字进行操作的话可以在指令“LDR”后面加上 B 或 H,比如按字节操作的指令就是 LDRB 和STRB,按半字操作的指令就是 LDRH 和 STRH。
三、压栈和出栈指令
现场保护的时候需要进行压栈 即入栈,恢复现场要进行出栈操作
压栈指令为PUSH 出栈指令为POP 这是一种多存储和多加载指令,即可以一次性操作多个寄存器数据,他们利用SP栈指针来生成地址
PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈
PUSH {LR} @将 LR 进行压栈
POP {LR} @先恢复 LR
POP {R0~R3,R12} @在恢复 R0~R3,R12
出栈要从栈顶也就是当前sp指针的位置开始 PUSH 和 POP 的另外一种写法是“STMFD SP!”和“LDMFD SP!”
四、跳转指令
有多种跳转操作,比如:
①、直接使用跳转指令 B、BL、BX 等。
②、直接向 PC 寄存器里面写入数据。
B指令 最简单的跳转指令 B指令会将PC寄存器的值设置会跳转目标地址,一但执行B指令 ARM处理器就会立即跳转到制定的目标地址
start:
ldr sp,=0X80200000 @设置栈指针
b main @跳转到 main 函数
BL指令 BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用一个基本但常用的手段。
push {r0,r1} @ 保存r0,r1
cps #0x13 @ 进入svc模式,允许其他中断在此进入
bl system_irqhandler @加载c语言中断处理函数到R2寄存器中、
cps #0x12 @进入IRQ模式
pop {R0, R1} @出栈
str r0,{r1,#0x10} @ 中断执行完成,写EOIR
五、算数运算指令
六、逻辑运算指令
在嵌入式中最常用的就是加减法 逻辑运算很好理解 在汇编配置的 I.MX6ULL的外设寄存器的时候可能会用到