Skip to content

有效地址计算

2026 大纲 四(三)寻址方式——有效地址的计算与访存代价一侧。

算完公式还没算完,你手上拿的还是个地址

寻址计算题的错法高度集中,而且不是算错,是提前停手。变址寻址 EA=(I)+A 算出 3000H,很多人到这里就把 3000H 填进答案——可 3000H 是地址,题目问的是操作数,还差 Mem[3000H] 这一步。一整类寻址方式的公式,右边写的都是 EA:

形式地址 A指令给的 按寻址方式字段 M可能经过多次变换 EA一个地址 访存 操作数一个数据

只有两个方式没有中间那一段:立即寻址(操作数就是 A)与寄存器寻址(操作数是 (Ri),本来就在 CPU 里)。除这两种以外,算到 EA 停下就等于交了半份答案。

这一篇处理的正是"从 A 到操作数"这条链上会被问到的四件事:一共碰了几次存储器(访存次数)、相对寻址的加法从哪个基准起算PC 到底是多少)、位移量该按什么口径读(补码还是无符号、要不要符号扩展),以及复合寻址那三段各装什么。四件事各有一条判据,都不需要背表。

交互可视化

加载可视化中...

一、访存次数:一次一次数出来

访存次数不需要记表,按"这条指令一共碰了几次存储器"逐段数即可。一条指令的完整执行最多经过三个访存场合:

场合什么时候发生次数
取指令每条指令都有恒为 1
求有效地址只有间接寻址需要(多重间接则多次)0 或 n
取操作数操作数在存储器里时才需要0 或 1

按这个框架逐种展开:

寻址方式取指令求 EA取操作数合计
立即100(操作数在指令里)1
寄存器100(操作数在寄存器)1
直接1012
寄存器间接10(EA 已在寄存器里)12
相对 / 基址 / 变址10(EA 靠加法算出,不访存)12
一重间接1113
n 重间接1n1n+2

编者注(辨析):偏移寻址三种方式看起来"多了一步计算",却和直接寻址一样只访存 2 次——因为那一步是在 CPU 内部做加法,加法器不碰存储器。真正让访存次数上涨的只有"到内存里再去取一次地址"这一件事。

二、相对寻址:基准与位移量

EA=(PC)+A

式中的 (PC)读取该值那一刻 PC 的内容。PC 的自增发生在取指周期(原因见 指令执行过程),所以等到译码、执行阶段用到它时,里面装的已经是下一条指令的地址:

PC=本条指令首地址+本条指令长度编址单位

分母那一项常被跳过,而它决定了增量到底是多少:

情形PC 增量
定长指令 +编址1单字长指令恰好占一个存储单元
定长指令 +字节编址指令占的字节数2 字节定长指令加 2;32 位定长指令加 4
变长指令本条指令的字节数5 字节的调用指令加 5

中间那一档最容易被漏掉:"定长"不等于"加 1"。同样是 2 字节的定长指令,按字编址加 1、按字节编址加 2,两者差一个单位,目标地址随之整体偏移。

位移量可正可负,用补码表示。当它的位宽小于地址位宽时,参与加法前必须按补码符号扩展到地址位宽。位移量的位宽直接决定转移范围:n 位补码位移量的可达范围是

PC2n1  PC+2n11

反过来用,公式移项即可:A=目标地址PC

至于地址字段该按无符号读还是按补码读,判据是它扮演什么角色,不是它长什么样:绝对地址(直接寻址、间接寻址里的形式地址)按无符号读,因为地址不存在负数;位移量与偏移量(相对、基址、变址)按补码读,因为它们必须能往回指。同一个 E3H,当绝对地址是 227,当 8 位位移量是 29。位宽不足时的扩展方式也跟着角色走——8 位位移量 E3H 扩到 16 位是 FFE3H 而不是 00E3H,用零扩展会把一个小的负位移变成一个很大的正数,目标地址直接跑飞。

还有一层单位问题容易被跳过:位移量的单位未必是字节。有的指令系统把目标地址定义成 (PC)+2+2×OFFSET,那个额外的 ×2 说明 OFFSET 数的是指令条数而不是字节数——这样同样宽的字段能覆盖两倍远的距离,代价是只能跳到指令边界上。算范围时要按题面给的那个公式走,不能默认位移量就是字节偏移。

三、复合寻址

部分机器把基址与变址组合起来,并给变址部分配一个比例因子

EA=(B)+(I)×f×+D

