目录
一、指令寻址
二、数据寻址
1.立即寻址
2.直接寻址
3.间接寻址
4.隐含寻址
5.寄存器寻址
6.寄存器间接寻址
7.基址寻址
8.变址寻址
9.相对寻址
10. 堆栈寻址
寻址方式是寻找指令或操作数有效地址的方式,也就是指确定本条指令的数据地址,以及下一条将要执行的指令地址的方法。
寻址方式分为指令寻址和数据寻址两大类。
一、指令寻址
指令寻址是指寻找下一条将要执行的指令地址。指令寻址方式有两种:一种是顺序寻址方式,另一种是跳跃寻址方式。
-
顺序寻址:可通过 程序计数器(PC)加1,自动形成下一条指令的地址。
-
跳跃寻址:通过 转移类指令 实现。跳跃寻址是指下一条指令的地址码不是由 PC 给出的,而是本条指令给出的。
注意:这里所说的 “ PC 加1 ” 并不是 PC 一定会加 “1” 这个数值,而是要加当前指令占据的地址长度,从而总能得到下一条指令的地址;例如,如果机器按字节编址,当前指令字长是 4 个字节,那么执行这条指令后 PC = PC + 4。
二、数据寻址
数据寻址是指确定本条指令中所有操作数的地址,即寻找指令要操作的数据的地址。
指令中的地址字段并不一定代表操作数的真实地址,称为形式地址(A)。结合形式地址和寻址方式,可计算出操作数在存储器中的真实存储地址,这一地址称为有效地址(EA)。
由于地址字段表达的含义不同,可以有多种不同的寻址方式:比如 直接寻址、间接寻址、寄存器寻址 等。此外,如果通过将某个寄存器内容与一个形式地址相加而生成有效地址,这种方式称为 偏移寻址。偏移寻址又包括基址寻址、变址寻址 和 相对寻址。
数据寻址方式的种类较多,通常在指令中设一个字段,用来指明属于哪种寻址方式。由此可得指令的格式如下:
操作码的位数决定了指令的条数,寻址特征和形式地址共同决定了可寻址的范围。
-
若为立即寻址,则形式地址的位数决定了数的范围。
-
若为直接寻址,则形式地址的位数决定了可寻址的范围。
-
若为寄存器寻址,则形式地址的位数决定了通用寄存器的最大数量。
-
若为寄存器间接寻址,则寄存器字长决定了可寻址的范围。
下面是常见数据寻址方式的详细介绍。
1.立即寻址
指令的地址字段指出的不是操作数的地址,而是操作数本身,称为 立即寻址,又称为 立即数寻址。 数据采用补码形式存放。
上面图中 # 表示立即寻址特征,A 就是操作数本身。
-
优点:指令在执行阶段不访问主存,指令执行速度快。
-
缺点:A的位数限制了立即数的范围,只适合操作数较小的情况。
2.直接寻址
指令格式的地址字段中直接指出操作数在内存中的地址,就称为 直接寻址。即
-
优点:指令简单,不需要专门计算操作数的地址,指令在执行阶段仅访问一次主存。
-
缺点:A 的位数决定了操作数的寻址范围,操作数的地址不易修改。
3.间接寻址
间接寻址 是相对于直接寻址而言的,是指指令的地址字段给出的形式地址不是操作数的真正地址,而是操作数地址所在的存储单元地址;也就是 “地址的地址”,即
这里用(A)来表示地址为 A 的存储单元所存放的数据。
间接寻址也可以分为多次进行,简称 多次间址。对于两次间接寻址,地址 A 存储的内容 A~1~ 还不是有效地址 EA,地址 A~1~ 对应的存储单元所存储的内容才是 EA。这时可以用存储字的首位来标记间接寻址是否结束:存储字首位为 “1” 时,说明还需要继续寻址;为 “0” 时,寻址结束,当前存储字存放的就是 EA。
-
优点:可扩大寻址范围(有效地址 EA 的位数大于形式地址 A 的位数);便于编制程序。
-
缺点:指令在执行阶段要多次访存(一次间址需两次访存,多次间址需多次访存)。
4.隐含寻址
隐含寻址 是指指令字中不直接给出操作数的地址,而是隐含在某个寄存器中(通过操作码表示)。比如,一地址指令中,对于加法操作就可以只给出一个操作数的地址,而把另一个操作数放在 ACC 中;这时 ACC 就是另一个操作数的地址。
因为隐含寻址可以省去指令字中的一个地址,所以这种方式可以缩短指令字长,在计算机的指令集中被广泛使用。
5.寄存器寻址
寄存器寻址 的指令在执行时所需的操作数来自寄存器,运算结果也写回寄存器;地址码字段直接指出了寄存器的编号,即
这样,指令执行期间不需要访问主存,减少了执行时间;而且计算机中寄存器数量是有限的,所以地址字段只需要用很少的二进制位指明寄存器编号即可,节省了存储空间。因此寄存器寻址在计算机被广泛应用。
-
优点:指令在执行阶段不访问主存,只访问寄存器,指令字短且执行速度快。
-
缺点:寄存器的价格昂贵,且数量有限。
6.寄存器间接寻址
如果寄存器中不是直接给出操作数,而是操作数的内存地址,那么就称为 寄存器间接寻址。即
这是寄存器寻址和间接寻址的结合。跟寄存器寻址相比,指令的执行阶段还需要访问主存;跟间接寻址相比,则可以少一次对主存的访问。
-
优点:获得操作数地址的速度较快;寄存器编号较短,可有效减少操作数字段的位数。
-
缺点:寄存器数量有限;指令的执行阶段需要访问主存(因为操作数在主存中)。
7.基址寻址
基址寻址 是一种偏移寻址的方式,需要设有基址寄存器 BR ;将基址寄存器 BR 的内容(基地址)加上指令中的形式地址,就可以形成操作数的有效地址。即
其中基址寄存器既可采用专用寄存器,也可采用通用寄存器。采用专用基址寄存器 BR ,使用时不用明确指出,只需要指令中的寻址特征反映出是基址寻址即可,这是 隐式 基址寄存器;对应地,如果采用通用寄存器,则需要用户明确指出用哪个寄存器作为基址寄存器,这是 显式 基址寄存器。
-
优点:可扩大寻址范围;有利于多道程序设计和浮动程序编制。
-
缺点:偏移量(形式地址 A)的位数较短。
8.变址寻址
变址寻址 和基址寻址极为相似,需要设有变址寄存器 IX;将变址寄存器 IX 的内容加上指令中的形式地址,就可以形成操作数的有效地址。即
只要变址寄存器的位数足够,也可以扩大操作数的寻址范围。变址寄存器同样可以采用隐式和显式两种方式。
不过从本质上讲,变址寻址和基址寻址还是有较大区别的。
-
基址寄存器是面向 操作系统 的,主要用于为程序或数据分配存储空间,其内容由操作系统或管理程序确定,在程序的执行过程中其值不可变,而指令字中的 A 是可变的;
-
变址寄存器的内容是由 用户设定 的,在程序执行过程中其值可变,而指令字中的 A 是不可变的。变址寻址主要用于处理数组问题。
例如,某个数组 a 内有 N 个数据元素,在主存中存放的首地址为 D。那么如果要对数组所有元素求和,可以通过直接寻址的方式依次叠加得到结果,写成汇编语言程序如下:
随着 N 的增大,程序的指令条数会越来越多,占据的存储空间也越来越大。
而如果使用变址寻址,只需要将数组元素的索引下标放入变址寄存器中,每次改变变址寄存器的内容(加 1),就能用同样的指令 “ ADD X, D ” 处理所有所有数的相加了。
利用一个条件转移指令(BNE),当变址寄存器 X 中内容还没有增大到 N 时,就跳转回 M 处再次执行相同的指令;当增大到 N 时就结束,得到最后结果。这样,不论 N 取多大,这段程序都只需用 7 条指令,所占存储单元大大减少。这其实就是 “循环” 的实现思路。
-
优点:可扩大寻址范围;在循环体中将 A 设为数组初始地址,可实现数组功能;适合编制循环程序。
9.相对寻址
相对寻址 也是偏移寻址的一种,它所基于的是 程序计数器 PC 。将 PC 的内容加上指令中的形式地址,就形成操作数的有效地址,即
相对寻址通常用于转移类指令,转移后的的目标地址与当前指令有一段距离,称为 相对位移量;这里就是形式地址 A ,所以 A 也称为 位移量。A 的位数决定了操作数的寻址范围,可正可负,用补码表示。
相对寻址的最大特点是转移的目标地址不固定,可以随 PC 的值变化;这样,无论程序加载到主存的哪段区域,都以正确运行,对于编写浮动程序非常有利。例如,之前计算数据和的程序,跳转的目标地址固定为 M;如果程序的首地址发生了改变,M 也会变化。可以将条件转移指令改为相对寻址:
这样,无论程序浮动到哪一地址空间,都可以正常运行了。另外,相对寻址也可以和间接寻址结合使用。
-
优点:便于程序浮动,广泛应用于转移指令。
10. 堆栈寻址
堆栈寻址 要求计算机中设有堆栈。堆栈既可以用寄存器组来实现,称为 硬堆栈;也可以利用主存的一部分空间作为堆栈,称为 软堆栈。
以软堆栈为例,可以用一个 堆栈指针 SP (Stack Pointer)指出栈顶地址,也可以用 CPU 中的寄存器作为 SP。根据栈数据结构的特点,操作数只能在栈顶指针指向的存储单元里存取。
可以看出,堆栈寻址也是一种 隐含寻址,操作数的地址被隐含在了 SP 中。而从本质上看,把 SP 看作存放有效地址的寄存器,堆栈寻址就是一种 寄存器间接寻址。
堆栈有 进栈(PUSH)和 出栈(POP)两种操作:
-
进栈(PUSH A):(SP)- 1 → SP;(ACC)→ M [ (SP) ]
-
出栈(POP A): (M [ (SP) ])→ ACC;(SP)+ 1 → SP
上面讨论的,都是主存按字编址的情况。如果主存按字节编址,则每次进出栈时 SP 的变化 Δ 会受到存储字长的影响;如果存储字长为 2 字节(16 位)则 Δ = 2,为 4 字节则 Δ = 4。
下表列出了所有寻址方式、有效地址及访存次数的简单总结(不含取本条指令的访存)。
寻址方式 | 有效地址 EA | 访存次数 |
---|---|---|
立即寻址 | 不需要 | 0 |
直接寻址 | EA = A | 1 |
间接寻址 | EA = (A) | 2(一次间址) |
隐含寻址 | 隐含在寄存器中 | 0 |
寄存器寻址 | EA = Ri | 0 |
寄存器间接寻址 | EA = (Ri) | 1 |
基址寻址 | EA = (BR) + A | 1 |
变址寻址 | EA = (IX) + A | 1 |
相对寻址 | EA = (PC) + A | 1 |
堆栈寻址 | EA = (SP) - 1 (入栈) 或 EA = (SP) (出栈) | 0(硬堆栈)或 1(软堆栈) |