常见寻址方式操作数的寻址方式,就是CPU根据指令的操作数如何寻找真实的数据,或者真实的数据如何在指令 表示。
寻址方式是指寻找指令或者操作数的有效地址的方式。即确定本条指令的数据地址及下一条指令将要执行的指令地址的方法。 指令中的地址码字段并不代表操作数的真实地址,地址码中的字段,称为形式地址(A)。用形式地址结合寻址方式可以计算出操作数在存储系统中的真实地址,称为有效地址(EA)。 对于符号 (A),整个内容表示的是地址为A的数值。而A可以是寄存器的标号,也可以是内存地址,所以(A)是对应的数值。例如EA = (A),可以表示为有效地址为地址为A的数值。
这一部分可以用指针的知识理解,(A)相当于*A,
而EA = (A)相当于,EA = *(*A)
寻址方式分为指令寻址跟数据寻址两大类。寻找下一条要执行的指令地址,称为指令寻址。寻找操作数的地址称之为数据寻址。
指令寻址- 顺序寻址 程序的指令序列在主存中顺序存放,程序执行的时候,从第一条指令开始,逐条取出并逐条执行。这种程序的顺序执行,称为顺序寻址方式。 为了达到顺序寻址的目的,CPU中必须有一个程序计数器(PC).对指令的顺序号进行计数。PC中开始时存放的是程序的首地址,每执行一条指令,PC 1,用来指明下一条指令所在内存的地址,直到程序结束。这里一定注意,PC中存放的是下一条指令的地址。
- 跳跃寻址 当程序出现分支或者循环的时候,就会改变程序的执行顺序,此时对指令寻址采取跳跃寻址方式。。所谓跳跃,便是指下条指令的地址并不是通过PC的当前值来获取的,而是由指令本身给出,跳跃的处理方式是重新修改PC的内容,然后进入取指阶段(也就是说,下一条指令的地址仍由PC所给出,只不过它的值被修改了。)
数据寻址数据的寻址方式比较多样,其过程就是把操作数的形式地址,变换成操作数的有效地址的过程。通常数据寻址的指令格式如下:
通常我们约定:指令字长 = 存储字长 = 机器字长。
根据操作数存放的不同位置,从而衍生出各种不同的寻址方式,往往不同的计算机有不同的寻址方式。而操作数,通常位于:
- 包含在指令中
- 包含在CPU的某一寄存器中
- 包含在主存储器中
- 包含在I/O设备的端口中
这种类型的指令,不是明显的给出操作数的地址,而是在指令中隐含着操作数的地址,显然单地址指令就是如此。(比如利用ACC作为第二操作数的地址,因此,累加器ACC对单地址指令格式来说是隐含地址)。
优点:利于缩短指令字长,可简化地址结构,是获取操作数最快的方式
缺点:需要增加存储操作数的硬件或者隐含地址的硬件。
2. 立即寻址种类型的指令,地址字段是操作数本身,因此,又称立即数寻址,数据采用补码的方式存放。 看下面的汇编代码,分号后面是注释:
1.mov ax,2308H ;2308 ->ax
意思是将2308H这个地址移动到ax寄存器中,这样,给出的地址就是操作数本身。
- 优点:在取指令的时候,操作码跟操作数被同时取出,不必再次访存,提高了指令的执行速度。
- 缺点:因操作数指令的一部分,因此不能被修改,而且对于定长指令格式,操作数大小还将受到长度的限制。
所以,通常用于给定的某一寄存器或者主存单元赋值,或者用于提供某一常数。换成C 代码可以看成:
1.int x = 100;
2.const int j = 100;
3.···
即地址码字段直接给出操作数所在的内存地址,即EA = A的情况。如下面的汇编指令:
mov ax [200]; 将地址为200处的数据,存放到ax中
这种行为就像程序中直接给出变量名:
int y = x;
优点:简单,执行阶段值访问一次内存,因此在早期的计算机中,常常作为主要的寻址方式 缺点:A的位数决定了该指令操作数的寻址范围,并且操作数的地址不易被修改。
4. 间接寻址间接寻址是相对直接寻址而言的,指令的地址字段不是操作数的真实地址,而是操作数的有效地址所在的存储单元的地址,听起来有点拗口,也就是操作数地址的地址,即EA = (A),间接寻址可以是一次间接寻址也可以是多次间接寻址。如果还是有点不好理解,那么用下图来理解(用间接寻址的方式取出788这个数):
- 优点:明明可以一步到位,为什么还有多此一举?显然,这种方式可以扩大寻址范围,将小地址作为一个跳板,可以访问更多的地址空间,便于编程(子程序中的返回)。
- 缺点:需要进行多次访存(一次的间接寻址就需要两次访存)。访问速度慢。
寄存器寻址是指的在指令中,直接给出操作数所在的寄存器编号,即EA = Ri。操作数在R的内部(类似于直接寻址)。 就像下面的汇编指令:
mov ax,bx
- 优点:指令执行时,不访问内存,只访问寄存器,指令字短,故执行速度快,支持向量/矩阵运算。
- 缺点:寄存器的价格昂贵,且计算机内寄存器的数量有限。
类似于间接寻址,寄存器中给出的不是一个操作数,而是操作数所在的主存单元的地址,即EA = Ri。 用汇编指令表示为;
mov ax,[bx]
这种做法的主要特点就是,比间接寻址快,但是由于操作数在主存中,故仍需要访问内存,一般用于扩大寻址范围。
7. 相对寻址这种寻址方式的原理是基于程序的局部性原理。指令中的A,加上PC上的内容,作为操作数的地址。即EA = (PC) A。其中A是相对于当前地址的偏移量。可正可负。用补码表示。
特点:A的位数决定操作数的寻址范围。操作数不固定,随着PC的变化而变化,并与指令地址总差一个固定值。便于程序浮动。被广泛用于转移指令(即jump指令)。 这里注意理解PC指令的作用。比如下面的句子:
jump A
CPU从存储器中取一个字节,即(PC) 1 ->PC.也就是说PC自增1.若此时,转移指令的地址为X,且占2个字节。那么取出该指令后,PC自增2,即(PC) = X 2。执行完这个指令后,跳到X 2 A处继续执行。
8. 基址寻址(面向系统)基址寻址,是将CPU中的基址寄存器(BR)的内容,加上指令格式中的形式地址A,从而形成有效地址。即EA = A (BR)。
特点:可以扩大寻址范围(因为基址的位数可以设置为很长)。BR的内容可由操作系统或者管理程序确定。程序的执行期间,BR内容不变但是A的内容可变。有利于多道程序的设计。
9. 变址寻址(面向用户)这种做法是,指定一个变址寄存器IX,有效地址等于A与寄存器IX的内容相加。即EA = A (IX)。与上面的基址寻址的方法不同,IX的内容可以随要求填入,IX既可以用专用的寄存器,又可以用通用寄存器。用汇编指令可以表示为:
mov ax,200[si]
过程如图:
变址寻址是一种被广泛采用的寻址方式。最典型的应用就是将指令的地址码部分给出的地址A作为基准地址,而将变址寄存器中的内容作为修改量。在遇到需要频繁修改操作数地址的操作时,无需修改指令,只要修改变址寄存器中的编址值即可。
在编程中,可设A为数组首地址,不断修改寄存器的内容,便可以得到数组中的任一数据地址。特别适合编制循环程序。
10. 堆栈寻址堆栈是存储器中按LIFO的方式管理的存储区,该存储区的读/写单元地址用一个特定的寄存器给出,该寄存器称为堆栈指针(SP)。堆栈分为硬堆栈跟软堆栈两种。 寄存器堆栈称为硬堆栈,从主存中划出一段区域称为软堆栈。
(这里注意sp一开始指向为空,所以在弹出的时候,先加1,因为有数据的时候才可以弹出。)
,