比例因子 f 通常取 1,2,4,8,它的含义是固定的:数组元素的字节数。这一段硬件设计的动机很直接:访问数组元素时,下标 i 与地址偏移之间永远差一个 × 元素宽度的换算。若指令不提供比例因子,编译器就得在每次访问前插入一条移位或乘法指令;提供了比例因子,这一步换算由地址加法器顺手做掉,不占一条指令

三段的分工是固定的:

装什么为什么装它
位移量 D数组首地址首地址是编译期常量,正好放进指令的立即数字段
基址寄存器行偏移 i× 行宽内层循环期间不变,外层每轮更新一次
变址寄存器 ×f列偏移 j× 元素宽内层循环每轮变化,正好由比例因子完成 × 元素宽

对应的地址公式:

addr(a[i][j])=+i××+j××

编译器不会在内层循环里反复做 i× 这个乘法——它把结果预先算好放进基址寄存器,外层每转一轮就加一个行宽。

把第一节那三条判据套上去,复合寻址的访存次数不用另记:(B)(I) 都在寄存器里,×f 与两次加法全部由 CPU 内部的地址加法器完成,求 EA 一次存储器都不碰。

取指 1 + 求 EA 0 + 取操作数 1 = 2 
三段完整走查:同一条指令在各寻址方式下的 EA、由目标地址反求位移量、二维数组元素地址(想核对自己每一步的基准值、进制换算与三段分配取得对不对时展开)

(一)同一条指令在各寻址方式下的 EA。 设某机按字节编址、指令定长 4 字节;本条指令首地址 2000H,故取指后 PC=2000H+4=2004HR1=5000H(用作基址寄存器)、R2=0030H(用作变址寄存器);形式地址 A=0100H;存储器 Mem[0100H]=6000HMem[5000H]=7777HMem[2104H]=4444HMem[5100H]=8888HMem[0130H]=3333HMem[6000H]=9999H

