Skip to content

数据寻址方式

2026 大纲 四(三)寻址方式

一串二进制不会告诉你它是数还是地址

内存里放着 0100H。它是数值 256,还是地址 0100H?这一位信息不在数据里——它在指令的寻址方式字段 M(寻址特征位)里。M 说立即数它就是 256,M 说直接寻址它就是地址。CPU 在译码阶段读出 M,才知道接下来该怎么解释指令里那个地址字段。那两三位看起来不起眼的寻址方式位因此一位都不能省:没有它,地址码根本无法解释

于是问题变成:为什么值得给 M 留出好几位、支持这么多种解释方式?因为指令里的地址字段同时被三个互相拉扯的要求盯着——

  • 地址码要短:它直接决定指令长度,而指令长度决定取指要访存几次;
  • 寻址范围要大:操作数可能落在主存任何地方,也可能在寄存器里、在指令里、在栈顶;
  • EA 计算要简单:这一步在指令的执行路径上,每多一次加法或访存都要当场付出时间。

三个要求不可能同时满足,所以没有"最好的寻址方式",只有铺开在这个三角里的一整条折中谱系。立即寻址把操作数直接塞进指令——不访存最快,但装不下大数;间接寻址把地址放进主存单元——寻址范围不再受指令长度限制,代价是多访存一次;寄存器间接寻址再把这个存地址的地方从主存搬进 CPU——省掉那次访存,代价是占用一个寄存器。读下面每一种方式时都可以回来问一句:它在这个三角里站在哪、拿什么换了什么

先约定三个记号:A 是指令里的地址字段,称形式地址(X) 表示"取 X 的内容";有效地址 EA 是操作数所在存储单元的地址。还要注意 EA 不一定是物理地址——无虚拟存储机制时 EA 就是主存物理地址,有虚拟存储机制时 EA 是虚拟地址,之后还要再经一次地址转换。寻址方式讨论的一律是 EA 这一层。

交互可视化

加载可视化中...

一、先分两类:指令寻址与数据寻址

"寻址"这个词底下压着两件不同的事:

类别要确定的是有哪几种
指令寻址下一条指令的地址从哪来顺序寻址:由 PC 自增自动形成;跳跃寻址:由转移类指令给出目标地址
数据寻址指令里的形式地址该怎么解释成操作数立即、直接、间接、寄存器、寄存器间接、变址、基址、相对、堆栈、隐含

关键的一层关系是:跳跃寻址的目标地址,仍然要靠数据寻址的那几种方式算出来——JMP 7 这种把绝对地址写在指令里的是直接寻址,(PC) + A 这种给出相对位移的是相对寻址,还可以把目标地址存在某个单元里用间接寻址取出。所以两类不是并列的清单:指令寻址决定"走哪条路",数据寻址提供"路标怎么读"

区分数与地址的判据则全部来自指令格式里的寻址方式字段:

[ OP  M  A ]

CPU 在译码阶段读出 M 字段,据此决定接下来怎么解释 A。这也解释了那 2~3 位"看起来不起眼"的字段为何必须存在——没有它,地址码就无法解释

二、各数据寻址方式

方式有效地址 / 操作数收益与代价
立即操作数 =A立即数取操作数无须访存,速度最快;立即数位宽受指令字长限制,装不下大数
直接EA=A(直接地址、绝对地址)不需要计算;地址空间受 A 的位数限制,这是它最主要的局限
间接EA=(A),常用 @ 标志突破指令中地址字段的位宽限制;代价是多访存一次。可多重间接;经典用途是子程序返回
寄存器操作数 =(Ri)寄存器编号比存储地址短得多 指令短;操作数已在 CPU 内,执行阶段无须访存
寄存器间接EA=(Ri)地址码长度同寄存器寻址,但 EA 来自寄存器而非指令字段,寻址范围不受指令长度限制;执行阶段访存一次
变址EA=(I)+AA 给基准地址(数组首址),变址寄存器 I 给偏移。循环中变的是寄存器,不是指令
基址EA=(B)+A基准由基址寄存器 B 给出,A 是各指令自带的偏移量。程序重定位的原理
相对EA=(PC)+A位移量可正可负、用补码;8 位位移量的范围是基准值的 128+127。带来位置无关代码
堆栈操作数隐含在栈顶,由 SP 访问指令中无须给出地址。PUSH X 调整 SP 后写栈顶,POP X 读栈顶后反向调整。零地址运算指令的基础
隐含操作码隐含指出一地址指令的另一操作数隐含为累加器内容、栈操作指令的操作数隐含为栈顶元素

