指令寻址和数据寻址
“寻址”这个词在本章里指两件完全不同的事:
- 指令寻址:下一条指令的地址从哪来——答案永远落在 PC 上
- 数据寻址:操作数的地址从哪来——答案落在有效地址 EA 上
两者的机制其实是同一套(这是本节最省事的一个发现),但它们的结果送往不同的目的地:一个送进 PC,一个送去取数。分清这一点,4.2 就只剩下一件事要学。
机制
指令寻址:只有两种
顺序寻址:
那个
- 按字编址、单字长指令 →
- 按字节编址、32 位定长指令 →
- 变长指令 →
不是常数,要等译码器确定本条指令长度后才知道(见 4.1.4)
跳跃寻址:由转移类指令给出新的 PC 值。跳跃之后并不是”一直跳”——新值装进 PC 后,机器立刻回到顺序寻址。 所谓”跳跃”只是往 PC 里塞了一个非顺序的值这一个动作。
关联对照:跳跃寻址没有自己的一套方法,它复用数据寻址方式
转移指令的目标地址怎么算?和取操作数地址用的是同一批寻址方式,只是算出的 EA 送进 PC 而不是送去访存:
转移指令写法 用的是哪种寻址方式 送 PC 的值 JMP 2000H直接寻址 JMP *(2000H)间接寻址 主存 2000H 单元的内容 JMP R1寄存器寻址 JMP $+8PC 相对寻址 所以 4.2.2 那十种寻址方式学一遍,指令寻址和数据寻址一起解决。 教材把它们分成两节讲,是按”结果送哪儿”分的,不是按”怎么算”分的。
数据寻址:指令里多一个字段
一旦支持多种寻址方式,指令必须说清用的是哪一种,于是地址码那一半再拆开:
寻址特征字段的位数决定了这台机器最多支持几种寻址方式:
形式地址 A 与有效地址 EA
这是整个 4.2 的核心一对,也是”寻址方式”这个概念存在的全部理由:
| 形式地址 | 有效地址 | |
|---|---|---|
| 在哪 | 写在指令里的那几位 | 算出来的 |
| 是什么 | 计算 EA 的原料 | 操作数真正所在的地址 |
| 谁决定它们的关系 | —— | 寻址方式 |
4.1.2 里指令字长不够用的那场争夺,出路就在这里:当
一个地址要走多少层
用户在 4.2.2 遇到的几乎全部困惑,根子都在拿两个不同层次的地址互相比较。所以先把整条链摆出来——这是本章的第二条主线:
graph TD S["源码符号<br/>L1 / arr / printf"] -->|"汇编器 + 链接器<br/>符号解析·重定位"| A["形式地址 A<br/>(指令里的那几位)"] A -->|"★寻址方式 4.2.2<br/>加寄存器·加位移·再访存"| EA["有效地址 EA<br/>= 逻辑地址"] EA -->|"分段<br/>段基址 + EA"| LIN["线性地址"] LIN -->|"分页 MMU<br/>页表 / TLB"| PA["物理地址"] PA -->|"Cache 划分<br/>标记 组号 块内"| C{"Cache<br/>命中?"} C -->|命中| HIT["取自 Cache"] C -->|缺失| MM["主存译码<br/>片选 + 片内行列"] MM --> CELL["存储单元"] classDef here fill:#ffe6cc,stroke:#d79b00,stroke-width:3px classDef co3 fill:#e1f5fe,stroke:#0288d1 classDef pre fill:#e8e8e8,stroke:#888 class A,EA here class LIN,PA,C,MM,CELL,HIT co3 class S pre
| 层 | 输入 → 输出 | 谁在做 | 在哪一节 |
|---|---|---|---|
| 符号解析 | 符号 → 形式地址 | 汇编器 / 链接器(静态) | 4.1.1 |
| 寻址方式 | 形式地址 → EA | CPU 内的地址计算 | 4.2.2 |
| 分段 | EA → 线性地址 | 段部件 | OS 3.1.4 |
| 分页 | 线性地址 → 物理地址 | MMU + 页表/TLB | 3.6.2 |
| Cache 划分 | 物理地址 → 标记/组号/块内 | Cache 控制器 | 3.5.3 |
| 主存译码 | 物理地址 → 片选 + 行列 | 地址译码器 | 3.3.3 |
用法是一句话:碰到”这是什么地址”的疑问,先定位它在这条链的哪一层。 上下相邻的两层永远是”输出→输入”的关系,不是同一层的两种做法,因此不能拿来比较优劣、也不能互相替代。4.2.2 里所有关于”基址寄存器 vs 段寄存器”的纠结,用这一句就能拆开。
边界
PC 的增量在取指周期就完成,早于执行周期。 所以执行 JMP 时,PC 里装的已经是下一条指令的地址而不是当前指令的地址。PC 相对寻址的基准就是这个已经加过的值——这是 4.2.2 最容易错的一处,也是整章最高频的计算陷阱。
“跳跃寻址”不是一种寻址方式的名字,它是”指令寻址的一种情形”。 具体用哪种方式算目标地址,仍从 4.2.2 那十种里挑。判断题若说”跳跃寻址与相对寻址是同一概念”,错。
顺序寻址的
指令必然从主存(或 Cache)取,但操作数不一定。 操作数可以在寄存器里、可以是立即数、可以在栈顶。“寻址”不等于”访存”——立即寻址和寄存器寻址都不访存。
寻址特征字段的位数是设计参数,不是每台机器都有。 定长格式的 RISC 常常靠操作码本身隐含寻址方式(LW 就是基址+位移,没有别的可能),根本不需要独立的寻址特征字段。
对照速查
| 指令寻址 | 数据寻址 | |
|---|---|---|
| 找的是什么 | 下一条指令的地址 | 操作数的地址 |
| 结果送到 | PC | 送去访存(或直接用) |
| 有哪几种 | 顺序、跳跃 | 十种(见 4.2.2) |
| 算法 | 复用数据寻址的那十种 | —— |
| 概念 | 一句话 |
|---|---|
| 形式地址 | 指令里写着的那几位,是原料 |
| 有效地址 EA | 算完之后操作数真正所在的地址 |
| 寻址方式 | 从 |
| 寻址特征字段 |
| 判断 | 对错 |
|---|---|
| 顺序寻址就是 | ❌(增量 = 指令字长 ÷ 编址单位) |
| 跳跃寻址是一种数据寻址方式 | ❌(是指令寻址的一种情形) |
| 转移指令的目标地址有专门的计算方式 | ❌(复用数据寻址方式) |
| 形式地址就是操作数地址 | ❌(只有直接寻址时才相等) |
| 每种寻址方式都要访存 | ❌(立即、寄存器寻址不访存) |
| 执行转移指令时 PC 里是当前指令地址 | ❌(已经是下一条的地址) |
考点
- 指令寻址(→PC)与数据寻址(→操作数)是两回事,但算法是同一套
- 顺序寻址增量
,按字节编址时不是 1指 令 字 长 编 址 单 位 - 变长指令的 PC 增量要等译码后才确定
- 跳跃寻址只是往 PC 塞一个非顺序值,塞完立刻恢复顺序寻址
- 形式地址
是原料,有效地址 EA 是结果,寻址方式是二者之间的函数 - 寻址特征
位 → 最多 种寻址方式 - 地址翻译链有六层:符号 → 形式地址 → EA → 线性地址 → 物理地址 → Cache 划分 / 主存译码;跨层比较是本章一切混乱的来源
链接
- 🏠 返回总览:计算机组成原理第 4 章:指令系统总览
- ⬅️ 上一节:4.1.5 指令的操作类型
- ➡️ 下一节:4.2.2 常见的数据寻址方式
- 🔗 3.6.2 页式虚拟存储器(地址链的下一层)
- 🔗 3.5.3 Cache 和主存的映射方式(物理地址怎么被切三段)
- 🔗 3.3.3 存储器芯片的地址分配和片选(链的末端)
- 🔗 5.3 指令执行过程(本地资料)(PC 增量发生在取指周期)
- 📖 名词库:第 4 章名词库