寻址方式EA 的算法EA操作数总访存
立即不产生 EA0100H1
寄存器(R1不产生 EA5000H1
直接EA=A0100H6000H2
间接EA=Mem[A]6000H9999H3
寄存器间接(R1EA=(R1)5000H7777H2
相对EA=PC+A=2004H+0100H2104H4444H2
基址(B=R1EA=(B)+A=5000H+0100H5100H8888H2
变址(I=R2EA=(I)+A=0030H+0100H0130H3333H2

三处值得回看:相对寻址那一行用的是 2004H 而不是 2000H(按字节编址、4 字节定长指令,PC 增量是 4);间接寻址是唯一访存 3 次的,多出来的那次花在"到 0100H 去把真正的地址读回来";立即与寄存器两行的 EA 栏是空的,因为它们不产生存储器地址。

(二)由目标地址反求位移量。 某转移指令位于 3000H,本条指令占 2 字节,要跳到 2FC0H

PC=3000H+2=3002H,A=2FC0H3002H=42H

写成 8 位补码即 BEH。回代验算:3002H+(42H)=2FC0H ✓。顺带看一眼范围:以 3002H 为基准、8 位补码位移,可达 2F82H ~ 3081H,目标 2FC0H 落在其中,位移量装得下。

(三)二维数组元素的地址。 int a[50][30],每个元素 4 字节,按行优先存放,数组首地址 00500000H,求 a[7][12] 的地址与三段分配。

行宽(一整行占多少字节)=30×4=120 字节;偏移量 =7×120+12×4=840+48=888=378H;地址 =00500000H+378H=00500378H

来源
位移量 D00500000H数组首地址,编译期常量
基址寄存器 (B)7×120=840行偏移,外层循环每轮 +120
变址 (I)×f12×4=48列偏移,f=4 即元素字节数

反过来读也成立:看到比例因子是 4,就知道元素占 4 字节;再由数组的列数算出行宽,基址寄存器里装的必然是 i× 行宽。

考点速记

  1. 所有公式算出来的都是 EA(一个地址),取操作数还差 Mem[EA];访存次数按取指恒 1 + 求 EA(只有间接才需要)+ 取操作数(在存储器里才需要)三个场合逐一数——数的是碰了几次存储器,不是算了几次加法
  2. 相对寻址的基准是 PC 而非本条首址,增量分按字编址加 1 / 按字节编址加指令字节数 / 变长加本条字节数三档;位移量按补码读,位宽不足时须符号扩展,且单位未必是字节。
  3. 复合寻址 EA=(B)+(I)×f+D 三段固定分工(位移量装首地址、基址装行偏移、变址乘比例因子装列偏移),比例因子 = 元素字节数段数多少不影响访存次数,仍是 2 次,叠一层间接才变 3 次。

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

  • 算完 EA 就停手(2013-17)。给出变址寄存器内容 1000H、形式地址 2000H,再给一串存储单元的内容,问"变址寻址下访问到的操作数"。EA=1000H+2000H=3000H 只是半程,答案是 Mem[3000H]=4000H。四个选项恰好把这条链上的每一站都摆了出来——寄存器内容、形式地址、EA、操作数,停在哪一站就选中哪一个错项。
  • 相对寻址的基准取错(2009-16)。转移指令在 2000H、占 2 字节、按字节编址、每取一个字节 PC 加 1、位移量 06H。基准不是 2000H 而是取完整条指令之后的 PC =2002H,目标地址 =2008H。选项里 2006H(用本条首址)、2007H(只加了一次)、2009H(多加了一次)把三种取错基准的方式全列齐了。判断增量时先问两句:指令占几个字节、按什么编址
  • 位移量的单位不是字节(2013-44)。题面给的公式是"转移目标地址 =(PC)+2+2×OFFSET、顺序执行下条地址 =(PC)+2"。由后一句可知 16 位指令占 2 个地址单元,故按字节编址;由前一句里的 ×2 可知 OFFSET 数的是指令条数,所以 8 位补码的 OFFSET 向后最多跳 128 条指令(不是 128 字节,也不是 127 条)。这道题两问都是从给定公式反推口径,一个字都不能默认。
  • 复合形式的偏移地址反求下标(2018-18)。double 数组首址 2000H、变址寄存器存下标、偏移地址 = 变址值 × sizeof(double),某次取到的元素地址是 2100H。(2100H2000H)÷8=256÷8=32。关键在先把十六进制差值换成十进制再除,以及 sizeof(double) 是 8 不是 4。
  • 基址寻址叠上补码与大小端(2019-15)。形式地址 FF12H 用补码表示、要符号扩展成 32 位 FFFFFF12H,与基址 F0000000H 相加得 EFFFFF12H——这里正是"零扩展会跑飞"的实例:若扩成 0000FF12H,结果是 F000FF12H,恰好就是错项 A。算出的 EA 是操作数首字节的地址,而题问的是 LSB(最低有效字节)的地址:大端方式下最低有效字节排在最后,4 字节操作数的 LSB 在 EFFFFF12H + 3 = EFFFFF15H。三步——符号扩展、地址相加、按端序定位——错一步就落进一个错项。
  • 由指令格式反推转移目标地址的范围(2010-43)。16 位机、按编址、单字长指令,所以 PC 增量是 1 而不是 2;相对寻址的位移量取自一个 16 位寄存器、按补码,于是目标地址范围是 (PC)+132768(PC)+1+32767。"定长不等于加 1"这条在这里正好反过来用:它确实加 1,但理由是按字编址,不是因为定长。

易错:把 EA 当操作数交卷。除立即与寄存器两种方式外,公式右边一律是地址,还差一次 Mem[EA]

易错:相对寻址用本条指令首地址当基准。PC 在取指周期就已自增,用到它时装的是下一条指令的地址。

易错:见到"定长指令"就认为 PC 加 1。加 1 的条件是按字编址;按字节编址要加指令占的字节数。

易错:把位移量按无符号读,或位宽不足时做零扩展。位移量是补码,必须符号扩展。

易错:把偏移寻址"多做了一次加法"算进访存次数。那次加法在 CPU 内部,加法器不碰存储器。

教材出处
  • 袁春风《计算机组成与系统结构(第 3 版)》§4.2.3 寻址方式:有效地址在无虚拟存储时即物理地址、变址寻址中元素占 4 字节时变址寄存器每次加 4、前变址与后变址的有效地址表达式(印刷页 p94~96)
  • 唐朔飞《计算机组成原理(第 3 版)》§7.3 寻址方式:间接寻址在执行阶段需访存两次或多次、寄存器寻址在执行阶段无须访存、相对寻址的位移量用补码表示且 8 位位移的范围为 (PC)+127(PC)128、基址与变址结合时 EA=A+(IX)+(BR)(印刷页 p313、p316)

相关知识

数据寻址方式指令执行过程指令格式设计与扩展操作码

真题练习