处理器寻址方式

原始 Flomo:https://v.flomoapp.com/mine/?memo_id=MTg4ODAzMzk1

寻址方式描述指令如何定位操作数。不同 ISA(x86、ARM、PowerPC、RISC-V 等)的寻址模式和汇编语法并不完全相同。下面先解释常见概念,再以传统 x86 16 位地址表达式说明原笔记中的七类形式;不要把这七类当成所有处理器都统一规定的分类。

1. 七种常见寻址方式

方式操作数/有效地址如何确定示例(概念或 x86 风格)典型用途
立即寻址常量直接编码在指令中MOV AL, 12H常量、掩码、初值
直接寻址指令给出内存地址/位移MOV AL, [1234H]访问固定地址(受 ISA 限制)
寄存器寻址操作数位于寄存器MOV AL, BL快速算术与数据搬运
寄存器间接寻址寄存器保存内存地址MOV AL, [BX]指针、缓冲区访问
寄存器相对/基址加位移有效地址 = 基址寄存器 + 位移MOV AL, [BX+12H]结构体成员、局部变量
基址变址寻址有效地址 = 基址 + 变址MOV AL, [BX+SI]数组、表格
相对基址变址有效地址 = 基址 + 变址 + 位移MOV AL, [BX+SI+12H]数组元素加字段偏移

2. 立即寻址与寄存器寻址

立即数是指令编码中的常量,不需要再从内存读取。例如:

MOV R0, #42       ; ARM 风格伪例:把立即数 42 写入 R0

寄存器寻址直接使用寄存器中的值:

MOV R0, R1        ; 将 R1 的值复制到 R0
ADD R0, R0, R2    ; R0 = R0 + R2

立即数宽度、符号扩展、可编码范围受具体指令集限制;超出范围时,汇编器可能改用多条指令或常量池。

3. 直接与寄存器间接寻址

直接寻址由指令提供地址或地址位移;寄存器间接寻址由寄存器保存地址。后者是指针和数组访问的基础:

uint8_t buffer[16];
uint8_t *p = &buffer[3];
uint8_t value = *p;

在嵌入式中,内存映射寄存器通常通过芯片头文件定义的地址访问,但必须使用厂商提供的正确地址、访问宽度和 volatile 限定,不能任意解引用猜测地址。

4. 基址、变址与位移

数组访问常可抽象为:

effective_address = base_address + index * element_size + member_offset

例如访问结构体数组中第 i 个元素的成员,编译器可能用基址寄存器、变址/缩放和常量位移组合计算地址。C 代码:

struct Sample { uint16_t raw; uint16_t status; };
struct Sample samples[8];
uint16_t status = samples[i].status;

编译器最终生成何种寻址指令取决于目标 ISA、优化等级和数据布局。

5. 相对寻址与 PC-relative

PC 相对寻址以程序计数器附近的位置为基准,常用于分支、位置无关代码和访问常量池。它与“基址+变址+位移”不是同一概念,虽然都包含位移量。

6. 需要纠正的原始笔记边界

  • 原笔记中的 BX、SI、BP 是传统 x86 16 位地址计算常见寄存器,并非 ARM/PowerPC/RISC-V 的通用寄存器命名。
  • 现代 x86-64 允许更丰富的 base + index * scale + displacement 表达式。
  • ARM、PowerPC、RISC-V 等 ISA 各自定义 load/store、立即数和 PC-relative 规则;RISC-V 常见 load/store 使用基址寄存器加立即数偏移。
  • “七种寻址方式”是教学分类,不是跨 ISA 的统一标准。

7. 工程实践与验证

  1. 读汇编前先确认目标架构、ABI、指令集版本和汇编语法。
  2. 用编译器生成汇编(如 GCC/Clang 的 -S)观察数组、结构体和指针访问。
  3. 用反汇编和调试器检查有效地址、寄存器值及内存映射。
  4. 检查对齐、访问宽度、地址空间、权限和外设寄存器副作用。
  5. 对性能敏感代码以目标芯片实测为准,不凭“寻址方式名称”推断周期数。

相关专题