ARM汇编指令集详解

ARM汇编指令集详解

简介:ARM(Advanced RISC Machines)处理器凭借其低功耗、高性能的特点,广泛应用于嵌入式系统、移动设备、物联网等领域。无论是做底层驱动开发、操作系统移植,还是嵌入式系统调试,掌握 ARM 汇编语言都是必不可少的基本功。本文将系统讲解 ARM 处理器架构、寄存器组织、寻址方式、数据处理指令、分支指令、加载存储指令、批量数据传送、状态寄存器操作、协处理器指令、异常处理等核心内容,配合详细的指令格式说明和代码示例,帮助你全面掌握 ARM 汇编编程。


一、ARM 处理器架构概述

1.1 处理器架构分类

常见的处理器架构包括:51/52、ARM、x86、PPC(Power PC)、MIPS 等。ARM 采用的是 RISC(精简指令集) 架构。

RISC 与 CISC 的区别

特性 RISC(精简指令集) CISC(复杂指令集)
指令长度 所有指令长度一致 指令长度不一致
指令数量 少,只保留常用指令 多,包含复杂指令
执行周期 大多数指令一个周期 指令执行周期不等
代表 ARM、MIPS、RISC-V x86

1.2 冯诺依曼体系结构

计算机的冯诺依曼体系结构由五大部分组成:

  • 输入(Input)
  • 输出(Output)
  • 存储器(Memory)
  • 运算器(ALU)
  • 控制器(CU)

计算机的三级存储设备:Cache -> 主存储器 -> 辅助存储器。其中寄存器和 Cache 集成在 CPU 内部,Cache 是高速缓冲存储器。

1.3 ARM 工作模式

ARM 处理器主要有两个工作模式(共8种):

  • User 模式:用户模式,应用代码在此模式下运行
  • SVC 模式:超级用户模式(特权模式),CPU 启动时进入此模式

其他模式包括:FIQ、IRQ、Abort、Undefined、System、Monitor 等。

ARM 的工作状态有三个:ARM 状态、Thumb 状态、Jazelle 状态。

1.4 ARM 流水线

ARM 采用3级流水线:取指令 -> 译码 -> 执行,并行执行。在执行当前指令时,可以同时取下一条指令。

重要概念 :PC(程序计数器)指向的是正在取址的指令地址,而不是正在执行的地址。所以:

复制代码
PC - 8 = 正在执行的指令地址(ARM状态下)

不论有多少级流水线,都是按照三级流水线执行。if-else 等跳转指令会打断流水线,而三目运算符不会跳转,所以在 ARM 编程中尽量使用三目运算符代替 if-else

图片占位符

1.5 ARM 指令集版本

ARM 指令集架构经历了多个版本的发展:v1、v2、v3、v4、v5、v6、v7、v8。Cortex-A 系列之前有 37 个寄存器,Cortex-A 之后有 40 个寄存器。


二、寄存器组

ARM 处理器拥有一个丰富的寄存器组,包括通用寄存器、程序计数器、程序状态寄存器等。

2.1 通用寄存器(R0-R15)

ARM 处理器共有 16 个通用寄存器(32位):

寄存器 名称 用途
R0-R3 通用寄存器 函数调用时默认用来传参
R4-R11 通用寄存器 保存变量,函数调用时需要保护
R12 IP(Intra-Procedure) 临时暂存寄存器
R13 SP(Stack Pointer) 栈指针,指向栈顶
R14 LR(Link Register) 链接寄存器,保存函数返回地址
R15 PC(Program Counter) 程序计数器,指向正在取址的指令

重要说明

  • R0-R3 默认用来传参,调用函数时参数通过这些寄存器传递
  • SP 在代码开始时必须初始化 ,例如:LDR SP, =0x4000000
  • LR 用于保存子程序的返回地址,在调用子程序时需将 LR 压栈
  • PC 的值是当前取址地址,正在执行的指令地址 = PC - 8

2.2 程序状态寄存器(CPSR/SPSR)

ARM 有一个 CPSR (当前程序状态寄存器)和最多 5 个 SPSR(备份程序状态寄存器,每种异常模式一个)。

CPSR 的 32 位分为 4 个 8 位的域:

