阅读寄存器名时,先确认指令集、运行模式和调用约定。x86-64、32 位 Arm A/R-profile 与 Cortex-M3 不能共用一张没有适用范围的寄存器表;CPU 核心寄存器也不同于通过总线访问的 GPIO、RCC 等外设寄存器。
x86 的通用寄存器与不同宽度
跳转到“x86 的通用寄存器与不同宽度”下表保留常见历史名称与用途,但“累加器、基址、计数器”等名称并不意味着它们只能执行那一种工作。哪些寄存器传参、哪些由被调用方保存,还取决于 ABI。
| 寄存器族 | 16 位 | 32 位 | 64 位 | 常见历史用途或特殊关系 |
|---|---|---|---|---|
| 累加器 | AX | EAX | RAX | 某些算术指令的隐含操作数;常用于整数返回值 |
| 基址 | BX | EBX | RBX | 通用数据或地址;保存义务由 ABI 规定 |
| 计数器 | CX | ECX | RCX | 某些循环、移位或字符串指令使用 |
| 数据 | DX | EDX | RDX | 某些乘除法及 I/O 指令使用 |
| 源索引 | SI | ESI | RSI | 字符串操作的源地址等 |
| 目标索引 | DI | EDI | RDI | 字符串操作的目标地址等 |
| 帧指针 | BP | EBP | RBP | 可用于栈帧定位,也可能被优化后用于其他用途 |
| 栈指针 | SP | ESP | RSP | 栈顶位置及隐含栈操作 |
这些通常是同一寄存器不同位宽的视图,并不是三组互不相关的存储。例如在常规 x86-64 模式下,写 EAX 会把 RAX 的高 32 位清零;写 AX 或 AL 不会自动清零其余位。
8 位名称包括 AL/AH、BL/BH、CL/CH、DL/DH。64 位模式还提供 SIL、DIL、BPL、SPL 及 R8B 等低字节视图;AH 等高字节寄存器与 REX 前缀存在编码限制,不能随意混用。
常规 x86-64 还增加 R8~R15,其低位视图例如 R8D、R8W、R8B。具体扩展是否可用应查目标 CPU 和工具链;此处不是所有新扩展寄存器的完整清单。
x86 的段、状态与系统寄存器
跳转到“x86 的段、状态与系统寄存器”| 类别 | 名称 | 应怎样理解 |
|---|---|---|
| 代码段 | CS | 代码段选择与执行属性相关,不只是一个普通代码地址变量 |
| 数据与栈段 | DS、ES、SS | 保护模式中可见部分是段选择子;不是直接保存完整数据区或栈区地址 |
| 附加段 | FS、GS | 在 64 位模式下仍有可用于地址形成的段基址,常由系统用于线程相关数据 |
| 指令指针 | EIP、RIP | 与取指位置和控制转移相关,不能把它当作可随意 mov 写入的通用寄存器 |
| 状态与控制标志 | FLAGS、EFLAGS、RFLAGS | 包含条件状态及控制位,例如 ZF、CF;不是每条指令都更新所有标志 |
| 系统控制 | CR0、CR2、CR3、CR4;64 位模式的 CR8 | 控制执行模式、分页等系统功能,访问受特权规则约束;CR1 保留 |
| 硬件调试 | DR0、DR1、DR2、DR3、DR6、DR7 | 断点地址、状态与控制等调试功能 |
| 描述符表 | GDTR、IDTR | 包含相应描述符表的基址与界限 |
| 局部描述符与任务状态 | LDTR、TR | 可见部分为选择子,并配有处理器维护的描述符信息;不能只解释成普通地址寄存器 |
段机制随实模式、保护模式、64 位模式而变化。在常规 64 位代码中,不能把 32 位分段地址形成规则原样搬过来。系统寄存器的详细字段与访问权限应查 Intel 软件开发手册。
32 位 Arm:核心名称与 AAPCS32 约定
跳转到“32 位 Arm:核心名称与 AAPCS32 约定”这里的 R0~R15 针对 32 位 Arm/Thumb 执行环境,不能直接替代 AArch64 的 X0~X30 等寄存器模型。
| 名称 | 核心角色与常见调用约定 |
|---|---|
| R0~R3 | AAPCS32 中通常用于参数、返回值或临时数据;不保证跨调用保留 |
| R4~R8、R10、R11 | AAPCS32 通常要求被调用方保留;R11 也可能用作 FP 帧指针 |
| R9 | 平台相关,可作平台寄存器或被调用方保存的变量寄存器;不能一概当作任意临时寄存器 |
| R12,IP | 调用内部临时寄存器,链接器插入的代码也可能使用它 |
| R13,SP | 栈指针 |
| R14,LR | 普通子程序调用的链接/返回信息;嵌套调用前需要按约定保存仍有用的值 |
| R15,PC | 程序计数器;读取与写入规则受到具体指令和执行状态限制 |
“通用寄存器是 R0~R12”是寄存器分类;“参数放在哪、谁负责保存”是 ABI 规则。两者要分别理解。AAPCS32 公共调用接口要求栈保持 8 字节对齐,不能只压入一个 4 字节 LR 后就直接调用任意 C 函数。详见 Arm AAPCS32。
在经典 32 位 A/R-profile 环境中,可见 CPSR 当前状态寄存器,以及某些异常模式使用的 SPSR 保存状态寄存器。VFP 浮点和 NEON/Advanced SIMD 寄存器属于相应扩展,是否存在、数量与调用约定要看实现;它们不是每个 Arm 核心都具有的部件。
Cortex-M3:不要套用 CPSR/SPSR 表
跳转到“Cortex-M3:不要套用 CPSR/SPSR 表”STM32F1 常见 Cortex-M3 核心的主要名称如下。它没有 NEON,也没有硬件 VFP 浮点单元;软件仍然可以通过软件例程完成浮点计算。
| 名称 | 作用 |
|---|---|
| R0~R12 | 通用寄存器;调用保存规则仍需遵循所用 ABI |
| R13,SP | 当前所用栈指针,关联 MSP 或 PSP |
| R14,LR | 普通调用的返回信息;异常处理期间还可能保存特殊的异常返回编码 |
| R15,PC | 执行位置及控制转移 |
| xPSR | 组合表示应用状态、异常编号和执行状态等信息,不是 A/R-profile 的 CPSR |
| MSP | 主栈指针;异常处理使用它 |
| PSP | 进程栈指针;线程模式可以选择使用它 |
| PRIMASK | 屏蔽可配置优先级异常;不能理解成关闭所有异常 |
| BASEPRI | 非零时按优先级阈值屏蔽相应异常;具体编码需结合已实现优先级位数 |
| FAULTMASK | 更强的异常屏蔽,仍不屏蔽 NMI |
| CONTROL | 线程模式特权与栈选择等控制 |
这些寄存器可通过处理器指令或 CMSIS 核心寄存器接口访问;不要从 Cortex-M3 推断全部 Cortex-M 型号都实现 BASEPRI、FAULTMASK 或同样的字段。
核心寄存器与外设寄存器分开查
跳转到“核心寄存器与外设寄存器分开查”CPU 的 R0、PC 等不是 GPIO 的输入、输出或模式寄存器。STM32 的 GPIO、RCC、USART、TIM、ADC 等外设通过芯片规定的地址映射访问,其寄存器布局由具体器件手册定义。
- STM32F107 外设寄存器偏移速查:保留 GPIO、RCC、USART、TIM、ADC 五组表,并说明器件范围。
- x86 与 Arm 汇编语法:明确操作数、注释和指令集状态。
- 从 C/C++ 到真实汇编:比较不同 ABI 和优化级别的生成结果。