若任意通用寄存器都可用作基址/变址寄存器,指令中必须给出寄存器编号并标明用途;若机器设有专门的基址寄存器,则无须在指令中指出。

间接寻址:两级箭头就是它的收益与代价

图 4.1 单级间接寻址

图 4.1 单级间接寻址

有效地址不再受指令中地址字段位宽的限制(存储单元有多宽,地址就能有多宽),但取一次操作数要多访存一次。子程序返回是它的经典用途:把返回地址预先写进某个固定单元,子程序末尾用一条 JMP @A 就能返回调用点——同一条指令,不同调用场合返回到不同地方。

寄存器间接寻址是同一个思路挪了个位置:存放地址的那个地方从主存搬进了 CPU。两者的差别全在代价上——间接寻址的 EA 来自主存单元,取一次操作数共访存 2 次(取地址 + 取数),地址位宽受存储字长限制;寄存器间接寻址的 EA 来自寄存器,只访存 1 次,位宽受寄存器位数限制,代价是占用一个寄存器。

变址寻址:循环里变的是寄存器

图 4.2 数组元素的变址寻址

图 4.2 数组元素的变址寻址

图中 A 给定数组首地址,变址器 I 里存的是元素下标。按字节编址、元素占 1 字节时,for (i = 0; i < N; i++) { x = a[i]; … } 的循环体中 I 从 0 开始每轮加 1,取数指令本身一个位都不用改;元素占 4 字节则每轮加 4。有的机器(如 Intel 8086)还提供自动变址,存取一个数据后变址寄存器按数据长度自动增减,连"加 4"这条指令都省了。

基址寻址:改一个寄存器,整个程序就搬走了

图 4.3 基址寻址过程

图 4.3 基址寻址过程

B 由操作系统在程序装入时写入、运行期不再改动;变的是 A。整个程序搬到内存别处,只需改 B 一个寄存器的值,所有指令里的 A 一个都不用动——多道程序环境下,这条性质是把程序装到任意空闲区域的前提。

三、偏移寻址:三兄弟的统称

变址、基址、相对三种方式形式完全一致——都是"某个寄存器的内容加上一个形式地址",因此教材把它们统称为偏移寻址。区别只在那个寄存器是谁,以及谁固定、谁变化

寄存器是谁不变谁在变谁来改用途
变址变址寄存器 I形式地址 A(数组首址)寄存器 I(下标)程序员 / 编译器数组、表格的顺序访问
基址基址寄存器 B寄存器 B(程序起始地址)形式地址 A(各指令自带偏移)操作系统(装入时设定)程序重定位
相对程序计数器 PC二者都随位置浮动位移量 A 固定写死编译器 / 汇编器转移指令、位置无关代码

有些指令系统还把基址和变址结合起来,形成基址加变址寻址

EA=A+(I)+(B)

三段各司其职,正好对应二维数组访问的三个成分。展开算例见 有效地址计算

四、间接与变址的结合

变址寻址还能与间接寻址组合,先后顺序不同结果不同:

名称先做什么有效地址对应的 C 语义数据长什么样
前变址(先变址后间址)先算 A+(I),再对结果间接取一次EA=(A+(I))取出指针数组的第 i 个指针所指的对象A 处是一串指针
后变址(先间址后变址)先从 A 间接取出一个地址,再加 (I)EA=(A)+(I)先取出基址指针,再偏移 iA 处是一个指针,指向数组
同一组数据在前后变址下差出多远:两条路各走一遍(怀疑自己把先后顺序记反了时展开)

I=4A=200HMem[200H]=1000HMem[204H]=2000H

  • 后变址:先间接取内容,再加变址值 —— EA=Mem[200H]+4=1000H+4=1004H
  • 前变址:先加变址值,再间接取内容 —— EA=Mem[200H+4]=Mem[204H]=2000H

同一组条件,结果一个在 1004H、一个在 2000H,差得很远。可见这两种方式不是写法差异而是语义差异:区分办法只有一条——看加法发生在间接取内容之前还是之后

