# 寻址模式

> 计算机科学 · CIE A-Level
> 来源: https://www.owlsprep.com/zh/study/cie-9618-u4-addressing-modes/

本模块讲解CPU指令的常见寻址模式，每种模式如何计算数据/指令的有效内存地址，以及它们的实际使用场景，适用于备考CIE A-Level 9618第4卷。

**先修:** [指令格式与机器语言](https://www.owlsprep.com/zh/study/cie-9618-u4-instruction-formats/); [内存组织基础](https://www.owlsprep.com/zh/study/cie-9618-u4-memory-organisation/)

## 学习目标

- 识别CPU指令集中使用的不同寻址模式
- 解释每种寻址模式在常见场景下的用途
- 计算任意给定寻址模式下的有效内存地址
- 为特定编程任务选择合适的寻址模式

## 立即寻址与直接寻址

**寻址模式** — 规定CPU如何从汇编指令的地址字段计算出目标数据或指令的有效内存地址的规则。

**立即寻址** — 指令要使用的值直接存储在指令本身中，不需要额外的内存访问就能获取操作数。

*例:* 用于向寄存器加载常量值。

**例题:** 将立即数15加到寄存器R0中。请说明指令地址字段存储的内容，以及是否需要额外的内存访问。

1. 1. 在立即寻址中，操作数就是值本身，直接存储在地址字段中。
2. 2. 获取指令后不需要额外的内存访问，因为该值已经嵌入在指令中。
3. 结果：地址字段存储15，需要0次额外内存访问。

**直接寻址** — 指令的地址字段存储目标数据的完整有效内存地址，CPU只需一次额外内存周期就能直接从该地址获取数据。

*例:* 用于访问单个固定内存变量。

**例题:** 将内存地址1000处存储的值加载到寄存器R1中。指令的地址字段存储什么值？

1. 1. 在直接寻址中，地址字段等于目标数据的有效地址。
2. 2. 目标数据在地址1000处，因此地址字段恰好存储1000。
3. 结果：地址字段值 = 1000，需要1次额外内存访问来获取数据。

## 间接寻址

**间接寻址** — 指令的地址字段存储的是一个内存位置（或寄存器）的地址，该位置存储了目标数据的完整有效地址，需要多次内存访问才能获取数据。

*例:* 用于指针、动态数据，以及访问大容量内存空间。

**例题:** 一条指令使用内存间接寻址，地址字段值为2000，内存位置2000中存储的值为5000。目标数据的有效地址是多少，需要多少次内存访问？

1. 1. 获取指令后，CPU首先读取地址字段值2000。
2. 2. 第一次额外内存访问：获取存储在2000处的有效地址，即5000。
3. 3. 第二次额外内存访问：从有效地址5000获取目标数据。
4. 结果：有效地址 = 5000，需要2次额外内存访问。

> **tip**
>
> 寄存器间接寻址使用寄存器而非内存来存储有效地址，只需要1次额外内存访问，因此比内存间接寻址更快。

## 变址寻址

**变址寻址** — 有效地址由存储在指令中的常量基偏移量加上专用变址寄存器中存储的值计算得到。

*例:* 访问数组元素最高效的寻址模式。

**例题:** 一个数组从基地址200开始，要访问第3个元素（0索引，index = 2），变址寄存器X存储的值为2，请计算有效地址。

1. 1. 变址寻址的有效地址公式为：
2. $$EA = \text{Base Offset} + \text{Index Register Value}$$
3. 2. 代入给定值：基偏移量 = 200，变址寄存器值 = 2。
4. 3. 计算: $EA = 200 + 2 = 202$。
5. 结果：数组第3个元素的有效地址是202。

> **info**
>
> 使用变址寻址遍历数组时，每次循环只需递增变址寄存器的值，指令的基偏移量永远不需要修改，因此循环效率很高。

## 相对寻址

**相对寻址** — 有效地址由存储在指令中的偏移量加上程序计数器（PC）的当前值计算得到。

*例:* 用于分支跳转和跳转到附近指令。

**例题:** 当前分支指令存储在地址100，长度为4字节。获取指令后，PC的值为104，分支偏移量为+12，请计算分支目标的有效地址。

1. 1. 相对寻址的有效地址公式为：
2. $$EA = PC + \text{Offset}$$
3. 2. 记住，获取指令后PC会自动更新为指向下一条指令，因此我们使用这个更新后的PC值。
4. 3. 代入值: $EA = 104 + 12 = 116$。
5. 结果：分支目标的有效地址为116。

> **tip**
>
> 相对寻址支持位置无关代码：整个程序可以移动到不同的内存位置而不需要修改分支指令，因为偏移量始终相对于当前PC。

## 常见错误

- **错误做法:** 混淆立即寻址和直接寻址，认为地址字段中的值始终是地址。
  - 原因: 立即寻址将地址字段的值作为实际操作数，而非地址。
  - 正确做法: 确认指令需要的是常量值（立即寻址）还是来自内存的数据（直接寻址）。
- **错误做法:** 在相对寻址计算中使用当前指令的地址。
  - 原因: PC在计算有效地址前已经更新为指向下一条指令，因此这种做法会得到错误的偏移量。
  - 正确做法: 始终将偏移量加到更新后的PC值上（当前指令地址 + 指令长度）。
- **错误做法:** 认为内存间接寻址只需要一次额外内存访问。
  - 原因: 一次访问用于获取有效地址，第二次用于获取实际数据。
  - 正确做法: 内存间接寻址记为2次额外内存访问，寄存器间接寻址记为1次。
- **错误做法:** 在变址寻址访问数组时，将索引值作为完整的有效地址。
  - 原因: 考生忘记加上作为指令偏移量存储的数组基地址。
  - 正确做法: 始终要将数组的基偏移量加上变址寄存器的值才能得到有效地址。
- **错误做法:** 认为立即寻址需要一次额外内存访问来获取操作数。
  - 原因: 操作数直接嵌入在指令本身中，因此不需要额外访问。
  - 正确做法: 获取指令后，立即寻址需要0次额外内存访问。

## 速查表

| 寻址模式 | 有效地址 | 额外内存访问次数 | 常见使用场景 |
| --- | --- | --- | --- |
| 立即寻址 | 值存储在指令中 | 0 | 加载常量 |
| 直接寻址 | EA = 地址字段值 | 1 | 访问固定变量 |
| 内存间接 | EA = (地址字段)指向位置存储的值 | 2 | 访问指针/动态数据 |
| 变址寻址 | EA = 基偏移量 + 变址寄存器值 | 1 | 访问数组元素 |
| 相对寻址 | EA = 更新后的PC + 偏移量 | 0 | 分支/跳转 |

## 下一步

寻址模式是CPU指令集设计的核心组成部分，理解寻址模式对于解读汇编指令、解释CPU内存访问行为，以及回答CIE 9618中处理器基础部分的常见考题至关重要。本主题建立在你已有的指令格式和内存组织知识基础上，是汇编编程和理解指令执行过程中CPU如何与内存交互的基础。寻址模式的问题经常出现在第4卷的选择题和拓展回答题中，因此掌握每种模式的有效地址计算对于考试成功至关重要。

- [RISC vs CISC](https://www.owlsprep.com/zh/study/cie-9618-u4-risc-vs-cisc/)
- [流水线技术](https://www.owlsprep.com/zh/study/cie-9618-u4-pipelining/)
- [多核处理器](https://www.owlsprep.com/zh/study/cie-9618-u4-multicore-processors/)

---

来自 [OwlsPrep](https://www.owlsprep.com) —— A-Level / IB / AP / IGCSE 免费学习指南，依据官方考纲编写。原页面：https://www.owlsprep.com/zh/study/cie-9618-u4-addressing-modes/
