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