考点速记

  1. 寻址先分两类:指令寻址(顺序 / 跳跃)与数据寻址(十种);跳跃寻址的目标地址仍由数据寻址方式给出。多种方式并存是在地址码长度、寻址范围、计算与访存代价这个三角里铺开的折中谱系。
  2. 一串二进制是数还是地址,由指令的寻址方式字段 M 决定,数据本身不携带这个信息。
  3. 变址、基址、相对统称偏移寻址,形式都是"寄存器内容 + 形式地址";变址与基址的"谁变谁不变"恰好相反——前者服务数组遍历、后者服务程序重定位;相对寻址的基准是下一条指令的地址,位移量用补码

这一节在真题里被考过的形式

  • 给出偏移寻址的定义,问哪一种不属于它(2011-16)。判据就一句:能不能写成"某寄存器内容 + 形式地址"。基址、变址、相对都能,间接寻址不能——它的 EA 直接来自主存单元,全程没有寄存器参与相加。相对寻址是这道题里被误排除得最多的一项,原因是"PC 听起来不像普通寄存器";但定义只看形式,不看那个寄存器叫什么名字。
  • 问哪种寻址方式适合按下标顺序访问一维数组(2017-15)。答变址。理由不是"变址听起来像数组",而是数组遍历中首址不变、下标在变,变址寻址恰好把不变的那个放在指令的形式地址里、把变的那个放在寄存器里,于是循环体内的取数指令一个位都不用改
  • 同一个寄存器编号,里面可能是操作数也可能是操作数地址,CPU 凭什么区分(2023-17)。答寻址方式——寄存器寻址取其内容当操作数,寄存器间接寻址取其内容当地址。这问的正是本篇开篇那句话:解释权在指令不在数据,所以答案既不可能是"寄存器编号",也不可能是"寄存器的内容"。
  • 给一段真实的 x86 机器代码,判断某条指令用的是哪种寻址方式(2023-44)。jmp/jge 这类短跳转的机器码里跟的是一个字节的位移量而非绝对地址,是相对寻址mov [ecx+edx*4+00422000h], 0Ah 的源操作数 0Ah 直接写在指令中,是立即寻址。这类题不考定义,考的是从机器码的形态上把它认出来——跟在操作码后面的到底是位移量、绝对地址,还是一个常数。

易错:把相对寻址排除出偏移寻址。PC 也是寄存器,EA=(PC)+A 完全符合"寄存器内容 + 形式地址"。

易错:把变址和基址的"谁变谁不变"记反。变址是形式地址固定(数组首址)、寄存器在变(下标);基址是寄存器固定(OS 装入时设定)、形式地址在变(每条指令自带偏移)。

易错:以为数据本身能看出是地址还是数值。解释权只在寻址方式字段手上。

易错:把前变址与后变址记反。判据只有一条——加法发生在间接取内容之前(前变址,EA=(A+(I)))还是之后(后变址,EA=(A)+(I))。

教材出处
  • 袁春风《计算机组成与系统结构(第 3 版)》§4.2.3 寻址方式:地址码短与寻址空间大之间的矛盾、立即/直接/间接/寄存器/寄存器间接寻址的定义(印刷页 p94);变址寻址与数组遍历、前变址与后变址、相对寻址的位移量为带符号整数、基址寻址与偏移寻址的统称、隐含寻址(印刷页 p95~96);图 4.1 单级间接寻址(p94)、图 4.2 数组元素的变址寻址(p95)、图 4.3 基址寻址过程(p96)
  • 唐朔飞《计算机组成原理(第 3 版)》§7.3.1 指令寻址:指令寻址分顺序寻址与跳跃寻址,顺序寻址通过 PC 加 1 自动形成下一条指令地址、跳跃寻址通过转移类指令实现,跳跃寻址的转移地址形成方式见直接寻址与相对寻址(印刷页 p310)
  • 同上 §7.3 寻址方式:间接寻址用于子程序返回、寄存器寻址与寄存器间接寻址的比较(印刷页 p313);变址寻址求 N 个数平均值的程序对比、自动变址、基址加变址的组合、相对寻址位移量用补码表示且 8 位位移的范围为 (PC)+127(PC)128(印刷页 p316)

相关知识

有效地址计算指令格式设计与扩展操作码指令系统的基本概念指令执行过程

真题练习