ARM 汇编语言语法小解

ARM 汇编语言语法小解

📚 系列文章提示

本文来自《ARM汇编指令深入解析》系列教程。如果你想要:

  • 查找其他ARM汇编指令的讲解
  • 了解本系列的整体结构
  • 按顺序系统学习ARM汇编

请访问:系列导读与目录总览


文章目录

ARM汇编语言是一种低级编程语言,用于直接控制ARM处理器的操作。以下是ARM汇编语言的详细语法介绍:

一、基本架构特点

  1. RISC架构:精简指令集,大多数指令在一个时钟周期内执行
  2. 加载/存储架构:只有加载/存储指令可以访问内存,运算指令只操作寄存器
  3. 统一字长:大多数指令为32位(ARM模式)或16位(Thumb模式)
  4. 条件执行:几乎所有指令都可以条件执行

二、基本语法结构

1. 指令格式

复制代码
[label:] mnemonic [operands] [; comment]

示例

assembly 复制代码
start:          ; 标签
    MOV R0, #10 ; 将立即数10加载到R0
    ADD R1, R0, #5 ; R1 = R0 + 5

2. 程序组成

  • 指令:处理器执行的操作
  • 伪指令:汇编器指令,不生成机器码
  • 汇编器指示符:控制汇编过程的指令

三、寄存器

1. 通用寄存器(32位)

  • R0-R12:通用目的寄存器
  • R13 (SP):堆栈指针
  • R14 (LR):链接寄存器(保存返回地址)
  • R15 (PC):程序计数器

2. 特殊寄存器

  • CPSR :当前程序状态寄存器
    • N(负标志)、Z(零标志)、C(进位标志)、V(溢出标志)
    • 模式位、中断禁止位等

四、指令分类与语法

1. 数据处理指令

复制代码
OPcode{S}{cond} Rd, Rn, Operand2
  • S:可选,更新条件标志
  • cond:条件码(可选)
  • Rd:目标寄存器
  • Rn:第一操作数寄存器
  • Operand2:第二操作数(寄存器/立即数/移位寄存器)

常见指令

assembly 复制代码
MOV R0, #0x3F      ; 传送立即数
ADD R1, R2, R3     ; 加法:R1 = R2 + R3
SUB R4, R5, #10    ; 减法:R4 = R5 - 10
AND R0, R1, R2     ; 按位与
ORR R3, R4, #0xFF  ; 按位或
EOR R5, R6, R7     ; 按位异或
CMP R0, R1         ; 比较,设置标志位

2. 加载/存储指令