复制代码
[31:24] 条件标志位域(用 f 表示)
[23:16] 状态位域(用 s 表示)
[15:8]  扩展位域(用 x 表示)
[7:0]   控制位域(用 c 表示)

条件标志位

名称 说明
N 负数标志 运算结果为负数或小于时置 1
Z 零标志 运算结果为零时置 1
C 进位/借位标志 运算产生进位或借位时置 1
V 溢出标志 运算结果发生溢出时置 1

控制位

名称 说明
I IRQ 中断禁止 1=禁止, 0=允许
F FIQ 中断禁止 1=禁止, 0=允许
T Thumb 状态标志 1=Thumb 状态
M[4:0] 模式标志 指定当前处理器模式

图片占位符


三、寻址方式

ARM 汇编指令的一般格式:

复制代码
指令 {<条件码>}{S} <Rd>, <Rn>, <shift_operand>
  • <> 中的内容必须写
  • {} 中的内容可选
  • 操作数个数只能少,不能多(Rd 和 Rn 不能省略)
  • Rd:目的操作数(destination)
  • Rn:第一个源操作数(通用寄存器)
  • shift_operand:第二个操作数,可以是立即数、寄存器或移位码

ARM 的第二操作数可以是:ARM 通用寄存器、立即数、或移位码。

关于立即数:ARM 中的立即数是由一个 8 位的数左移或右移偶数位得到的,所以不是所有的数都是立即数。如果不确定某个数是否为立即数,可以使用伪指令:

asm 复制代码
LDR R0, =0xFFF    ; 0xFFF 不是立即数,但使用伪指令可以加载任意值

四、数据处理指令

4.1 MOV -- 数据传送

复制代码
MOV {<cond>}{S} <Rd>, <shift_operand>

将第二操作数(可以是立即数或寄存器)传送到目的寄存器。

asm 复制代码
MOV R0, #0         ; R0 = 0
MOV R1, R2         ; R1 = R2
MOV R0, R0         ; 无操作(NOP)
MOVS R0, #0xFFFFFFFB  ; 设置标志位,CPSR 的 N 位置1(结果为负)

注意:操作数最多只能有两个。

4.2 MVN -- 取反传送

复制代码
MVN {<cond>}{S} <Rd>, <shift_operand>

将第二操作数取反后传送到目的寄存器。

asm 复制代码
MVN R0, #0         ; R0 = 0xFFFFFFFF(取反)
MVN R0, #0x0F      ; R0 = 0xFFFFFFF0

4.3 ADD / SUB -- 加法 / 减法

复制代码
ADD {<cond>}{S} <Rd>, <Rn>, <shift_operand>
SUB {<cond>}{S} <Rd>, <Rn>, <shift_operand>
asm 复制代码
ADD R0, R1, R2     ; R0 = R1 + R2
ADD R0, R1, #5     ; R0 = R1 + 5
SUB R0, R1, R2     ; R0 = R1 - R2
SUB R0, R1, #10    ; R0 = R1 - 10

4.4 ADC / SBC / RSC -- 带进位的运算

