8086微处理器对数据访问需要通过7种寻址方式中的一种进行寻址,以下我们以MOV指令为例来解释这7种不同的寻址方式。
1.寄存器寻址(Register addressing)
这种寻址方式采用寄存器来存储被处理的操作数,采用这种寻址方式的指令不需要访问存储器就可以直接从寄存器中获得操作数,因此寄存器寻址是一种快速的寻址方式。在8086微处理器中,8位操作数可以使用AL、AH、BL、BH、CL、CH、DL、DH等8位寄存器,而16位操作数则需要使用AX、BX、CX、DX、SI、DI、BP、SP等16位寄存器。下面是几个寄存器寻址的例子:
MOV BX,AX
MOV DS,AX
MOV AH,AL
需要注意的是,源寄存器和目的寄存器的长度必须一致,也就是说,同为8位或同为16位寄存器,混用8位寄存器和16位寄存器是错误的。比如MOV AH,BX这样的指令是无法通过汇编的。
由于寄存器寻址实际上并不访问存储器,所以也不存在有效地址生成的问题。
2.立即寻址(Immediate addressing)
在这种寻址方式中,寻址的对象是一个写在指令中的常数。由于这个常数写在指令的操作码之后,所以被称为立即数,这种寻址方式也就被称为立即寻址。由于立即寻址的操作数存放于指令之中,在指令被执行时操作数已经在CPU内部的相关部件(比如重排序缓冲器)之中,不需要再访问存储器,因而其访问速度非常快。立即寻址方式只能用于源操作数的寻址,多用于给寄存器赋初值。例如:
MOV AX,O
MOV CX,20
需要注意的是,段寄存器和标志寄存器不能用这种方式直接赋初值。下面的代码是错误的:
MOV DS,1550H
要给段寄存器赋初值,我们需要使用通用寄存器作为中转,先将立即数传到通用寄存器中,再传送到段寄存器中。使用类似下面这样的代码段就可以完成:
MOV AX,DA'l'A
MOV DS,AX
DATA是一个数据段的定义标号,在这里作为一个立即数存在。
由于立即寻址实际上并不访问存储器,所以并不存在有效地址生成的问题。
3.直接寻址(Direct addressing)
上面我们介绍的两种寻址方式中,操作数都并没有真正存储在存储器中。当需要访问定义在存储器中的操作数时,我们就需要使用下面要介绍的几种对存储器目标的寻址方式。直接寻址是其中最简单、直接的一种。
在直接寻址方式中,操作数存储在存储器中,而相应存储单元的地址被放在指令的操作码之后。和立即寻址不同,立即寻址的操作数直接跟在指令的操作码之后,而在直接寻址方式中跟在指令操作码之后的是操作数的偏移地址。操作数的物理地址是通过数据段地址和这个偏移地址计算出来的。例如:
MOV AX,[1250H]
MOV BX,COUNT
MOV CX,[COUNT]
这里,COUNT是一个预先定义好的标号,如果COUNT的偏移地址为1250H,则上面这三条指令的源操作数是相同的。在默认情况下,直接寻址方式默认操作数在数据段中,如果我们需要使用直接寻址方式访问其他段的数据,就需要使用段跨越前缀。例如:
MOV AX,ES:COUNT
MOV BX,CS:BUFFER
直接寻址的有效地址生成方式:
EA=操作数地址
4.寄存器间接寻址(Register indirect addressing)
寄存器间接寻址使用寄存器保存操作数的偏移地址,访问寄存器内容所指定存储单元以获得操作数。在8086微处理器中,并不是所有的寄存器都可以被用于寄存器间接寻址,可以用的寄存器有基址寄存器BX、BP和变址寄存器SI、DI。如果使用BX、SI、DI存储偏移地址,则默认段前缀为DS,如果使用BP存储偏移地址,则默认段前缀为SS。下面是寄存器间接寻址的例子:
MOV AX,[BX]
MOV BX,[SI]
MOV CX,BP同样,寄存器间接寻址可以通过段跨越前缀实现对非默认段的寻址:
MOV AX,ES:[BX]
MOV BX,DS:[BP]
寄存器间接寻址可以被用于对表格进行操作,将基址寄存器或变址寄存器初始化为表格的开始,配合INC、LOOP等指令每访问一个数据修改一次寄存器的值,就可以实现对表格的访问。寄存器间接寻址的有效地址生成方式:(www.xing528.com)
EA=寄存器内容
5.寄存器相对寻址(Register relative addressing)
和寄存器间接寻址类似,寄存器相对寻址使用寄存器保存操作数的有效地址相关的信息,但和寄存器间接寻址不同的是,寄存器相对寻址方式在寄存器中保存的不是存储单元的有效地址,而是有效地址相对于某存储单元的相对偏移值(位移量),这也是寄存器相对寻址中“相对”一词的来历。在寄存器相对寻址方式中,操作数的有效地址由给定的位移量和寄存器内容共同决定。和寄存器间接寻址相仿,并不是所有的寄存器都可以用于寄存器相对寻址,可以用的寄存器有基址寄存器BX、BP和变址寄存器SI、DI。其默认段前缀也和寄存器间接寻址是一样的。下面是寄存器相对寻址的例子:
MOV AX,[BX+10]
MOV BX,10[SI]
MOV CX,[BP]+10上面三种写法的含义是相同的。如果预先定义了标号,则寄存器相对寻址也可以写作:
需要注意的是,通过BP对堆栈段的操作只能以字的长度进行,字节操作是禁止的。也就是说,类似下面的指令是错误的:
MOV AL,BP
寄存器相对寻址中的位移量可以是8位或16位的带符号数,它被存储于指令操作码之后的一个或两个字节之中。寄存器相对寻址同样也可以使用段跨越前缀。例如:
MOV AX,ES:ARRAY[BX]
寄存器相对寻址的有效地址生成方式:
EA=寄存器内容+位移量
6.基址变址寻址(Based indexed addressing)
在寄存器间接寻址和寄存器相对寻址中,我们看到两类寄存器可以被用来存储目标地址或位移量,那就是基址寄存器BX、BP和变址寄存器SI、DI。那么,同样是用于存储位移量的寄存器,8086为什么还要把它们分为基址寄存器和变址寄存器两类呢?其原因就在于,8086提供了同时使用基址寄存器和变址寄存器进行寻址的寻址方式,那就是这里提到的基址变址寻址和即将提到的相对基址变址寻址。
基址变址寻址方式是使用基址寄存器和变址寄存器共同来定位操作数地址的一种寻址方式,也就是说,操作数的有效地址是由一个基址寄存器(BX或BP)和一个变址寄存器(SI或DI)的内容之和确定的。操作数使用的默认段前缀由基址寄存器确定,如果基址寄存器为BX,则默认段前缀为DS(即访问数据段),如果基址寄存器为BP,则默认段前缀为SS(即访问堆栈段)。基址变址寻址的例子如下:
MOV AX,[BX+SI]
MOV BX,[BP+SI]
MOV CX,[BP][DI]
MOV DX,[BX][DI]
上面两种不同写法的含义是相同的。对其他段的访问同样也要通过段前缀来完成:
MOV BX,CS:[BP+SI]
MOV CX,ES:[BX][DI]
需要注意的是,在一条基址变址寻址方式的指令中,使用的两个寄存器必须分别是基址寄存器和变址寄存器,而不能同时使用两个基址寄存器或两个变址寄存器,下面这两条指令就违反了这条规则,因而是错误的。
MOV AX,[BX+BP]
MOV BX,[SI+DI]
如果把基址寄存器中存放数组的起始地址,变址寄存器中存放数组元素的相对位置,用基址变址寻址方式来访问数组是非常简单的。基址变址寻址方式的有效地址生成方式:
EA=基址寄存器内容+变址寄存器内容
7.相对基址变址寻址(Relative based indexed addressing)
在基址变址寻址的基础上,再加上一个位移量就形成了相对基址变址寻址。其寄存器组合方法和默认段前缀规则是和基址变址寻址方式一样的,写法也非常类似,只是加上了位移量的部分。例如:
MOV AX,[BX+SI+2]
MOV BX,RECORD[BP+SI]
MOV CX,LIST[BP+DI+2]
MOV DX,FILE[BX][DI]
相对基址变址寻址在使用寄存器上也必须遵守和基址变址寻址一样的规则,也就是说,使用的寄存器必须一个是基址寄存器BX或BP,另一个是变址寄存器SI或DI,而不能同为基址寄存器或同为变址寄存器。相对基址变址寻址经常被用来访问类似记录数组一类有复杂结构的列表,这时基址寄存器可以被用来保存列表的起始地址,变址寄存器可以用来保存记录在列表中的索引,而位移量用来表示记录中的特定元素。
相对基址变址寻址方式的有效地址生成方式:
EA=基址寄存器内容+变址寄存器内容+位移量
在这7种数据访问的寻址方式中,寄存器寻址和立即寻址并不实际访问存储器,其访问速度是比较快的;直接寻址对存储器的访问地址固定,对于预取等提高存储器访问效率的操作比较有利;寄存器间接寻址、寄存器相对寻址等其余4种寻址方式的有效地址和寄存器的内容相关,在现代的超标量超流水线处理机中实现数据预取等操作时就必须考虑到寄存器的相关性问题,实现起来比较复杂。但是,和寄存器寻址、立即寻址、直接寻址等寻址方式相比,寄存器间接寻址、寄存器相对寻址等复杂的寻址方式具有更强大的功能和更佳的灵活性,对于程序的编写有好处。灵活运用这几种寻址方式,发挥这些寻址方式各自的长处,对于编写更好的汇编语言程序非常重要。
免责声明:以上内容源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。