assembly 复制代码
LDR Rd, [Rn]           ; 从内存加载到寄存器
STR Rd, [Rn]           ; 从寄存器存储到内存
LDR Rd, [Rn, #offset]  ; 带偏移量的加载
LDMIA Rn!, {reglist}   ; 多寄存器加载
STMIA Rn!, {reglist}   ; 多寄存器存储

3. 分支指令

assembly 复制代码
B label        ; 无条件跳转
BL label       ; 带链接的跳转(用于函数调用)
BX Rn          ; 跳转到寄存器指定的地址
BEQ label      ; 相等时跳转(Z=1)
BNE label      ; 不相等时跳转(Z=0)

4. 移位操作

assembly 复制代码
LSL R0, R1, #2     ; 逻辑左移2位
LSR R2, R3, #4     ; 逻辑右移4位
ASR R4, R5, #1     ; 算术右移1位
ROR R6, R7, #8     ; 循环右移8位

五、寻址方式

1. 立即数寻址

assembly 复制代码
MOV R0, #0xFF      ; 立即数0xFF
ADD R1, R2, #100   ; 立即数100

2. 寄存器寻址

assembly 复制代码
ADD R0, R1, R2     ; R0 = R1 + R2
MOV R3, R4         ; R3 = R4

3. 寄存器间接寻址

assembly 复制代码
LDR R0, [R1]       ; R0 = memory[R1]
STR R2, [R3]       ; memory[R3] = R2

4. 基址加偏移寻址

assembly 复制代码
LDR R0, [R1, #4]     ; R0 = memory[R1 + 4]
LDR R0, [R1, R2]     ; R0 = memory[R1 + R2]
LDR R0, [R1, R2, LSL #2] ; R0 = memory[R1 + (R2 << 2)]

5. 前变址/后变址寻址

assembly 复制代码
LDR R0, [R1, #4]!    ; 前变址:R1 = R1 + 4, 然后加载
LDR R0, [R1], #4     ; 后变址:先加载,然后R1 = R1 + 4

六、条件执行

1. 条件码后缀

后缀 含义 条件标志
EQ 相等 Z=1
NE 不相等 Z=0
CS/HS 进位/无符号>= C=1
CC/LO 无进位/无符号< C=0
MI N=1
PL 正/零 N=0
VS 溢出 V=1
VC 无溢出 V=0
HI 无符号> C=1且Z=0
LS 无符号<= C=0或Z=1
GE 有符号>= N=V
LT 有符号< N!=V
GT 有符号> Z=0且N=V
LE 有符号<= Z=1或N!=V
AL 总是执行 任何

2. 条件执行示例

assembly 复制代码
CMP R0, R1      ; 比较R0和R1
ADDGT R2, R3, #1  ; 如果R0>R1,则执行
MOVLE R2, #0     ; 如果R0<=R1,则执行

七、伪指令和汇编器指示符

1. 常用伪指令

assembly 复制代码
ADR R0, label      ; 加载标签地址(小范围)
LDR R0, =label     ; 加载标签地址(大范围)
LDR R0, =0x12345678 ; 加载32位立即数
NOP                ; 空操作

2. 汇编器指示符

assembly 复制代码
.global _start     ; 声明全局符号
.section .text     ; 代码段开始
.align 2           ; 按4字节对齐
.arm               ; 使用ARM指令集
.thumb             ; 使用Thumb指令集
.word 0x12345678   ; 定义32位数据
.byte 0x12, 0x34   ; 定义字节数据
.ascii "Hello"     ; 定义ASCII字符串
.asciz "World"     ; 定义以null结尾的字符串
.equ MAX, 100      ; 定义常量

八、完整示例程序

assembly 复制代码
/* ARM汇编示例:计算1+2+...+10 */

.global _start      /* 全局入口点 */
.section .text      /* 代码段 */

_start:
    MOV R0, #0      /* 总和清零 */
    MOV R1, #1      /* 计数器从1开始 */
    MOV R2, #10     /* 最大值 */
    
loop:
    CMP R1, R2      /* 比较计数器和最大值 */
    BGT end         /* 如果R1>R2,跳转到结束 */
    ADD R0, R0, R1  /* 累加:R0 = R0 + R1 */
    ADD R1, R1, #1  /* 计数器加1 */
    B loop          /* 继续循环 */
    
end:
    /* 此时R0中存储着结果55 */
    
    /* 退出程序(Linux系统调用) */
    MOV R7, #1      /* 退出系统调用号 */
    MOV R0, #0      /* 返回码0 */
    SWI 0           /* 软中断 */
    
.section .data      /* 数据段 */
result: .word 0     /* 存储结果 */

九、ARM与Thumb模式

  1. ARM模式

    • 32位指令
    • 完整的指令集
    • 所有指令都可以条件执行
  2. Thumb模式

    • 16位指令(也有32位Thumb-2指令)
    • 代码密度更高
    • 有限的指令集
    • 只有分支指令可以条件执行
  3. 模式切换

assembly 复制代码
ADR R0, thumb_code+1
BX R0               ; 切换到Thumb模式
.thumb
thumb_code:
    MOV R0, #10     ; Thumb指令

十、注意事项

  1. 立即数限制:ARM立即数必须是8位位图循环移位得到的
  2. 对齐要求:ARM指令需要4字节对齐,数据访问也有对齐要求
  3. PC的特殊性:读取PC时返回当前指令地址+8(ARM模式)
  4. 寄存器使用约定:函数调用时通常使用R0-R3传递参数,R0保存返回值

十一、常用编程模式

  1. 函数调用
assembly 复制代码
/* 调用函数 */
BL function_name
/* ... */

/* 函数定义 */
function_name:
    PUSH {R4-R11, LR}  /* 保存寄存器和返回地址 */
    /* 函数体 */
    POP {R4-R11, PC}   /* 恢复寄存器并返回 */
  1. 堆栈操作
assembly 复制代码
PUSH {R0-R3, LR}   /* 压栈多个寄存器 */
POP {R0-R3, PC}    /* 出栈并返回 */

ARM汇编语言通过其丰富的指令集和灵活的条件执行机制,为底层系统编程提供了强大的控制能力。随着ARM架构的发展(如ARMv8-A的AArch64),语法有所变化,但基本概念保持了一致性。

相关推荐
代码游侠3 天前
STM32开发——基础外设
linux·运维·arm开发·stm32·单片机·嵌入式硬件·学习
代码游侠4 天前
Linux驱动复习——驱动
linux·运维·arm开发·笔记·学习
古译汉书4 天前
【IoT死磕系列】Day 6:工业控制底层大动脉—CAN总线
linux·网络·arm开发·单片机·物联网·tcp/ip
姜太公钓鲸2334 天前
STM32是ST公司基于ARM Cortex-M内核开发的32位微控制器。上述文字中的内核是什么意思?作用是什么?
arm开发·stm32·嵌入式硬件
日更嵌入式的打工仔4 天前
FIQ 与 IRQ
arm开发·笔记
The️5 天前
STM32-FreeRTOS操作系统-软件定时器
arm开发·stm32·单片机·嵌入式硬件·mcu·c#
szxinmai主板定制专家5 天前
RK3588 8个USB工控解决方案,适用于机器视觉,工业互联等
arm开发·人工智能·fpga开发
我在人间贩卖青春5 天前
ARM编程模型
arm开发·arm工作模式
安全二次方security²5 天前
【CVE-2025-0647】ARM CPU漏洞安全通告
arm开发·安全·cve-2025-0647·tlbi·cpp rctx 指令·c1-ultra·虚拟化漏洞
道亦无名6 天前
armBitRevIndexTable1024
arm开发