寻址方式是指令获取操作数的方式,决定了操作数的来源(指令中 / 寄存器中 / 内存中)和地址的计算方法。不同的寻址方式在灵活性、执行效率与代码密度之间权衡。
寻址方式总体上分为两大类:指令寻址(下一条指令在哪)与数据寻址(本条指令的操作数在哪)。
程序计数器 PC 自动加上本条指令的长度,指向下一条指令:
PC ← PC + 指令长度
按顺序执行下一条指令
通过转移指令改变 PC,使执行流跳转到目标地址:
PC ← 目标地址
包括:
- 无条件跳转(JMP)
- 条件跳转(BEQ, BNE 等)
- 调用(CALL)与返回(RET)
操作数直接包含在指令中,无需访问内存。
OP #立即数
MOV R1, #100 → R1 ← 100
ADD R1, R2, #5 → R1 ← R2 + 5
指令中的地址码 就是操作数的内存地址:
OP A (EA = A)
MOV R1, [1000] → R1 ← M[1000]
ADD R1, [2000] → R1 ← R1 + M[2000]
地址码指向的单元中存放的是有效地址:
OP [A] (EA = M[A])
MOV R1, [[1000]]
假设 M[1000]=2000, M[2000]=999
→ R1 ← M[M[1000]] = M[2000] = 999
操作数在寄存器中,速度最快:
OP R1
ADD R1, R2, R3 → R1 ← R2 + R3
MOV R1, R2 → R1 ← R2
寄存器中是有效地址,操作数在内存中:
OP [R1] (EA = (R1))
MOV R1, [R2] → R1 ← M[R2]
若 R2=1000,则 R1 ← M[1000]
基址寻址:有效地址 = 基址寄存器 + 形式地址,基址寄存器由操作系统设置,用于程序重定位。
EA = (BR) + A
MOV R1, [BR+100]
若 BR=1000,则 R1 ← M[1100]
变址寻址:有效地址 = 变址寄存器 + 形式地址,变址寄存器由用户修改,常用于数组遍历。
EA = (IX) + A
MOV R1, [A+IX]
若 A=1000, IX=50,则 R1 ← M[1050]
EA = (BR) + (IX) + A,用于二维数组访问。有效地址 = PC + 形式地址,且 PC 已更新为下一条指令的地址:
EA = PC + A
BEQ R1, R2, offset
若 R1=R2,则跳转到 PC + offset
操作数隐含在栈顶,由栈指针 SP 指示:
PUSH:SP ← SP-1, M[SP] ← 数据
POP :数据 ← M[SP], SP ← SP+1
| 寻址方式 | 有效地址 EA | 访存次数 | 速度 | 灵活性 |
|---|---|---|---|---|
| 立即 | 无(操作数在指令中) | 0 | 最快 | 低 |
| 直接 | $EA = A$ | 1 | 快 | 低 |
| 间接 | $EA = M[A]$ | 2 | 慢 | 高 |
| 寄存器 | 无(操作数在 Rn) | 0 | 最快 | 中 |
| 寄存器间接 | $EA = (R)$ | 1 | 较快 | 高 |
| 基址 | $EA = (BR)+A$ | 1 | 较快 | 高 |
| 变址 | $EA = (IX)+A$ | 1 | 较快 | 高 |
| 相对 | $EA = (PC)+A$ | 1 | 较快 | 高 |
| 堆栈 | $EA = (SP)$ | 1 | 较快 | 低 |
1. 立即寻址:addi $t0, $t1, 100
2. 寄存器寻址:add $t0, $t1, $t2
3. 基址寻址:lw $t0, 100($t1) → $t0 ← M[$t1+100]
4. PC 相对寻址:beq $t0, $t1, offset
5. 伪直接寻址:j target(跳转地址 = PC高4位 | target<<2)
1. 立即寻址:MOV EAX, 100
2. 寄存器寻址:MOV EAX, EBX
3. 直接寻址:MOV EAX, [0x1000]
4. 寄存器间接:MOV EAX, [EBX]
5. 基址寻址:MOV EAX, [EBX+100]
6. 变址寻址:MOV EAX, [ESI*4+100]
7. 基址+变址:MOV EAX, [EBX+ESI*4+100]
↑ 以上为站内 HTML 相对链接(纯网页可浏览);本页右上「在 Obsidian 中打开」跳回源笔记。