ARM 常用汇编指令

ARM 常用汇编指令

1. 数据传输指令
使用处理器做的最多事情就是在处理器内部来回的传递数据,常见的操作有:

  • 将数据从一个寄存器传递到另外一个寄存器。
  • 将数据从一个寄存器传递到特殊寄存器,如 CPSR 和 SPSR 寄存器。
  • 将立即数传递到寄存器。

数据传输常用的指令有三个:MOV、MRS 和 MSR

MOV 指令用于将数据从一个寄存器拷贝到另外一个寄存器,或者将一个立即数传递到寄存器里面

MOV R0 R1 @将 R1 里面的数据复制到 R0 中

MRS 指令用于将特殊寄存器(如 CPSR 和 SPSR)中的数据传递给通用寄存器,要读取特殊寄存器的数据只能使用 MRS 指令

MRS R0, CPSR @将特殊寄存器 CPSR 里面的数据传递给 R0,即 R0=CPSR

MSR 指令用来将普通寄存器的数据传递给特殊寄存器,也就是写特殊寄存器,写特殊寄存器只能使用 MSR

MSR CPSR, R0 @将 R0 中的数据复制到 CPSR 中,即 CPSR=R0

2. 存储器访问指令
ARM 不能直接访问存储器,比如 RAM 中的数据。常用的存储器访问指令有两种:LDR 和 STR。
LDR 主要用于从存储加载数据到寄存器 Rx 中,LDR 也可以将一个立即数加载到寄存器 Rx中,LDR 加载立即数的时候要使用“=”,而不是“#”。在嵌入式开发中,LDR 最常用的就是读取 CPU 的寄存器值:

@LDR Rd, [Rn , #offset] 从存储器 Rn+offset 的位置读取数据存放到 Rd 中

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, [R0] @读取地址 0X0209C004 中的数据到 R1 寄存器中

STR 是将数据写入到存储器中:

@STR Rd, [Rn, #offset] 将 Rd 中的数据写入到存储器中的 Rn+offset 位置。

LDR R0, =0X0209C004 @将寄存器地址 0X0209C004 加载到 R0 中,即 R0=0X0209C004
LDR R1, =0X20000002 @R1 保存要写入到寄存器的值,即 R1=0X20000002
STR R1, [R0] @将 R1 中的值写入到 R0 中所保存的地址中

3. 压栈和出栈指令
通常在A 函数中调用 B 函数,当 B 函数执行完以后再回到 A 函数继续执行。
此过程必须先保存A函数中当前的数据(现场保护),等B函数执行结束后再进行恢复A函数数据(恢复现场)。在进行现场保护的时候需要进行压栈(入栈)操作,恢复现场就要进行出栈操作。压栈的指令为 PUSH,出栈的指令为 POP,PUSH 和 POP 是一种多存储和多加载指令,即可以一次操作多个寄存器数据,他们利用当前的栈指针 SP 来生成地址。注意:处理器的堆栈是向下增长的
PUSH 另一种写法为 STMFD SP!

@PUSH <reg list> 将寄存器列表存入栈中。

PUSH {R0~R3, R12} @将 R0~R3 和 R12 压栈
PUSH {LR} @将 LR 进行压栈

STMFD SP!,{R0~R3, R12} @R0~R3,R12 入栈

POP 另一种写法为 LDMFD SP!

@POP <reg list> 从栈中恢复寄存器列表。

POP {LR} @先恢复 LR 
POP {R0~R3,R12} @在恢复 R0~R3,R12

LDMFD SP!, {R0~R3, R12} @再恢复 R0~R3, R12

STMFD 可以分为两部分:
STM 和 FD,同理,LDMFD 也可以分为 LDM 和 FD。看到 STM和 LDM 有没有觉得似曾相识,前面讲了 LDR 和 STR,这两个是数据加载和存储指令,但是每次只能读写存储器中的一个数据。STM 和 LDM 就是多存储和多加载,可以连续的读写存储器中的多个连续数据
FD 是 Full Descending 的缩写,即满递减的意思。

4. 跳转指令
有多种跳转操作,比如:使用跳转指令 B、BL、BX 等。直接向 PC 寄存器里面写入数据。

B 指令会将 PC 寄存器的值设置为跳转目标地址, 一旦执行 B 指
令,ARM 处理器就会立即跳转到指定的目标地址

@B <label>
@跳转到 label,如果跳转范围超过了+/-2KB,可以指定 B.W <label>使用 32 位版本的跳转指令

_start: 

ldr sp,=0X80200000 @设置栈指针
b main @跳转到 main 函数

BL 指令相比 B 指令,在跳转之前会在寄存器 LR(R14)中保存当前 PC 寄存器值,所以可以通过将 LR 寄存器中的值重新加载到 PC 中来继续从跳转之前的代码处运行,这是子程序调用一个基本但常用的手段。

@BL <label> 跳转到标号地址,并将返回地址保存在 LR 中。 
push {r0, r1} @保存 r0,r1
cps #0x13 @进入 SVC 模式,允许其他中断再次进去

bl system_irqhandler @加载 C 语言中断处理函数到 r2 寄存器中

cps #0x12 @进入 IRQ 模式
pop {r0, r1} 
str r0, [r1, #0X10] @中断执行完成,写 EOIR

5. 算术运算指令

指令 计算公式 描述
ADD Rd, Rn, Rm(或#immed) Rd = Rn + Rm(或#immed) 加法运算,指令为 ADD
ADC Rd, Rn, Rm(或#immed) Rd = Rn + Rm(或#immed) + 进位 带进位加法运算,指令为 ADC
SUB Rd, Rn, Rm(或#immed) Rd = Rn - Rm(或#immed) 减法运算,指令为 SUB
SBC Rd, Rn, Rm(或#immed) Rd = Rn - Rm(或#immed) - 借位 带借位减法运算,指令为 SBC
MUL Rd, Rn, Rm Rd = Rn * Rm 乘法运算32位,指令为 MUL
UDIV Rd, Rn, Rm Rd = Rn / Rm 无符号除法运算,指令为 UDIV
SDIV Rd, Rn, Rm Rd = Rn / Rm 有符号除法运算,指令为 SDIV

Rn Rm Rd 为寄存器 #immed为立即数,其中最常会用的就是加减指令,乘除基本用不到

6. 逻辑运算指令

指令 计算公式 描述
AND Rd, Rn Rd = Rd & Rn
AND Rd, Rn,#immed Rd = Rn & #immed 按位与,指令为 AND
AND Rd, Rn,Rm Rd = Rn & Rm
ORR Rd, Rn Rd = Rd | Rn
ORR Rd, Rn,#immed Rd = Rn | #immed 按位或,指令为 ORR
ORR Rd, Rn,Rm Rd = Rn | Rm
BIC Rd, Rn Rd = Rd & (~Rn)
BIC Rd, Rn,#immed Rd = Rn & (~#immed) 位清除,指令为 BIC
BIC Rd, Rn,Rm Rd = Rn & (~Rm)
ORN Rd, Rn,#immed Rd = Rn | (~#immed) 按位或非,指令为 ORN
ORN Rd, Rn,Rm Rd = Rn | (~Rm)
EOR Rd, Rn Rd = Rd ^ Rn
EOR Rd, Rn,#immed Rd = Rn ^ #immed 按位异或,指令为 EOR
EOR Rd, Rn,Rm Rd = Rn ^ Rm

若需了解汇编语法 请点击汇编基本语法

你可能感兴趣的:(Linux,单片机,linux,c语言,arm开发)