通过程序计数器(PC)加1,自动生成下一条指令的地址。对于变长指令字结构等情况PC+n,也属于顺序寻址
通过转移类指令实现,是否跳跃受到状态寄存器和操作数的控制。
跳跃的地址分为
绝对地址:由标记符直接得到
相对地址:相对于当前指令地址的偏移量
(详见上一节↓)
如OP为JMP,地址码为7,此时PC的值将改为7,CPU根据PC的值指向指令7
确定本条指令的地址码指明的真实地址(如起始地址为100,OP为JMP,地址码为7,则真实地址为107而不是7)
一地址指令结构(操作码,寻址特征,形式地址A)
①寻址特征表示使用以下的哪种寻址方式
②确定了使用哪种寻址方式,再结合形式地址A,即可得到操作数的真实地址(也称有效地址EA)
二地址指令结构(操作码,寻址特征,形式地址A1,寻址特征,形式地址A2),需要为每个形式地址指明它的寻址特征
以下假设指令字长=机器字长=存储字长,希望找到的操作数是3
不是明显地给出操作数的地址,而是在指令中隐含着操作数的地址。如ACC中的操作数不需要指令指出。
优点:有利于缩短指令字长
缺点:需增加存储操作数或隐含地址的硬件
待找的操作数直接被放在指令中,即形式地址A就是操作数本身,又称为立即数,一般采用补码形式。寻址特性为“#”的表示立即寻址。
优点:指令执行阶段不需要访问主存,执行时间最短
缺点:A的位数限制了立即数的范围
EA=A,LDA为取数指令
一条指令的执行共需要2次访存:取指令、执行指令
优点:实现简单,指令执行阶段仅访问一次主存,不需专门计算操作数的地址。
缺点:A的位数决定了该指令操作数的寻址范围,操作数的地址不易修改。
(1)一次间址
A中存放的是EA,即EA=(A)
一条指令的执行需要3次访存:取指令1次+执行指令2次
(2)两次间址
存储单元第一个比特位是1需要继续寻找,为0表示后面就是EA
共需要4次访存:取指令1次+指令执行3次
可以看出,n次间址的访存次数:1+(n+1)=n+2次
优点:可扩大寻址范围(有效地址EA的位数可以大于形式地址A的位数);便于编制程序(用间接寻址可以方便地完成子程序返回)
缺点:指令在执行阶段要多次访存,多次寻址需根据存储字的最高位确定几次访存
寄存器中存放操作数。直接给出操作数所在的寄存器编号Ri,即EA=Ri
一条指令的执行需要在取指令时访存1次
优点:指令在执行阶段不访问主存,只访问寄存器;指令字短且执行速度快,支持向量/矩阵运算。
缺点:寄存器价格昂贵,计算机中寄存器个数有限。
寄存器中存放操作数的地址。寄存器Ri指向的是操作数所在主存单元的地址,即EA=(Ri)
一条指令的执行需要2次访存:取指令1次+指令执行1次
特点:比一般间接寻址相比速度快,但指令的执行阶段需要访问主存
相对于下一条指令的偏移。取出当前指令后,PC指向下一条指令,再以PC作为起点,EA=(PC)+A
A可以看做是所指地址的偏移量,可正可负,通常用补码表示。
若程序的起始地址为M,OP为JMP的主存地址为M+3,对应地址码为0(指向第一条指令)。执行完JMP后PC指向M+4,为了保证跳转到第一条指令(即M)而不是跳转到主存地址为0的地址,需要将OP为JMP对应的地址码A的值改为-4,利用相对寻址,EA=(PC)+A=M+4+(-4)=M。因此,我们可以随意挪动代码段,A的值-4一定能让程序跳转回第一条指令(M),即这段代码在程序内浮动时不用再更改跳转指令的地址码
为了防止经常挪动代码造成数组元素的存放地址被频繁修改,可以将程序段和数据端分开存放
优点:便于程序浮动(一段代码在程序内部的浮动)、广泛应用于转移指令
以程序的起始存放地址作为起点,即EA=(BR)+A
BR叫做基址寄存器,基址寄存器是面向操作系统的,其内容由操作系统或管理程序确定。在程序执行过程中,基址寄存器的内容不变(作为基地址),形式地址可变(作为偏移量)。当采用通用寄存器作为基址寄存器时,可由用户决定哪个寄存器作为基址寄存器,但其内容仍由操作系统确定。
优点:
①可扩大寻址范围:基址寄存器的位数通常大于形式地址A的位数
②用户不必考虑自己的程序存于主存的哪一空间区域,故有利于多道程序设计:主存中可能同时多个程序的数据,每个程序的起始存放位置不同。程序运行前,CPU的基址寄存器都会修改为当前运行程序的起始存放地址,通常存放在PCB中
③便于程序浮动(整段程序在内存中的浮动):程序可以在主存中以任意位置开始存放
也可采用通用寄存器来代替基址寄存器。R0指明基地址存放在哪个寄存器中,此图中EA=(R0)+A
程序员自己决定从哪里作为起点,即EA=(IX)+A
IX叫做变址寄存器,同样,也可用通用寄存器作为变址寄存器
变址寄存器是面向用户的,变址寄存器的内容可由用户改变(即改变IX),而形式地址A不变。因此可以看成A作为基地址,IX作为偏移量。
for(int i=0;i<10;i++){
sum+=a[i];
}
通常情况下需要逐个执行
可以使用变址寻址实现for循环进行优化
将立即数0放到ACC、IX中,EA=(IX)的0+A的7=7指向a[0],IX+1对应for循环的i++,作差比较小于0,因此仍满足for循环条件。跳转回主存地址2,EA=(IX)的1+A的7=8指向a[1],和a[0]相加存ACC,以此类推。
可以看出,在数组处理过程中,可设定A为数组的首地址,不断改变变址寄存器Ⅸ的内容,就可以很容易形成数组中任一数据的地址。因此变址寻址特别适合编制循环程序。
若上述程序不是从0号主存地址开始存放的,则需要结合基址寄存器BR的值得到EA,即EA=(BR)+A+(IX)
操作数存放在堆栈中,隐含使用堆栈指针(SP)作为操作数地址。可以设置一组专门的寄存器,每个寄存器存放一个堆栈元素。也可在主存中划出一片区域作为堆栈。
(1)寄存器存放堆栈/硬堆栈
弹栈和压栈都不需要进行访存,成本高,速度快
设栈顶地址最小
将两个栈顶元素依次弹出进行运算在压回栈顶。每弹出一个元素后SP+1;在压回栈时,SP先-1再压回栈顶。
若M表示栈顶单元,寄存器Y用来存放运算结果
出栈:(M)→ACC,(SP)+1→SP
入栈:(SP)-1→SP,(Y)→(M)
(2)在主存中划分区域作为堆栈/软堆栈
弹栈和压栈都需要进行访存,成本低,速度慢。堆栈可用于函数调用时保存当前函数的相关信息