寻址
汇编语言中,操作码用助记符表示,操作数则由寻址方式体现。8086处理器只有输入输出指令与外设交换数据,除外设数据外的数据寻址方式有3类:
用常量表达的具体数值(立即数寻址)
用寄存器名表示的其中内容(寄存器寻址)
用存储器地址代表保存的数据(存储器寻址)
立即数寻址
立即数寻址(或立即寻址)中,指令需要的操作数紧跟在操作码之后作为指令机器代码的一部分,并随着处理器的取指操作从主存进入指令寄存器。
这种操作数用常量形式直接表达,从指令代码中立即得到,被称为立即数(Immediate)。
立即数寻址方式只用于指令的源操作数,在传送指令中常用来给寄存器和存储单元赋值。
简而言之,立即数寻址就是 操作码 + 立即数,其中立即数是常量形式的,可以直观的看到。
例如,将数据0102H传送到AX寄存器的指令,可以书写为:
mov ax, 0102h ; 指令代码:B8 02 01
8086处理器规定数据高字节存放于存储器高地址单元、数据低字节存放于低地址单元,如图右所示。
寄存器寻址
寄存器寻址方式的操作数存放在处理器的寄存器中。通常直接使用寄存器名表示它所保存的数据,即寄存器操作数。
绝大多数指令采用通用寄存器寻址(8086处理器是16位的AX、BX、CX、DX、SI、DI、BP和SP,以及8位
的AL、AH、BL、BH、CL、CH、DL和DH),部分指令支持专用寄存器,例如段寄存器、标志寄存器等。
寄存器寻址方式简单快捷,是最常使用的寻址方式。
凡是只使用寄存器名(无其他符号,例如中括号、变量名等)的操作数都为寄存器寻址。
mov al,ah
注意:MOV指令不允许把8位寄存器的数据传送到16位寄存器中。下面演示错误的用法:
mov di,dh ;di是16位的,dh是8位的,所以出错。
存储器寻址
如何寻址主存中存储的操作数就称为存储器寻址方式,也称为主存寻址方式。编程时,存储器地址使用包含段选择器和偏移地址的逻辑地址。
这里复习一下逻辑地址、偏移地址和物理地址之间的关系:
段基地址左移4位(十六进制一位) + 偏移地址 = 20位物理地址
逻辑地址是应用程序所看到的地址,段基地址和偏移地址共同组成逻辑地址,可以通过寻址获取物理地址。
段寄存器的默认和超越
段寄存器(段选择器)有默认的使用规则。寻址存储器操作数时,段寄存器不用显式说明,即数据就在默认的段中,一般是DS段寄存器指向的数据段;如果采用BP或SP作为基地址指针,则默认使用SS段寄存器指向堆栈段。
如果不使用默认的段选择器,需要书写段超越指令前缀显式说明。段超越指令前缀,是一种只能跟随具有存储器操作数的指令之前的指令,其助记符是段寄存器名后跟英文冒号,即CS:、SS:、DS:或ES:。
偏移地址的组成
存储器操作数寻址使用的偏移地址常被称为有效地址EA(Effective Address)。
为了方便各种数据结构的存取,8086处理器设计了多种主存寻址方式,但可以统一表达如下:
其中基址寄存器是BX或BP,变址寄存器是SI或DI,位移量是8或16位有符号值。
直接寻址
存储器的直接寻址方式的有效地址只有位移量部分,直接包含在指令代码中,直接寻址常用于存取变量。
例如,将变量COUNT内容传送给AX的指令:
mov ax,count ;也可以表达为mov ax,[count]
汇编语言的指令代码中直接书写变量名就是在其偏移地址(有效地址)的存储单元读写操作数。
假设操作系统为变量COUNT分配的有效地址是2000H,则该指令的机器代码是:A1 00 20,反汇编的指令形
式为:MOV AX, DS:[2000H],其源操作数采用直接寻址。
MASM 汇编程序使用中括号表示偏移地址,变量 COUNT 也可以采用加有中括号[COUNT]的形式,体现其访问存储单元的特性。
寄存器间接寻址
有效地址存放在寄存器中,就是采用寄存器间接寻址存储器操作数。
MASM汇编程序使用英文中括号括起寄存器表示寄存器间接寻址。8086 处理器只有基址寄存器BX和两个变址寄存器SI、DI可以作为寄存器间接寻址的寄存器。
下面的前两条指令的源操作数、后两条指令的目的操作数都是寄存器间接寻址方式:
mov al,[bx] ;字节量传送,BX间接寻址
mov cx,[si] ;字量传送,SI间接寻址
mov [di],dl ;字节量传送,DI间接寻址
mov word ptr[di],1394h ;字量传送,DI间接寻址
寄存器间接寻址中寄存器的内容是偏移地址,相当于一个地址指针。
指令“MOV AL, [BX]”执行时,如果BX=2000H,则该指令功能等同于“MOV AL, DS:[2000H]”:
设计寄存器间接寻址的主要目的是只要将数组或字符串首地址(或末地址)赋值给通用寄存器,利用寄存器间接寻址就可以访问到数组或字符串头一个(或最后一个)元素或字符。
寄存器相对寻址
寄存器相对寻址的有效地址是寄存器内容与位移量之和。(常用于访问数组和结构)
8086只有BX和BP、SI和DI可作为寄存器相对寻址的寄存器。
mov si, [bx+4] ;源操作数采用寄存器相对寻址还可表达为:[4][bx]或4[bx]
这条指令中,源操作数的有效地址由BX寄存器内容加位移量4获得,默认与BX寄存器配合的是DS指向的数据段
基址变址寻址
使用基址寄存器内容加上变址寄存器内容形成有效地址寻址存储器操作数被称为基址变址寻址。
8086的基址寄存器是BX和BP,变址寄存器是SI和DI,使用BP默认访问堆栈段,其他默认访问数据段,可以使用段超越。
mov al,[bx+si] ;源操作数在数据段,也可以表达为:[bx][si]
mov ax,[bp+di] ;源操作数在堆栈段,也可以表达为:[bp][di]
mov ax,ds:[bp+si] ;源操作数在数据段,也可以表达为:ds:[bp][si]
相对基址变址寻址
采用相对基址变址寻址,存储器操作数的有效地址由基址寄存器内容、变址寄存器内容及位移量相加获得。同样,8086的基址寄存器是BX和BP,变址寄存器是SI和DI,使用BP默认访问堆栈段,其他默认访问数据段,可以使用段超越。
mov cx,[bx+si+4] ;源操作数也可以表达为:4[bx+si]
mov ax,80h[bx+di] ;源操作数也可以表达为:80h[bx][di]
mov dx,count[bp][di] ;源操作数也可以表达为:[bp+di+count]