【指令寻址与数据寻址】
寻址
寻址方式是指寻找指令或操作数有效地址的方式,也就是指确定本条指令的数据地址,以及下一条将要执行的指令地址的方法
指令中的地址码字段并不代表操作数的真实地址,称为形式地址 $(A)$,用形式地址并结合寻址方式,可以计算出操作数在存储器中的真实地址,称为有效地址 $(EA)$
形式地址 $(A)$ 表示地址为 $A$ 的数值,$A$ 既可以是寄存器编号也可以是内存地址,对应的 $(A)$ 就是寄存器中的数值,或相应内存单元的数值,例如:$EA=(A)$ 的意思就是有效地址是地址A中的数值
寻址方式分为指令寻址和数据寻址两大类,寻找下一条将要执行的指令地址称为指令寻址,寻找操作数的地址称为数据寻址
指令寻址
指令寻址方式有两种:
- 顺序寻址:通过程序计数器 $PC$ 自动 $+1$(一个指令字长),自动形成下一条指令的地址
- 跳跃寻址:通过转移类指令实现,即下条指令的地址码不是由程序计数器给出,而是由本条指令给出下条指令地址的计算方式,跳跃到的地址分为绝对地址(由标记符直接得到)和相对地址(对于当前指令地址的偏移量),跳跃的结果是当前指令修改 $PC$ 值,所以下一条指令仍然是通过程序计数器 $PC$ 给出
数据寻址
数据寻址就是如何在指令中表示一个操作数的地址,如何用这种表示得到操作数或怎样计算出操作数的地址
数据寻址方式的种类较多,为了区别各种方式,通常在指令字中设一个字段,用来指明属于哪种寻址方式
由此可得指令的格式如下所示:
【数据寻址方式】
数据寻址方式对比
下表给出了数据寻址方式的有效地址和访存次数的对比
寻址方式 | 有效地址 | 访存次数 |
---|---|---|
隐含寻址 | 程序指定 | $0$ |
立即寻址 | $A$ 即操作数 | $0$ |
直接寻址 | $EA=A$ | $1$ |
一次间接寻址 | $EA=(A)$ | $2$ |
寄存器寻址 | $EA=R_i$ | $0$ |
寄存器间接寻址 | $EA=(R_i)$ | $1$ |
相对寻址 | $EA=(PC)+A$ | $1$ |
基址寻址 | $EA=(BR)+A$ | $1$ |
变址寻址 | $EA=(IX)+A$ | $1$ |
隐含寻址
这种类型的指令,不是明显地给出操作数的地址,而是在指令中隐含着操作数的地址
如单地址的指令格式,就不是明显地在地址字段中指出第二操作数的地址,而是规定累加器 $ACC$ 作为第二操作数地址,指令格式明显指出的仅是第一操作数的地址,因此,累加器 $ACC$ 对单地址指令格式来说是隐含地址
该方式有利于缩短指令字长,但需要增加存储操作数或隐含地址的硬件
立即寻址
这种类型的指令的地址字段指出的不是操作数的地址,而是操作数本身,又称为立即数,此外,数据是采用补码形式存放的
立即寻址在指令执行阶段不访问主存,指令执行时间最短,但是 $A$ 的位数限制了立即数的范围
直接寻址
指令字中的形式地址 $A$ 就是操作数的真实地址 $EA$,即 $EA=A$
该方式简单便捷,指令在执行阶段仅访问一次主存,不需要专门计算操作数地址,但 $A$ 的位数决定了该指令操作数的寻址范围,操作数的地址不易修改
间接寻址
间接寻址是相对于直接寻址而言的,指令的地址字段给出的形式地址不是操作数的真正地址,而是操作数有效地址所在的存储单元的地址,也就是操作数地址的地址,即:$EA=(A)$
间接寻址可扩大寻址范围,可以方便地完成子程序返回,便于编制程序,但指令在执行阶段要多次访存,由于访问速度过慢,这种寻址方式并不常用
寄存器寻址
在指令字中直接给出操作数所在的寄存器编号,即 $EA=R_i$,其操作数在由 $R_i$ 所指的寄存器内
该方式在指令执行阶段不访问主存,只访问寄存器,因寄存器数量较少,对应地址码长度较小,使得指令字短且因不用访存,所以执行速度快,同时支持向量/矩阵运算,但寄存器价格昂贵,计算机中寄存器个数有限
寄存器间接寻址
寄存器间接寻址是指在寄存器 $R_i$ 中给出的不是一个操作数,而是操作数所在主存单元的地址,即 $EA=(R_i)$
寄存器间接寻址与一般间接寻址相比速度更快,但由于操作数在主存中,因此指令的执行阶段需要访问主存
相对寻址
相对寻址是把程序计数器 $PC$ 的内容加上指令格式中的形式地址 $A$ 而形成操作数的有效地址,即 $EA=(PC)+A$,其中 $A$ 是相对于当前指令地址的位移量,该位移量用补码表示,同时其位数决定操作数的寻址范围
该寻址方式的操作数的地址不是固定的,它随着 $PC$ 值的变化而变化,并且与指令地址之间总是相差一个固定值,因此便于程序浮动,广泛应用于转移指令
需要注意的是,对于转移指令 $JMPA$,当 CPU 从存储器中取出一个字节时,会自动执行 $(PC)+1\rightarrow PC$,若转移指令的地址为 $X$,且占 $2$ 个字节,在取出该指令后,$PC$ 的值会增 $2$,即 $(PC)=X+2$,这样在执行完该指令后,会自动跳转到 $X+2+A$ 的地址继续执行
基址寻址
基址寻址是将 CPU 中基址寄存器 $BR$ 的内容加上指令格式中的形式地址 $A$,而形成操作数的有效地址,即 $EA=(BR)+A$,其中基址寄存器既可采用专用寄存器,也可采用通用寄存器
基址寄存器是面向操作系统的,其内容由操作系统或管理程序确定,主要用于解决程序逻辑空间与存储器物理空间的无关性,在程序执行过程中,基址寄存器的内容作为基地址不变,而形式地址作为偏移量可变
当采用通用寄存器作为基址寄存器时,可由用户决定哪个寄存器作为基址寄存器,但其内容仍由操作系统确定
基址寻址可扩大寻址范围,用户不必考虑自己的程序存于主存的哪一空间区域,故有利于多道程序设计,以及可用于编制浮动程序,但作为偏移量的形式地址 $A$ 的位数较短
变址寻址
有效地址 $EA$ 等于指令字中的形式地址 $A$ 与变址寄存器 $IX$ 的内容相加之和,即 $EA=(IX)+A$,其中 $IX$ 为变址寄存器,也可用通用寄存器作为变址寄存器
变址寄存器是面向用户的,在程序执行过程中,变址操作数寄存器的内容作为偏移量可由用户改变,形式地址 $A$ 作为基地址不变
该方式可扩大寻址范围,同时在数组处理过程中,可设定 $A$ 为数组的首地址,不断改变变址寄存器 $IX$ 的内容,便可很容易形成数组中任一数据的地址,特别适合编制循环程序
显然,变址寻址与基址寻址的有效地址形成过程极为相似,但从本质上来讲,两者有较大区别,基址寻址面向系统,主要用于为多道程序或数据分配存储空间,故基址寄存器的内容通常由操作系统或管理程序确定,在程序的执行过程中其值不可变,而指令字中的 $A$ 是可变的,变址寻址立足于用户,主要用于处理数组问题,在变址寻址中,变址寄存器的内容是由用户设定的,在程序执行过程中其值可变,而指令字中的 $A$ 是不可变的
堆栈寻址
堆栈是存储器中一块特定的按后进先出 LIFO 原则管理的存储区,该存储区中被读/写单元的地址是用一个特定的寄存器给出的,该寄存器称为堆栈指针 $SP$
堆栈可分为硬堆栈与软堆栈两种:
- 硬堆栈:即寄存器堆栈,成本比较高,不适合做大容量的堆栈
- 软堆栈:从主存中划出一段区域来做堆栈
在采用堆栈结构的计算机系统中,大部分指令表面上都表现为无操作数指令的形式,因为操作数地址都隐含使用了 $SP$,通常情况下,在读/写堆栈中的一个单元的前后都伴有自动完成对 $SP$ 内容的增量或减量操作