复制代码
ADC {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 加法 + 进位标志C
SBC {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 减法 - 进位标志C
RSC {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 反向减法

ADC 和 SBC 要加上或减去 CPSR 中的 C 条件标志位,常用于实现 64 位运算。

asm 复制代码
; 64 位加法:R1:R0 + R3:R2 -> R1:R0
ADDS R0, R0, R2    ; 低32位加法,影响进位标志
ADC  R1, R1, R3    ; 高32位加法 + 进位

RSC 是反向相减,可以实现常数减寄存器的值:Rd = shift_operand - Rn

4.5 AND / ORR / EOR / BIC -- 逻辑运算

复制代码
AND {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 逻辑与
ORR {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 逻辑或
EOR {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 逻辑异或
BIC {<cond>}{S} <Rd>, <Rn>, <shift_operand>  ; 位清除
asm 复制代码
AND R0, R0, #0xFF     ; R0 = R0 & 0xFF(取低8位)
ORR R0, R0, #0x0F     ; R0 = R0 | 0x0F(置低4位)
EOR R0, R0, R0        ; R0 = 0(自身异或清零)
BIC R0, R0, #0x0F     ; 将R0的低4位清零

BIC 指令详解:将第二个操作数取反后与第一个操作数相与,实现指定位清零。

asm 复制代码
BIC R0, R0, #0x1011   ; 将 0x1011 取反得 0xFFFFEFFE,再与 R0 相与
                      ; 效果:清除 R0 的 bit0, bit1, bit8, bit12

EOR 的常见用途

  • 两个相同的数异或可以清零变量
  • 与 1 异或取反码
  • 与 0 异或保持不变
  • 交换两个值不需要中间变量

4.6 MUL / MLA -- 乘法

复制代码
MUL {<cond>}{S} <Rd>, <Rn>, <Rm>           ; Rd = Rn * Rm
MLA {<cond>}{S} <Rd>, <Rn>, <Rm>, <Rs>     ; Rd = Rn * Rm + Rs

以上两个只保存低 32 位的值。

64 位乘法指令

指令 说明
UMULL 无符号长整型乘法,结果64位存入 RdLo, RdHi
UMLAL 无符号长整型乘法累加
SMULL 有符号长整型乘法
SMLAL 有符号长整型乘法累加
asm 复制代码
; 格式:UMULL <RdLo>, <RdHi>, <Rm>, <Rs>
; 64位结果:RdHi:RdLo = Rm * Rs
UMULL R0, R1, R2, R3  ; R1:R0 = R2 * R3(64位无符号乘法)

4.7 比较指令(不保存结果,只影响标志位)

CMP -- 比较

复制代码
CMP {<cond>} <Rd>, <shift_operand>

执行减法但不存储结果,只更新 CPSR 的条件标志位。

asm 复制代码
CMP R0, #10      ; 比较 R0 和 10(实质是 R0 - 10)
CMP R0, R1       ; 比较 R0 和 R1

CMN -- 取负比较

复制代码
CMN {<cond>} <Rd>, <shift_operand>

与 CMP 类似,但将操作数取负后比较,用于与小负值进行比较。

TST -- 测试(按位与)

复制代码
TST {<cond>} <Rd>, <shift_operand>

两个操作数相与,不保存结果,只更新标志位。常用于测试某个位是否被置位。

asm 复制代码
; 测试 R0 的 bit0 是否为 1
MOV R0, #0xFFFFFFFC
TST R0, #0x1
; 0xFFFFFFFC & 0x00000001 = 0
; CPSR 的 Z 标志位置 1(结果为零)

TEQ -- 测试等价(按位异或)

复制代码
TEQ {<cond>} <Rd>, <shift_operand>

两个操作数异或,不保存结果,只更新标志位。可用于判断两个值是否相等,且不影响进位标志。

比较指令的特点:这些指令不需要 S 后缀就会更新标志位。

4.8 条件码

所有 ARM 指令都可以附加条件码,根据 CPSR 的标志位决定是否执行:

条件码 后缀 含义 标志位状态
0000 EQ 等于 Z=1
0001 NE 不等于 Z=0
0010 CS/HS 进位设置/无符号高于等于 C=1
0011 CC/LO 进位清除/无符号低于 C=0
0100 MI 负数 N=1
0101 PL 正数或零 N=0
0110 VS 溢出设置 V=1
0111 VC 溢出清除 V=0
1000 HI 无符号高于 C=1 且 Z=0
1001 LS 无符号低于或等于 C=0 或 Z=1
1010 GE 有符号大于等于 N=V
1011 LT 有符号小于 N!=V
1100 GT 有符号大于 Z=0 且 N=V
1101 LE 有符号小于等于 Z=1 或 N!=V
1110 AL 总是执行 无条件(默认)
asm 复制代码
MOVEQ R0, #1       ; 如果相等则 R0 = 1
MOVNE R0, #0       ; 如果不相等则 R0 = 0
CMP   R0, #10
ADDGT R1, R1, #1   ; 如果 R0 > 10,则 R1 = R1 + 1

五、分支指令

5.1 B -- 跳转指令

复制代码
B {<cond>} <地址>

最简单的分支指令,处理器立即跳转到给定地址继续执行。存储在分支指令中的实际值是相对于当前 PC 的偏移量,不是绝对地址,由汇编器计算。

限制:B 指令只能跳转 -32MB 到 +32MB 的范围。

asm 复制代码
B   label        ; 无条件跳转
BEQ equal_label  ; 相等时跳转
BNE not_equal    ; 不相等时跳转

5.2 BL -- 带链接的跳转

复制代码
BL {<cond>} <地址>

在跳转之前,将当前 PC 的值(下一条指令地址)保存到 R14(LR) 中。可以通过将 R14 装载回 R15 来返回。

asm 复制代码
BL  subroutine    ; 调用子程序,LR = 返回地址
; ...
subroutine:
    ; 子程序代码
    MOV PC, LR    ; 返回调用处

BL 是实现子程序调用的基本但强大的机制。

5.3 BX -- 跳转并切换状态

复制代码
BX {<cond>} <Rm>

跳转到 Rm 指定的地址,并将 Rm 的 bit[0] 复制到 CPSR 的 T 标志位,实现 ARM/Thumb 状态切换。Rm 的 [31:1] 位送入 PC。

asm 复制代码
BX R0    ; 跳转到 R0 指定的地址,根据 bit[0] 切换状态

5.4 BLX -- 带状态切换的链接跳转

结合了 BL 和 BX 的功能:保存返回地址的同时切换处理器状态。

5.5 长跳转实现

B/BL 只能跳转 -32MB ~ +32MB 范围,要实现长跳转需要直接修改 PC 值:

asm 复制代码
MOV PC, #0x12345678    ; 直接设置 PC 值实现长跳转

六、加载/存储指令(Load/Store)

Load/Store 指令实现 ARM 寄存器和存储器之间的数据传输,主要有三类:

6.1 单寄存器 Load/Store

传输单项数据,可以是字节、半字或字类型。

LDR -- 加载数据

复制代码
LDR {<cond>} <Rd>, <地址>
asm 复制代码
LDR R1, [R0]          ; 将 R0 指向的内存数据加载到 R1
LDR R1, [R0, #4]      ; 将 R0+4 地址的数据加载到 R1
LDR R1, [R0, R2]      ; 将 R0+R2 地址的数据加载到 R1
LDR R1, [R0, R2, LSL #2]  ; 将 R0 + R2*4 地址的数据加载到 R1
LDR R0, =0xFFF        ; 伪指令,加载任意常量

STR -- 存储数据

复制代码
STR {<cond>} <Rd>, <地址>
asm 复制代码
STR R1, [R0]          ; 将 R1 的内容存储到 R0 指向的内存地址
STR R1, [R0, #4]      ; 将 R1 存储到 R0+4 地址

变体指令

指令 说明
LDRB 加载一个字节(8位)
LDRH 加载一个半字(16位)
LDRBT 在用户模式下加载一个字节
STRB 存储一个字节
STRH 存储一个半字

寻址方式详解

asm 复制代码
; 偏移寻址
LDR R0, [R1]           ; 零偏移
LDR R0, [R1, #4]       ; 立即数偏移
LDR R0, [R1, R2]       ; 寄存器偏移
LDR R0, [R1, R2, LSL #2]  ; 寄存器偏移 + 移位

; 前索引寻址(先更新基址再访问)
LDR R0, [R1, #4]!      ; R1 = R1 + 4, 然后加载

; 后索引寻址(先访问再更新基址)
LDR R0, [R1], #4       ; 先加载 R1 指向的数据, 然后 R1 = R1 + 4

6.2 多寄存器 Load/Store(批量数据传送)

可以一次传送内存区域上的一块数据,非常适合用于现场保护和恢复。

复制代码
LDM {<cond>}<模式> Rn{!}, <寄存器列表>{^}
STM {<cond>}<模式> Rn{!}, <寄存器列表>{^}

8 种模式(前 4 种用于数据块传输,后 4 种用于堆栈操作):

模式 说明 用途
IA 每次传送后地址加 4 数据块传输
IB 每次传送前地址加 4 数据块传输
DA 每次传送后地址减 4 数据块传输
DB 每次传送前地址减 4 数据块传输
FD 满递减堆栈 堆栈操作
FA 满递增堆栈 堆栈操作
ED 空递减堆栈 堆栈操作
EA 空递增堆栈 堆栈操作
asm 复制代码
; 加载数据块
LDMIA R1!, {R2-R9}    ; 加载 R1 指向地址上的多字数据到 R2~R9,R1 值更新

; 堆栈操作(保护/恢复现场)
STMFD SP!, {R3-R7, LR}    ; 保护现场(压栈)
LDMFD SP!, {R3-R7, LR}    ; 恢复现场(出栈)
; 等价于:STMFD SP!, {R3-R7, LR} / LDMFD SP!, {R3-R7, PC}

压栈和出栈的本质:压栈是将寄存器的数据存储到内存,出栈是将内存的数据加载到寄存器。

6.3 单寄存器交换指令(SWP)

复制代码
SWP {<cond>} <Rd>, <Rm>, [<Rn>]

执行过程:

  1. 将内存地址 [Rn] 中的数据加载到 Rd
  2. 将 Rm 中的数据存储到内存地址 [Rn]

如果 Rd 和 Rm 为同一个寄存器,则实现了寄存器和内存的数据交换。

asm 复制代码
SWP R0, R1, [R2]     ; 将 [R2] 的数据加载到 R0,将 R1 存储到 [R2]
SWP R0, R0, [R1]     ; R0 与 [R1] 交换数据
SWPB R0, R1, [R2]    ; 字节交换

七、状态寄存器操作指令

7.1 MRS -- 从状态寄存器到通用寄存器

复制代码
MRS <Rd>, CPSR     ; 将 CPSR 的值读入 Rd
MRS <Rd>, SPSR     ; 将 SPSR 的值读入 Rd

7.2 MSR -- 从通用寄存器到状态寄存器

复制代码
MSR CPSR, <Rd>     ; 将 Rd 的值写入 CPSR
MSR SPSR, <Rd>     ; 将 Rd 的值写入 SPSR

CPSR 的 32 位分为 4 个域,可以单独修改某个域:

asm 复制代码
MSR CPSR_c, #0x03    ; 只修改控制位域 [7:0]
MSR CPSR_f, R0       ; 只修改条件标志位域 [31:24]
MSR CPSR_cxsf, R0    ; 修改所有域

域标识

  • c:控制位域 [7:0]
  • x:扩展位域 [15:8]
  • s:状态位域 [23:16]
  • f:条件标志位域 [31:24]

7.3 使能/禁止中断

asm 复制代码
; 禁止 IRQ 中断
MRS R0, CPSR
ORR R0, R0, #0x80       ; 设置 I 位(bit7)
MSR CPSR_c, R0

; 使能 IRQ 中断
MRS R0, CPSR
BIC R0, R0, #0x80       ; 清除 I 位
MSR CPSR_c, R0

八、协处理器指令

ARM 处理器支持协处理器(如 MMU、FPU 等),通过以下指令与协处理器交互:

指令 说明
CDP 协处理器数据操作
LDC 从存储器加载协处理器寄存器
STC 将协处理器寄存器存储到存储器
MCR 从 ARM 寄存器传数据到协处理器寄存器
MRC 从协处理器寄存器传数据到 ARM 寄存器
asm 复制代码
MCR p15, 0, R0, c1, c0, 0   ; 将 R0 的值传送到协处理器 p15 的 c1 寄存器
MRC p15, 0, R0, c0, c0, 0   ; 从协处理器 p15 的 c0 寄存器读取到 R0

协处理器指令在系统级编程(如配置 MMU、Cache、TLB 等)中非常重要。


九、异常处理

9.1 异常产生指令

复制代码
SWI {<cond>} <immed_24>    ; 软件中断,产生软中断,处理器进入 SVC 模式
BKPT <immed_16>            ; 断点中断指令,产生软件断点
asm 复制代码
SWI 0x123456    ; 产生软中断,中断号为 0x123456
BKPT 0x1234     ; 产生断点中断

9.2 ARM 异常处理流程

ARM 在遇到异常时,会自动执行以下操作:

  1. 将下一条指令的地址保存到相应模式的 LR 中
  2. 将 CPSR 的值保存到相应模式的 SPSR 中
  3. 修改 CPSR 的模式位,切换到对应的异常模式
  4. 将 PC 设置为特定的异常向量地址

异常向量表

异常类型 向量地址 入口模式
复位 0x00000000 SVC
未定义指令 0x00000004 Undefined
软中断(SWI) 0x00000008 SVC
指令预取中止 0x0000000C Abort
数据访问中止 0x00000010 Abort
保留 0x00000014 -
IRQ(普通中断) 0x00000018 IRQ
FIQ(快速中断) 0x0000001C FIQ

9.3 异常返回

异常处理完成后,需要恢复现场并返回:

asm 复制代码
; 保护现场
STMFD SP!, {R0-R7, LR}

; 异常处理代码
; ...

; 恢复现场并返回
LDMFD SP!, {R0-R7, PC}^    ; ^ 表示同时恢复 CPSR

MOVS PC, LR 也可以实现返回:将 LR 的值赋给 PC,并将 SPSR 的值恢复到 CPSR,切换回原来的模式。

9.4 函数编写规范

在 ARM 中正确封装一个函数,必须进行现场保护恢复

asm 复制代码
my_function:
    STMFD SP!, {R3-R7, LR}     ; 保护现场(保存用到的寄存器和返回地址)

    ; 函数体
    ; ...

    LDMFD SP!, {R3-R7, PC}     ; 恢复现场并返回

十、ARM 汇编编程要点

10.1 启动代码

在 ARM 编程中,一定要用汇编代码做初始化启动代码,包括:

  1. 初始化向量表
  2. 初始化栈指针(SP)
  3. 初始化内存控制器
  4. 跳转到 C 语言主函数
asm 复制代码
; 典型的启动代码框架
    LDR SP, =0x4000000       ; 初始化栈指针

    ; 跳转到 main 函数
    BL  main

    ; 死循环
halt:
    B   halt

10.2 ARM 指令机器码格式

ARM 指令固定为 32 位,其机器码格式如下:

复制代码
|31|30|29|28|27-25|24|23-22|21|20|19-16|15-12|11-0|
|  cond   | 001 |  | opcode |S |  Rn  |  Rd  |shift_operand |
  • 31:28\]:条件码

  • 24:21\]:操作码

  • 19:16\]:第一操作数寄存器 Rn

  • 11:0\]:第二操作数(立即数/移位码)

伪指令不是真正的 ARM 指令,由汇编器处理:

asm 复制代码
LDR R0, =0xFFFF0000   ; 加载任意32位常量(不是立即数也能用)
LDR SP, =0x4000000    ; 加载地址常量

10.4 PWM 注意事项

PWM 的手动装载优先级高于自动装载。要使用自动装载时,必须先关闭手动装载。


十一、完整汇编程序示例

以下是一个完整的 ARM 汇编程序示例,演示了基本的程序结构:

asm 复制代码
; ==============================
; ARM 汇编程序示例
; 功能:简单的算术运算和子程序调用
; ==============================

    AREA example, CODE, READONLY
    ENTRY

start
    ; 初始化栈指针
    LDR SP, =0x4000000

    ; 基本算术运算
    MOV R0, #10          ; R0 = 10
    MOV R1, #20          ; R1 = 20
    ADD R2, R0, R1       ; R2 = R0 + R1 = 30
    SUB R3, R1, R0       ; R3 = R1 - R0 = 10

    ; 逻辑运算
    AND R4, R0, #0xFF    ; R4 = R0 & 0xFF
    ORR R5, R0, #0x0F    ; R5 = R0 | 0x0F

    ; 调用子程序
    MOV R0, #5
    MOV R1, #3
    BL  multiply         ; 调用乘法子程序

    ; 条件执行
    CMP R0, #10
    MOVEQ R0, #100       ; 如果相等则 R0 = 100
    MOVNE R0, #200       ; 如果不等则 R0 = 200

    ; 死循环
loop
    B loop

; ==============================
; 子程序:乘法(简单实现)
; 输入:R0 = 被乘数, R1 = 乘数
; 输出:R2 = 积
; ==============================
multiply
    STMFD SP!, {R3, LR}  ; 保护现场

    MOV R2, #0           ; 结果清零
    MOV R3, #0           ; 计数器清零

mul_loop
    CMP R3, R1           ; 计数器 < 乘数?
    BGE mul_done
    ADD R2, R2, R0       ; 累加被乘数
    ADD R3, R3, #1       ; 计数器 +1
    B   mul_loop

mul_done
    LDMFD SP!, {R3, PC}  ; 恢复现场并返回

    END

十二、指令速查表

数据处理指令

指令 功能 示例
MOV 数据传送 MOV R0, #10
MVN 取反传送 MVN R0, #0
ADD 加法 ADD R0, R1, R2
SUB 减法 SUB R0, R1, R2
RSB 反向减法 RSB R0, R1, #0
ADC 带进位加法 ADC R0, R1, R2
SBC 带借位减法 SBC R0, R1, R2
AND 逻辑与 AND R0, R0, #0xFF
ORR 逻辑或 ORR R0, R0, #0x0F
EOR 逻辑异或 EOR R0, R0, R0
BIC 位清除 BIC R0, R0, #0x0F
MUL 乘法 MUL R0, R1, R2
MLA 乘加 MLA R0, R1, R2, R3
CMP 比较 CMP R0, #10
CMN 取负比较 CMN R0, #1
TST 位测试 TST R0, #0x01
TEQ 相等测试 TEQ R0, R1

分支指令

指令 功能 示例
B 跳转 B label
BL 带链接跳转 BL subroutine
BX 跳转并切换状态 BX R0
BLX 带链接切换跳转 BLX R0

加载/存储指令

指令 功能 示例
LDR 加载字 LDR R0, [R1]
STR 存储字 STR R0, [R1]
LDRB 加载字节 LDRB R0, [R1]
STRB 存储字节 STRB R0, [R1]
LDRH 加载半字 LDRH R0, [R1]
LDM 批量加载 LDMIA R0!, {R1-R5}
STM 批量存储 STMFD SP!, {R1-R5, LR}
SWP 数据交换 SWP R0, R1, [R2]

总结

本文全面系统地介绍了 ARM 汇编指令集的各个方面:

  1. 架构基础:了解了 ARM 处理器的 RISC 架构特点、工作模式、流水线机制。理解 PC 与实际执行地址的关系(PC - 8),以及流水线对程序优化的影响。
  2. 寄存器组织:掌握了 R0-R15 的用途分工、CPSR/SPSR 的标志位和控制位含义。理解了函数调用时 R0-R3 传参、LR 保存返回地址、SP 栈指针管理的关键作用。
  3. 数据处理指令:学习了 MOV/MVN、ADD/SUB/ADC/SBC/RSC、AND/ORR/EOR/BIC、MUL/MLA 等运算指令,以及 CMP/CMN/TST/TEQ 等测试指令。
  4. 分支与控制:掌握了 B/BL/BX/BLX 四种跳转指令,理解了条件码的使用和长跳转的实现方法。
  5. 存储器访问:学习了 LDR/STR 单寄存器操作、LDM/STM 批量传送的 8 种模式、SWP 交换指令,理解了压栈/出栈保护现场的原理。
  6. 状态寄存器操作:掌握了 MRS/MSR 指令的使用,以及 CPSR 各域的独立操作方法。
  7. 异常处理:理解了 ARM 的异常向量表、异常处理流程、现场保护与恢复机制。

ARM 汇编是嵌入式开发的底层基石,熟练掌握后,将为 Bootloader 开发、驱动编程、操作系统移植、性能优化等高级主题奠定坚实基础。


原始笔记来源:frasight/ARM笔记.asm

相关推荐
iCxhust2 小时前
微机原理实践教程(汇编篇)---A002流水灯
汇编·单片机·嵌入式硬件·51单片机·微机原理
浩浩测试一下2 小时前
栈帧 抬栈与平栈 (逆向分析)
汇编·windows api·堆栈·windows编程·windows 开发
陈eaten2 小时前
win11下nasm编写汇编及链接方案
汇编·链接·nasm·gcc·golink
iCxhust3 小时前
【无标题】8086/8088裸机对于学习微机原理的重要意义
汇编·单片机·嵌入式硬件·嵌入式·微机原理
山后太阳16 小时前
Keil5(MDK-ARM)完整下载安装教程+入门教程:从零搭建STM32开发环境
arm开发·stm32·嵌入式硬件
zz_lzh16 小时前
arm版AI牛马:armbian(rk3588)设备部署openclaw
arm开发·人工智能·arm
lanxiao88882 天前
F1C100S 内核
arm开发
杰杰桀桀桀2 天前
基于stm32ARM库函数的IIR二阶巴特沃斯低通滤波器--附完整代码
arm开发·stm32·嵌入式硬件·数字滤波器·巴特沃斯低通滤波
TBrL7UtdTELTTdut4BAL2 天前
ARM Cortex-A53 (无AES)平台加密网络转发性能测试与对比分析
arm开发·集成测试