1 处理器内部数据传输指令
MSR & MRS
用于在状态寄存器和通用寄存器之间传送数据
MRS: 状态寄存器到通用寄存器的传送指令。({R0-R12} <== CPSR,SPSR)
MRS R0, CPSR @ 将特殊寄存器 CPSR 里面的数据传递给 R0,即R0=CPSR
MSR: 通用寄存器到状态寄存器的传送指令。 MRS:(CPSR,SPSR==>{R0-R12})
MSR CPSR, R0 @ 将 R0 中的数据复制到 CPSR 中,即 CPSR=R0
MOV
MOV 指令用于将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄 存器里面,使用示例如下:
MOV R0, R1 @ 将寄存器 R1 中的数据传递给 R0,即 R0=R1
MOV R0, #0X12 @ 将立即数 0X12 传递给 R0 寄存器,即 R0=0X12
2 存储器访问指令
ARM 不能直接访问存储器,比如 RAM 中的数据,一般先将要配置的值写入到 Rx(x=0~12)寄存器中,然后借助存储器访问指令将 Rx 中的数据写入到寄存器中。
指令 | 描述 |
---|
LDR Rd, [Rn , #offset] | 从存储器 Rn+offset 的位置读取数据存放到 Rd 中 | STR Rd, [Rn, #offset] | 将 Rd 中的数据写入到存储器中的 Rn+offset 位置 |
LDR 指令
LDR 主要用于从存储加载数据到寄存器 Rx 中, LDR 也可以将一个立即数加载到寄存器 Rx中, LDR 加载立即数的时候要使用“=”,而不是“#”。在嵌入式开发中, LDR 最常用的就是读取 CPU 的寄存器值。
LDR R0, =0X0209C004 @ 将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, [R0] @ 读取地址 0X0209C004 中的数据到 R1 寄存器中
上述代码就是读取寄存器中的值,读取到的寄存器值保存在 R1 寄存器中, 上面代码中 offset 是 0,也就是没有用到 offset。
STR 指令
LDR 是从存储器读取数据, STR 就是将数据写入到存储器中
LDR R0, =0X0209C004 @ 将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, =0X20000002 @ R1 保存要写入到寄存器的值,即R1=0X20000002
STR R1, [R0] @ 将 R1 中的值写入到 R0 中所保存的地址中
LDR 和 STR 都是按照字进行读取和写入的,也就是操作的 32 位数据,如果要按照字节、半字进行操作的话可以在指令“LDR”后面加上 B 或 H,比如按字节操作的指令就是 LDRB 和 STRB,按半字操作的指令就是 LDRH 和 STRH。
3 压栈和出栈指令
我们通常会在 A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。要想再跳回 A 函数以后代码能够接着正常运行,那就必须在跳到 B 函数之前将当前处理器状态保存起来(就是保存 R0-R15 这些寄存器值),当 B 函数执行完成以后再用前面保存的寄存器值恢复R0-R15 即可。保存 R0-R15 寄存器的操作就叫做现场保护,恢复 R0~R15 寄存器的操作就叫做恢复现场。在进行现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。
指令 | 描述 |
---|
POP < reg list> | 出栈 | PUSH < reg list> | 入栈 |
4 跳转指令
指令 | 描述 |
---|
B < LABEL > | 跳转到 label | BX < Rm > | 间接跳转,跳转到存放于 Rm 中的地址处,并且切换指令集 | BL < LABEL > | 跳转到标号地址,并将返回地址保存在 LR 中 | BLX < Rm > | 结合 BX 和 BL 的特点,跳转到 Rm 指定的地址,并将返回地址保存在 LR 中,切换指令集 |
B指令
这是最简单的跳转指令, B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指 令, ARM 处理器就会立即跳转到指定的目标地址。如果要调用的函数不会再返回到原来的执行 处,那就可以用 B 指令。
BL指令
BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用一个基本但常用的手段。
5 算术运算指令
指令 | 计算公式 |
---|
ADD Rd, Rn, Rm / #immed | Rd = Rn + Rm / #immed | ADC Rd, Rn, Rm / #immed (带进位) | Rd = Rn + Rm / #immed + 进位 | SUB Rd, Rn, Rm / #immed | Rd = Rn – Rm / #immed | SUB Rd, #immed | Rd = Rd - #immed | SUB Rd, Rn, #immed | Rd = Rn - #immed | SBC Rd, Rn, Rm / #immed (带借位) | Rd = Rn - Rm / #immed - 借位 | MUL Rd, Rn, Rm | Rd = Rn * Rm | UDIV Rd, Rn, Rm (无符号) | Rd = Rn / Rm | SDIV Rd, Rn, Rm (有符号) | Rd = Rn / Rm |
6 逻辑运算指令
AND Rd, Rn, Rm Rd = Rn & Rm
ORR Rd, Rn, Rm Rd = Rn | Rm
BIC Rd, Rn, Rm Rd = Rn & (~Rm)
ORN Rd, Rn, Rm Rd = Rn | (~Rm)
EOR Rd, Rn, Rm Rd = Rn ^ Rm
|