指令寻址
寻址方式分为指令寻址和数据寻址两大类。寻找下一条将要执行的指令地址称为指令寻址;寻址本条指令的数据地址称为数据寻址。
指令寻址
指令寻址方式有两种:一是顺序寻址,二是跳跃寻址。
顺序寻址
通过程序计数器PC加1(1个指令字长,实际加的值回因指令长度、编址方式而不同),自动形成下一条指令的地址。
例:
若某系统采用定长指令字结构,指令字长=存储字长=16bit=2B,主存按字编址(即按2B编址)。
此时若取走地址直接让PC+1即可跳到下一条地址。
而若此时设某系统采用定长指令字结构,指令字长=存储字长=16bit=2B,主存按字节编址(即按1B编址)。
此时一条指令占两个地址。
此时若想实现顺序寻址则需PC+2(2个指令字长)来形成下一条指令的地址。
跳跃寻址
是指下条指令的地址不由程序计数器PC自动给出,而由本条指令给出下条指令地址的计算方式。
例:
若某系统采用定长指令字结构,指令字长=存储字长=16bit=2B,主存按字编址(即按2B编址)。
指令结构如下图所示:
当运行到第三条指令时,JMP为无条件转移,会将PC中的内容改成7,所以会跳到第7条指令地址进行执行。
数据寻址
数据寻址的方式较多,为区别各种方式,通常会在指令字中设一个形式地址的字段,来表明用那种寻址方式,如下图所示。
在数据寻址中,会EA来表示有效地址,A表示形式地址。
默认指令字长=机器字长=存储字长
直接寻址
指令字中的形式地址A就是操作数的真实地址EA, EA=A。
指令形式:
例:
若要对操作数3进行取值并放入寄存器中。
此时会先访存1次进行取指令,然后再访存1次执行指令,共访存2次。
直接寻址优点:简单,指令执行阶段仅访问一次主存,不需要专门计算操作数的地址。
直接寻址缺点:A的位数决定了该指令操作数的寻址范围,操作数的地址不易修改。
间接寻址
间接寻址中指令的地址字段给出的形式地址不是操作数的真正地址,而是操作数有效地址所在存储单元的地址,就是操作数地址的地址,即EA=(A)。
指令形式:
例:
上图进行寻址,首先会进行取地址访存1次,然后执行指令找到A所在的数据,根据A的内容找到真正地址EA,访存2次,共访存3次。
也可以两次间接寻址:
当主存字第一位为1时,表示取出的仍不是操作数的地址,需要多次间接寻址。只有当第一位为0时,表示取得的是操作数的地址。
优点:可扩大寻址范围(有效地址EA的位数大于形式地址A的位数),便于编制程序(用间接寻址可以方便地完成子程序返回)。
缺点:指令在执行阶段要多次访存(一次间接寻址需两次访存,多次需根据存储字的最高位确定)。
寄存器寻址
寄存器寻址是指在指令字中给出操作数所在的寄存器编号,即EA=$R_i$,其操作数在由$R_i$所指的寄存器内。
指令形式:
例:
若此时寄存器编号为1001,对应十进制9,会在$R_9$中进行寻址。
此时只需取指令的时候进行访存1次,由于EA在寄存器中,所以执行指令无需访存,共访存1次。
优点:指令在执行阶段不访问主存,只访问寄存器,指令字短且执行速度快,支持向量/矩阵运算。
缺点:寄存器价格昂贵,计算机中寄存器个数有限。
寄存器间接寻址
指寄存器$R_i$中给出的不是一个操作数,而是操作数所在的主存单元的地址。即EA=($R_i$)。
指令形式:
例:
用这种方式,取指令时需进行一次访存,执行指令也需访存1次,共访存2次。
优点:与一般间接寻址相比速度更快,但指令的执行阶段需要访问主存(因为操作数在主存中)
隐含寻址
这种类型的指令不明显地给出操作数的地址,而是在指令中隐含着操作数的地址。
例:
将A进行累加操作:
优点:有利于缩短指令字长
缺点:需增加存储操作数或隐含地址的硬件。
立即(数)寻址
这种类型的指令地址字段指出的就是操作数本身,又称立即数,采用补码表示。
指令形式:
例:
上方的形式地址就是十进制形式就是操作数3。
此时执行一条指令会取指令进行访存1次,由于已经是操作数,执行指令将不会访存,共访存1次。
优点:指令执行阶段不访问主存,指令执行时间最短
缺点:A的位数限制了立即数的范围。 如A的位数为n,且立即数采用补码时,可表示的数据范围为$-2^{n-1} $ ~ $ 2^{n-1} -1$
基址寻址
将CPU中基址寄存器(BR)的内容加上指令格式中的形式地址A,而形成操作数的有效地址,即$EA=(BR)+A$。
基址寻址的硬件实现:
例:
在图中中若主存以100开始作为主存地址,地址码寻址取数a,此时a的主存地址为105,就可以将BR设置为0000 0000 0110 0100(十进制100),通过ALU,此时均可以实现基于100来进行有效地址的寻址。
注:基址寄存器是面向操作系统的,其内容由操作系统或管理程序确定。在程序执行过程中,基址寄存器的内容不变(作为基地址),形式地址可变(作为偏移量)。
当采用通用寄存器作为基址寄存器时,可由用户决定哪个寄存器作为基址寄存器,但其内容仍由操作系统确定。
优点:便于程序“浮动”,方便实现多道程序并发运行。可扩大寻址范围(基址寄存器的位数大于形式地址A的位数);用户不必考虑自己的程序存于主存的哪一空间区域,故有利于多道程序设计,以及可用于编制浮动程序。
变址寻址
是将有效地址EA等于指令字中的形式地址A与变址寄存器IX的内容相加之和,即EA=(IX)+A,其中IX可为变址寄存器(专用),也可用通用寄存器作为变址寄存器。
变址寻址的硬件实现:
注:变址寄存器是面向用户的,在程序执行过程中,变址寄存器的内容可由用户改变(IX作为偏移量),形式地址A不变(作为基地址)。
优点:在数组处理过程中,可设定A为数组的首地址,不断改变变址寄存器IX的内容,便可很容易形成数组中任一数据的地址,特别适合编制循环程序。
相对寻址
把程序计数器PC的内容加上指令格式中的形式地址A而形成操作数的有效地址,即EA=(PC)+A,其中A是相对于PC所指地址的位移量,可正可负,补码表示。
相对寻址的硬件实现:
优点:操作数的地址不是固定,它随着PC值的变化而变化,并且与指令地址之间总是相差一个固定值,因此便于程序浮动(一段代码在程序内部的浮动)。相对寻址广泛应用于转移指令。
堆栈寻址
操作数存放在堆栈中,隐含使用堆栈指针(SP)作为操作数地址。
堆栈是存储器(或专用寄存器组)中一块特定的按“后进先出(LIFO)”原则管理的存储区,该存储区中被读/写单元的地址是用一个特定的寄存器给出的,该寄存器称为堆栈指针(SP)。
用寄存器来实现栈结构也称硬堆栈。而用主存中某一块区域来实现堆栈称为软堆栈。
下图是对寻址的总结: