16-8086处理器的寻址方式

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_35733751/article/details/85250781

CPU作为计算机的中央处理器,每天忙忙碌碌,只要它工作着就会不断地运行指令,处理各种数据。既然要处理数据,就会涉及两个问题:

1. 数据在哪里,如何获取

2. 处理完之后,把数据送到哪里去

而在计算机中,寻址方式就是如何找到要操作的数据,以及把数据处理完存放到哪里。对于8086处理器来说,它的寻址方式大致分为这几类:寄存器寻址,立即寻址,内存寻址,下面我们分别来讨论这几种寻址方式。

 

1. 寄存器寻址

寄存器寻址就是指令执行时,需要操作的数据位于寄存器中,比如下面几条指令:

mov ax,cx
add bx,0xf000
inc dx

在第一条指令中,有两个操作数都是寄存器,ax表示目的操作数,cx表示源操作数,这是典型的寄存器寻址。

第二条指令中,目的操作数bx是一个寄存器,因此这条指令也是寄存器寻址。

第三条指令就更不用说了,dx作为一个寄存器,既是源操作数,也是目的操作数

 

2. 立即寻址

立即寻址又叫立即数寻址,也就是说,指令的操作数是一个立即数,比如:

add bx,0xf000

在第一条指令中,目的操作数bx是一个寄存器,采用了寄存器寻址方式;而0xf000是源操作数,这是一个直接给出的数值,并且这个数据就在指令中直接得到,不需要通过其他方式寻找,故称为立即数,这也是一种寻址方式,叫做立即寻址。

mark:
mov ax,mark

再来看这条指令,目的操作数ax也采用了寄存器寻址方式,而源操作数是一个标号,通过前面的学习我们知道伪汇编指令需要转换成纯汇编指令,因为真正编译后,标号mark也会被转化成一个立即数,因为该指令的源操作数也采用了立即寻址方式。

另外,我们在确定一条指令的寻址方式时,是根据操作数来看的,例如有的指令只有一个操作数,比如inc ax指令,那么我们能确定这条指令就是采用寄存器寻址方式的。但是对于add bx,0xf000指令来说,这条指令既采用了寄存器寻址方式,也采用了立即数寻址方式,所以对于有两个操作数的指令来说,需要根据目的操作数或者源操作数来确定寻址方式。

 

3. 内存寻址

寄存器寻址的操作数位于寄存器中,立即寻址的操作数位于指令中,是指令的一部分。这也是速度最快的两种寻址方式。但是,它们也有一些局限性,因为有时候我们并不知道要操作的数是多少,再说了,寄存器的数量有限。因此,考虑到内存的容量大,在指令中使用内存地址来操作内存中的数据是再好不过的了。

我们知道8086CPU处理器访问内存时,采用是的段地址和偏移地址合成20位物理地址的模式。 段地址是由8086的4个段寄存器(ES、DS、CS、SS)来指定的,偏移地址由指令来指定。因此,所谓的内存寻址其实就是在寻找偏移地址。

3.1直接寻址

直接寻址方式使用了一个偏移地址,我们通过以下几条指令来说明。

第一条指令如下:

mov ax,word [ds:0x5c0f]

要表示内存地址,必须使用中括号括起来。

在上述指令,源操作数是直接寻址方式,当这条指令执行时,处理器将段寄存器ds的内容左移4位,加上0x5c0f,形成20位的物理地址。接下来,从该物理地址处取得一个字长度的数据,传送到寄存器AX中。

 

第二条指令如下:

add word [ds:0x0230],0x5000

第二条指令,目的操作数采用的直接寻址方式。当这条指令执行时,处理器用同样的方法,计算出20位内存地址,并且把0x0230这个数据用1个字的长度放进去。

 

第三条指令如下:

Mark:
xor byte [es:Mark],0x05

第三条指令中,目的操作数虽然使用了标号,但标号属于伪指令,转换成纯指令,标号就会成为一个确定的数字,所以依然属于直接寻址。

通过以上几条指令我们可以知道:在8086中,访问内存的时候,如果是段寄存器加一个固定偏移量(常量),就是直接寻址。

3.2 基址寻址

先从字面上来分析一下“基址寻址”,基址的意思是“基础地址”,所谓基址寻址就是在指令的地址部分使用基址寄存器bx或bp来提供偏移地址,同时还可以指定一个偏移量(可正可负)。

很多时候,我们有一大堆数据要处理,而且它们通常都挨在一起,顺序存放。比如:

Data:
dw 0x0020,0x0100,0x000f,0x0300,0xff00

假如要把这些数据统统加一,那么使用直接地址的话,如下:

Code:
inc word[ds:Data+0]
inc word[ds:Data+2]
inc word[ds:Data+4]
. . . . . .

我们知道这种方式是使用的直接寻址方式,虽然也能实现,但考虑效率和代码的简洁性,我们用循环来完成更好,因此可以使用基址寻址,如下:

mov bx,Data
mov cx,5 

IncreaseOne:
inc word[ds:bx]	;bx就是基础地址,当然你也可以使用bp寄存器
add bx,2
loop IncreaseOne

在8086处理器中,访问内存的时候,也就是中括号里面,一般基址寻址经常使用bx寄存器和bp寄存器,通常bx是针对数据段操作的时候,而bp针对栈段操作的数据。

 

3.3 变址寻址

变址寻址类似于基址寻址,唯一不同之处在于这种寻址使用的是变址寄存器(或称索引寄存器)SI和DI。

例如:

mov [ds:si],dx
add ax,[es:di]
xor word[ds:si],0x8000

在以上指令中使用了变址寄存器si和di,因此可以认为以上指令是使用了变址寻址方式。

同样地,变址寻址方式也允许带一个偏移量,例如以下指令:

mov [ds:si+0x0100],al

对于变址寻址,简单一句话就是,只要指令中使用了变址寄存器SI或DI,就是使用了变址寻址方式。

猜你喜欢

转载自blog.csdn.net/qq_35733751/article/details/85250781