微处理器原理与应用篇---ARM常见汇编指令

ARM 汇编常用指令详解与应用实例

ARM 汇编语言是嵌入式系统开发的基础,以下详细介绍常用指令的功能、语法及应用场景,并结合实例说明。

|---------|-----------------------------------------------------------|------------------------------------------------------------------------------------------------------------------------|
| 数据传输指令 | MOV Rd, RnMOV Rd, #imm | 将寄存器Rn中的数据或立即数imm传送到寄存器Rd中 |
| | MRS Rd, CPSRMRS Rd, SPSR | 将程序状态寄存器(CPSRSPSR)中的数据传送到通用寄存器Rd中 |
| | MSR CPSR, RnMSR SPSR, Rn | 将通用寄存器Rn中的数据传送到程序状态寄存器(CPSRSPSR)中 |
| 存储器访问指令 | LDR Rd, [Rn]LDR Rd, [Rn, #offset]LDR Rd, [Rn, Rm] | 从内存中加载数据到寄存器。[Rn]表示以Rn的值为地址的内存单元;[Rn, #offset]表示以Rn的值加上偏移量offset为地址的内存单元;[Rn, Rm]表示以Rn的值加上Rm的值为地址的内存单元 |
| | STR Rd, [Rn]STR Rd, [Rn, #offset]STR Rd, [Rn, Rm] | 将寄存器Rd中的数据存储到内存中。存储地址的计算方式与LDR指令类似 |
| 堆栈操作指令 | PUSH {R0, R1,..., Rn} | 将寄存器R0R1、...、Rn中的数据依次压入栈中 |
| | POP {R0, R1,..., Rn} | 从栈中弹出数据,并分别存储到寄存器RnRn - 1、...、R0中 |
| 跳转指令 | B label | 无条件跳转到标号label处执行 |
| | BL label | 跳转到标号label处执行子程序,同时将当前的PC值保存到R14LR)寄存器中 |
| | BX Rn | 跳转到寄存器Rn指定的地址执行,目标地址处的指令既可以是ARM指令,也可以是Thumb指令 |
| | BEQ label | 当Z标志位为1(即相等)时,跳转到标号label处执行 |
| | BNE label | 当Z标志位为0(即不相等)时,跳转到标号label处执行 |
| | BLT label | 当N标志位为1V标志位为0(即有符号数小于)时,跳转到标号label处执行 |
| | BGT label | 当Z标志位为0N标志位等于V标志位(即有符号数大于)时,跳转到标号label处执行 |
| 算术运算指令 | ADD Rd, Rn, Operand2 | 将寄存器Rn的值与操作数Operand2相加,结果存储在寄存器Rd中 |
| | SUB Rd, Rn, Operand2 | 将寄存器Rn的值减去操作数Operand2,结果存储在寄存器Rd中 |
| | MUL Rd, Rn, Operand2 | 将寄存器Rn的值与操作数Operand2相乘,结果存储在寄存器Rd中 |
| | SDIV Rd, Rn, Operand2 | 将寄存器Rn中的有符号数除以操作数Operand2,结果存储在寄存器Rd中 |
| 逻辑运算指令 | AND Rd, Rn, Operand2 | 对寄存器Rn的值和操作数Operand2进行按位与操作,结果存储在寄存器Rd中 |
| | ORR Rd, Rn, Operand2 | 对寄存器Rn的值和操作数Operand2进行按位或操作,结果存储在寄存器Rd中 |
| | EOR Rd, Rn, Operand2 | 对寄存器Rn的值和操作数Operand2进行按位异或操作,结果存储在寄存器Rd中 |
| | MVN Rd, Rn | 对寄存器Rn的值进行按位取反操作,结果存储在寄存器Rd中 |

1. LDR(Load Register)

功能 :从内存加载数据到寄存器。
语法

复制代码
LDR Rd, [Rn, #offset]   ; Rd = *(Rn + offset),基址+偏移寻址
LDR Rd, label          ; Rd = 标签地址处的值,PC相对寻址

实例

复制代码
LDR R0, =0x40000000    ; R0加载立即数地址(伪指令)
LDR R1, [R0]           ; 从地址0x40000000加载数据到R1
LDR R2, [R0, #4]       ; 从地址0x40000004加载数据到R2(偏移4字节)

应用:读取外设寄存器值(如 GPIO 状态)、加载常量数据。

2. LDRB(Load Register Byte)

功能 :从内存加载单字节数据到寄存器,高 24 位自动零扩展。
语法

复制代码
LDRB Rd, [Rn]          ; Rd = *(Rn)(8位),零扩展为32位

实例

复制代码
LDR R0, =0x40000000    
LDRB R1, [R0]          ; 从地址0x40000000加载1字节到R1低8位,高24位补0

应用:读取字符数据、访问 8 位寄存器(如 ADC 采样值)。

3. AND(Logical AND)

功能 :寄存器与操作数按位与,结果存入目标寄存器。
语法

复制代码
AND Rd, Rn, Rm         ; Rd = Rn & Rm
AND Rd, Rn, #immediate ; Rd = Rn & immediate

实例

复制代码
AND R0, R0, #0x0F      ; 保留R0低4位,高28位清零(屏蔽操作)
AND R1, R2, R3         ; R1 = R2 & R3

应用:位掩码操作(如提取状态标志)、清除特定位。

4. ADD(Addition)

功能 :寄存器加法运算。
语法

复制代码
ADD Rd, Rn, Rm         ; Rd = Rn + Rm
ADD Rd, Rn, #immediate ; Rd = Rn + immediate

实例

复制代码
ADD R0, R1, R2         ; R0 = R1 + R2
ADD R3, R3, #1         ; R3自增1(R3++)

应用:算术运算、地址计算(如数组索引)。

5. STR(Store Register)

功能 :将寄存器数据存储到内存。
语法

复制代码
STR Rd, [Rn, #offset]  ; *(Rn + offset) = Rd
STR Rd, label          ; *label = Rd

实例

复制代码
LDR R0, =0x40000000    
MOV R1, #0x12345678    
STR R1, [R0]           ; 将R1的值存入地址0x40000000

应用:写外设寄存器(如配置 GPIO 输出)、保存变量到内存。

6. DCD(Define Constant Data)

功能 :在内存中定义 32 位常量数据(非指令,属于伪指令)。
语法

复制代码
label DCD value1, value2, ...  ; 在当前地址定义字数据

实例

复制代码
DataArea DCD 0x12345678, 0x87654321  ; 定义两个32位常量
        DCD 100, 200                  ; 定义两个整数

应用:初始化数组、定义查找表(如正弦函数表)。

7. MUL(Multiply)

功能 :寄存器乘法运算。
语法

复制代码
MUL Rd, Rn, Rm         ; Rd = Rn * Rm(32位×32位→32位)

实例

复制代码
MOV R0, #5
MOV R1, #10
MUL R2, R0, R1         ; R2 = 5 * 10 = 50

应用:数学计算(如面积、体积)、缩放操作。

8. MSR(Move to Special Register)

功能 :将通用寄存器值写入特殊寄存器(如状态寄存器)。
语法

复制代码
MSR special_reg, Rn    ; special_reg = Rn

实例

复制代码
MOV R0, #0x13          ; 设置处理器模式为SVC(10011)
MSR CPSR_c, R0         ; 修改CPSR的低5位(模式位)

应用:系统初始化(如配置特权模式)、异常处理。

9. MOV(Move)

功能 :数据传送(寄存器←寄存器 / 立即数)。
语法

复制代码
MOV Rd, Rn             ; Rd = Rn
MOV Rd, #immediate     ; Rd = immediate(立即数需符合编码规则)

实例

复制代码
MOV R0, R1             ; R0 = R1
MOV R2, #0xFF          ; R2 = 0x000000FF

应用:初始化寄存器、数据传递。

10. STRH(Store Register Halfword)

功能 :将寄存器低 16 位存储到内存半字地址(16 位对齐)。
语法

复制代码
STRH Rd, [Rn]          ; *(Rn) = Rd[15:0](半字对齐)

实例

复制代码
MOV R0, #0x40000000    
MOV R1, #0x12345678    
STRH R1, [R0]          ; 将R1低16位(0x5678)存入地址0x40000000

应用:存储 16 位数据(如音频采样、16 位传感器值)。

综合实例:LED 控制与数据处理

以下代码演示如何使用上述指令实现 LED 控制和数据处理:

复制代码
    AREA    Main, CODE, READONLY
    ENTRY
    
; 定义外设基址和常量
LED_BASE    DCD     0x40021000      ; GPIO端口基址
DELAY_VAL   DCD     0x00FFFFFF      ; 延时计数最大值

; 主程序
Main
    LDR R0, =LED_BASE               ; R0 = GPIO基址
    LDR R1, [R0, #0x04]             ; 读取GPIO配置寄存器
    ORR R1, R1, #0x00000003         ; 配置PA0为输出模式(0b11)
    STR R1, [R0, #0x04]             ; 写回配置寄存器
    
Loop
    ; 点亮LED
    LDR R1, [R0, #0x10]             ; 读取输出数据寄存器
    ORR R1, R1, #0x00000001         ; 设置PA0为高电平
    STR R1, [R0, #0x10]             ; 写回输出寄存器
    
    ; 延时
    LDR R2, =DELAY_VAL
    LDR R2, [R2]
Delay1
    SUBS R2, R2, #1                 ; 递减计数
    BNE Delay1                      ; 非零则继续循环
    
    ; 熄灭LED
    LDR R1, [R0, #0x10]
    BIC R1, R1, #0x00000001         ; 清除PA0位(与0xFFFFFFFF异或)
    STR R1, [R0, #0x10]
    
    ; 延时
    LDR R2, =DELAY_VAL
    LDR R2, [R2]
Delay2
    SUBS R2, R2, #1
    BNE Delay2
    
    B Loop                          ; 无限循环
    END

指令对比与注意事项

指令 操作类型 数据宽度 内存访问方式
LDR 加载 32 位(字) 字对齐
LDRB 加载 8 位(字节) 任意地址
STR 存储 32 位(字) 字对齐
STRH 存储 16 位(半字) 半字对齐(偶地址)
  • 立即数限制:MOV 指令的立即数需符合 "8 位数值循环右移偶数位" 规则(如 0xFF00 可表示为 0xFF 右移 8 位),否则需用 LDR 伪指令加载。
  • 内存对齐:STR/STRH/LDR/LDRH 需遵循对齐规则,否则可能触发硬件异常。

掌握这些指令是 ARM 汇编编程的基础,可实现从简单外设控制到复杂算法的各类功能。

相关推荐
进击的程序汪7 小时前
Linux 启动过程流程图--ARM版
linux·运维·arm开发
比奇堡在逃帅哥10 天前
硬件-DAY04(ds18b20、ARM内核)
arm开发
切糕师学AI10 天前
半导体行业中的专用标准产品ASSP是什么?
arm开发·嵌入式硬件·嵌入式·计算机体系结构
Svan.11 天前
Portable Watch:基于STM32的便携智能手表
arm开发·驱动开发·stm32·嵌入式硬件·硬件工程·pcb工艺·智能手表
凉、介12 天前
CPU Cache 的映射与寻址
linux·arm开发·数据库·redis·缓存·嵌入式
学渣6765612 天前
单片机开发日志cv MDK-ARM工具链迁移到MAKE
arm开发·单片机·嵌入式硬件
ldinvicible12 天前
基于ARM ubuntu如何进行交叉编译
arm开发·数据库·ubuntu
Jason_zhao_MR12 天前
多协议物联网关的方案测试-基于米尔全志T536开发板
arm开发·嵌入式硬件·mcu·物联网·嵌入式
永夜的黎明13 天前
【二进制安全作业】250616课上作业1-栈溢出漏洞利用
c语言·汇编·安全