4-3_ARM汇编_学习笔记

4-3 ARM 汇编 · 学习笔记

所属课程:韦东山《ARM架构与编程》(百问网 · 单片机核心课程 ARM 架构篇)

所在章节:第 4 章 ARM 芯片基础(本章第 3 节;上节:4-2 ARM内部寄存器)

讲师:韦东山

原视频:4-3_ARM汇编

整理日期:2026-09-29

目录

  • 摘要
  • 一、本节在课程中的位置
  • 二、核心命题
  • 三、知识点展开
    • [3.1 三套指令集:ARM、Thumb、Thumb-2](#3.1 三套指令集:ARM、Thumb、Thumb-2)
    • [3.2 数据处理指令:运算发生在寄存器之间](#3.2 数据处理指令:运算发生在寄存器之间)
    • [3.3 内存访问指令:唯一的 Load/Store](#3.3 内存访问指令:唯一的 Load/Store)
    • [3.4 跳转指令:控制流的转移](#3.4 跳转指令:控制流的转移)
    • [3.5 状态寄存器访问指令](#3.5 状态寄存器访问指令)
    • [3.6 综合实例:把 C 语句翻译成汇编](#3.6 综合实例:把 C 语句翻译成汇编)
  • 四、常见误区
  • 五、本节结论与延伸
  • [附录 A:术语速查](#附录 A:术语速查)
  • [附录 B:自查清单](#附录 B:自查清单)

摘要

本节讲解 ARM 汇编基础:对比 ARM、Thumb、Thumb-2 指令集------16 位 Thumb 密度高但受限,Thumb-2 混合编码兼得密度与能力。再按数据处理、访存、跳转、状态访问四类梳理指令,以 LDR/ADD/STR 与 BL/BX 演示 4-1 四步运算的汇编形态。


一、本节在课程中的位置

本节是第 4 章第三节,从"认识硬件"进入"用硬件的语言说话":

  • 承上:4-1 建立了 RISC"运算在寄存器、访存靠 Load/Store"的模型,4-2 给出了 R0~R12、SP/LR/PC/xPSR 的寄存器词汇表------但两节都停留在"CPU 长什么样"。
  • 本节:学习指挥这些寄存器工作的语言------汇编指令,把前三节的地址空间、寄存器、数据通路串成可执行的代码。
  • 启下:后续小节将用汇编/反汇编分析 C 语言的内存读写与函数调用过程,并进入异常与中断处理、GNU 汇编工程实践。

一句话定位:汇编是地址空间(4-1)与寄存器(4-2)之间的"操作动词",本节补全裸机编程的最后一块拼图。

二、核心命题

  1. ARM 有哪几套指令集,该用哪套? ------ 经典 ARM(32 位)、Thumb(16 位)、Thumb-2(16/32 位混合),现代 Cortex-M 内核运行 Thumb-2。
  2. 常用指令有哪些? ------ 四大类:数据处理、内存访问(Load/Store)、跳转、状态寄存器访问。
  3. 一条 C 语句落到汇编是什么样子? ------ *p = *p + 1 对应"LDR 取数 → ADD 运算 → STR 存回",正是 4-1 四步法则的直接体现。

三、知识点展开

3.1 三套指令集:ARM、Thumb、Thumb-2

指令集 指令宽度 特点
ARM 固定 32 位 功能强、寻址灵活,代码密度低
Thumb 固定 16 位 代码密度高(省约 30%~40% 空间),但功能受限:多数指令只能访问 R0~R7,无条件执行、无完整数据处理能力
Thumb-2 16/32 位混合 兼得密度与能力,Cortex-M3/M4 内核只支持 Thumb-2(无 ARM 状态)

要点:

  • Thumb 是 ARM 指令集的功能子集压缩编码,不是另一种机器;
  • Thumb-2 通过指令前缀位区分 16 位与 32 位指令(半字 15:11 为 11101/11110/11111 者为 32 位指令),反汇编器必须逐半字解码;
  • Cortex-M 复位后处于 Thumb 状态,T 位恒为 1------这就是 4-2 中"复位向量 bit0 必须为 1"的由来。

3.2 数据处理指令:运算发生在寄存器之间

通用形式:op{S}{cond} Rd, Rn, Operand2------带 S 后缀则更新 APSR 的 N/Z/C/V 标志。

asm 复制代码
MOV  R0, #42        ; R0 = 42         (数据传送)
MVN  R0, R1         ; R0 = ~R1        (按位取反传送)
ADD  R0, R1, R2     ; R0 = R1 + R2    (加法)
SUB  R0, R1, #5     ; R0 = R1 - 5     (减法)
MUL  R0, R1, R2     ; R0 = R1 × R2    (低 32 位乘积)
AND  R0, R1, R2     ; R0 = R1 & R2    (与)
ORR  R0, R1, R2     ; R0 = R1 | R2    (或)
EOR  R0, R1, R2     ; R0 = R1 ^ R2    (异或)
BIC  R0, R1, R2     ; R0 = R1 & ~R2   (位清除)
LSL  R0, R1, #2     ; R0 = R1 << 2    (逻辑左移,另有 LSR/ASR/ROR)

比较与测试指令只改标志、不存结果:

asm 复制代码
CMP  R0, R1     ; 按R0-R1更新标志(Compare)
TST  R0, R1     ; 按R0&R1更新标志(Test)

Cortex-M3 的 Thumb-2 还引入除法 SDIV/UDIV 与 CBZ/CBNZ(比较为零跳转)、IT 条件块等增强指令。

3.3 内存访问指令:唯一的 Load/Store

ARM 是 Load/Store 架构,运算指令不能直接操作内存,访存只有两类:

asm 复制代码
LDR  R0, [R1]        ; R0 = *R1        (读 32 位字)
LDR  R0, [R1, #4]    ; R0 = *(R1+4)    (立即数偏移)
LDR  R0, [R1, R2]    ; R0 = *(R1+R2)   (寄存器偏移)
LDRB R0, [R1]        ; 读单字节;LDRH 读半字
STR  R0, [R1]        ; *R1 = R0        (写 32 位字)
STRB R0, [R1]        ; 写单字节;STRH 写半字
LDM  R0, {R1-R5}     ; 批量加载(多寄存器)
STM  R0, {R1-R5}     ; 批量存储
PUSH {R0, LR}        ; 压栈(STM 的别名)
POP  {R0, PC}        ; 出栈(LDM 的别名)

伪指令 LDR Rd, =立即数 用于把任意 32 位常数/地址装入寄存器------这正是 4-1 中"指针指向 0x40010800"的汇编实现方式。

3.4 跳转指令:控制流的转移

asm 复制代码
B    label       ; 无条件跳转(Branch)
BEQ  label       ; 条件跳转:Z=1 则跳(B + 条件码组合)
BL   func        ; 跳转并链接:LR = 返回地址,PC = func(调用子程序)
BX   LR          ; 跳转到寄存器地址(从子程序返回)
BLX  Rm          ; 带链接+状态切换(Cortex-M 中状态恒为 Thumb)

要点:

  • BL func ... BX LR 是子程序调用的标准范式:BL 把返回地址存入 LR(呼应 4-2"LR 省一次访存"的设计),BX LR 跳回;
  • 也可直接向 PC 赋值实现跳转(MOV PC, LR);
  • BX/BLX Rm 依据 Rm 的 bit0 判断目标状态:为 1 保持 Thumb,为 0 切到 ARM 状态(Cortex-M 上恒为 Thumb,bit0 必须为 1)。

3.5 状态寄存器访问指令

4-2 讲过:xPSR 等特殊寄存器没有内存地址,只能用专用指令访问:

asm 复制代码
MRS  R0, APSR     ; 读程序状态寄存器到通用寄存器
MSR  APSR, R0     ; 写程序状态寄存器
MRS  R0, CONTROL  ; 读 CONTROL(MSP/PSP 选择等)
MSR  CONTROL, R0

3.6 综合实例:把 C 语句翻译成汇编

C 代码(4-1 的指针访问外设寄存器):

c 复制代码
unsigned int *p = (unsigned int *)0x40010800;
*p = *p + 1;

对应的 Thumb-2 汇编与四步法则对照:

asm 复制代码
        LDR  R1, =0x40010800   ; 伪指令:把寄存器地址装入 R1
        LDR  R0, [R1]          ; ① 读内存:R0 = *p
        ADD  R0, R0, #1        ; ② CPU 内部运算:R0 = R0 + 1
        STR  R0, [R1]          ; ③ 写回内存:*p = R0

子程序调用完整范式:

asm 复制代码
        BL   my_func           ; 调用:LR = 返回地址
        ...                    ; 返回后继续
my_func:
        PUSH {R0, LR}          ; 保存现场(多级调用需保护 LR)
        ...                    ; 函数体
        POP  {R0, PC}          ; 恢复现场并返回(PC 出栈即跳回)

可以看到:每一条指令都精确落在 4-1(Load/Store、统一编址)与 4-2(寄存器分工、LR/PC)划定的框架之内------汇编不过是这套框架的"操作动词表"。

四、常见误区

  1. "Cortex-M 上可以写 32 位 ARM 指令" ------ 错。Cortex-M3/M4 只支持 Thumb/Thumb-2,复位即处于 Thumb 状态,T 位恒为 1。
  2. "Thumb 与 ARM 是两种互不相干的机器语言" ------ 错。Thumb 是 ARM 指令集的压缩编码子集,同一程序可混合链接。
  3. "ADD R0, [R1] 可以直接对内存做加法" ------ 错。Load/Store 架构下运算指令的操作数只能是寄存器/立即数,必须先 LDR 后 ADD 再 STR。
  4. "CMP 会把差值存入寄存器" ------ 错。CMP 只按减法结果更新 N/Z/C/V 标志,不保存结果,专供条件跳转使用。
  5. "BL 调用后必须 PUSH {LR}" ------ 不完全对。一级调用可直接 BX LR 返回;只有嵌套调用(LR 会被覆盖)时才需要压栈保护。
  6. "xPSR 可以像外设寄存器那样用指针读写" ------ 错。核心寄存器不在地址空间中,只能用 MRS/MSR 指令访问。

五、本节结论与延伸

结论:ARM 汇编 = 三套指令集的选择(现代 Cortex-M 用 Thumb-2)+ 四类动词(数据处理、Load/Store 访存、B/BL/BX 跳转、MRS/MSR 状态访问)。C 语句到汇编的映射严格遵循"先取数入寄存器、再运算、后写回"的 RISC 法则,函数调用则由 BL/BX 与栈共同支撑。

延伸到下一节:掌握了指令动词,下一节将用它们逐行分析 C 程序的运行过程------局部变量在栈上的布局、参数如何经 R0~R3 传递、返回值如何经 R0 返回,从反汇编视角彻底打通 C 与汇编的隔阂。

附录 A:术语速查

术语 含义
ARM 指令集 经典 32 位定长指令集,功能强、密度低
Thumb 16 位压缩指令集,ARM 子集,密度高、只能访问低寄存器
Thumb-2 16/32 位混合编码指令集,Cortex-M3/M4 专用
Load/Store 架构 只有取数/存数指令能访存,运算只发生在寄存器间
LDR / STR 读 / 写内存字指令(B/H 后缀为字节/半字)
伪指令 汇编器代为展开的助记符,如 LDR Rd, =imm32
B / BL / BX 跳转 / 带链接跳转(存返回地址到 LR)/ 跳转到寄存器
CMP / TST 比较 / 测试:只更新标志位不保存结果
S 后缀 指令更新 APSR 的 N/Z/C/V 标志
IT 块 Thumb-2 的 If-Then 条件执行块,最多 4 条指令免跳转
MRS / MSR 读 / 写状态寄存器(xPSR、CONTROL 等)的专用指令
PUSH / POP 压栈 / 出栈(STM/LDM 的栈式别名)

附录 B:自查清单

  • 能说出 ARM、Thumb、Thumb-2 三者关系及 Cortex-M 的选择;
  • 能解释 Thumb-2 如何在同一条指令流中混排 16 位与 32 位指令;
  • 能默写"读内存→运算→写回"对应的 LDR/ADD/STR 三连;
  • 能写出完整的最小子程序:BL 调用、PUSH/POP 保护、BX LR 返回;
  • 能说明 CMP 与 SUB、TST 与 AND 的区别(标志 vs 结果);
  • 能解释为什么 LDR Rd, =0x40010800 需要伪指令而不能用 MOV 一步完成;
  • 能用 MRS/MSR 读写 xPSR,并说明它与外设寄存器访问方式的差异。
相关推荐
kkkkkkkkkk_Z1 小时前
新手自学嵌入式 | 学习日记:ARM架构初探与基础概念梳理
arm开发·学习·架构
SKH.1 小时前
ARM-lcd屏幕点亮
arm开发
鬓戈1 小时前
开源中文输入法技术调研与自建方案
学习·开源
only-lucky2 小时前
QML深入学习七(MVC模块)
学习·mvc
2401_850122042 小时前
高温耐油热缩套管选型:材料、温度和油液要匹配
经验分享·笔记·科技·学习
Xudde.3 小时前
Me and My Girlfriend 靶机渗透测试(Vulnhub Writeup)
笔记·学习·安全·web安全
Canmag 兴隆磁性3 小时前
自动装盒设备 AO-WCMF
学习·永磁材料·充磁
imDwAaY3 小时前
Bean的生命周期
java·笔记·后端·学习·spring·dubbo
坤坤子吖3 小时前
C++11——Lambda、function、bind 与可调用对象
c++·笔记·学习