80X86寻址方式总结2008年05月03日 星期六 下午 11:48
一:概论
80x86汇编程序都是分段程序设计结构,每个程序段都有一个开始地址:段基址。在保护模式下段基址要由16位的段选择子得到,这些段选择子存放在六个段寄存器(CS,SS,DS,ES,FS,GS)中:
代码段总是由 CS 段寄存器来指示;
堆栈段总是由 SS 段寄存器来指示;
字符处理指令总是使用 ES 段寄存器作为目标操作数的段寄存器;
一般的数据段可用 DS、ES、FS、GS来指示,但 DS 作为数据段的默认段寄存器,用它来寻址比其它几个段寄存器的效率高,因此最好安排 DS 寻址最常引用的数据段,而 ES、FS、GS去寻址一些不常用的数据段。
段内偏移地址(某个字节相对段基址的偏移量)也被称为有效地址 EA(effective address),它由以下4个部分组成:
EA = 基址 + (变址 * 比例因子) + 位移量
基址、变址、位移量的值可正可负,比例因子只能为正。
1:基址
(32位寻址):
1):如果基址寄存器是 ESP或EBP,则段寄存器为 SS;
2):如果基址寄存器是其它通用寄存器,则段寄存器为 DS;
(16位寻址):
基址寄存器可以是 BX 或 BP
2:变址
(32位寻址):
变址寄存器可以为除 ESP 之外的32位通用寄存器
(16位寻址):
变址寄存器可以是 SI 或 DI
3:比例因子
一个常数,可取 1、2、4、8。
4:位移量
一个8位、16位、32位的常数。
二:详解
默认情况下,存储器寻址使用DS数据段,可以使用段寄存器来显式指出选择的段。
1:立即寻址
对多字节立即数,高字节放在寄存器高位,低字节放在寄存器低位。
例:
MOV BL,43 ;把十进制数43放入BL中
MOV AX,98H ;把十六进制数98H放入AX中
MOV AL,'A' ;把字符'A'的ASCII码放入AL中
MOV CX,'AB' ;把字符'AB'的ASCII码放入CX中
2:寄存器寻址
指令中必须是同长的寄存器
3:直接寻址
指令中直接提供源操作数的偏移地址,它作为代码的一部分存放在代码段中。
例:
MOV BL,DS:[00300H] ;把DS数据段中偏移地址为300H的字节复制到BL
MOV CX,ES:[00300H] ;把ES数据段中偏移地址为300H的字复制到CX
MOV EAX,DwordVar ;把DS数据段中DwordVar单元复制到EAX
MOV CL,ByteVar ;把DS数据段中ByteVar单元复制到CL
4: 寄存器间接寻址
操作数的有效地址存放在指令指明的寄存器中,能够用作间接寻址的寄存器有:
EAX,EBX,ECX,EDX,ESI,EDI --> 使用 DS 作为段寄存器
ESP,EBP --> 使用 SS 作为段寄存器
例:
LEA EBX, ARRAY ;把数组开始地址送EBX
MOV AL, [EBX] ;访问数组的第0个元素,若要访问其它元素,只需增加数组索引EBX的值
MOV AX, [EBP] ;把SS段中EBP指向的字单元复制到 AX
MOV [EBP], AX ;把AX的值复制到SS段中EBP指向的单元
MOV [EDI], AL ;把AL的值复制到DS段中EDI指向的单元
MOV AL, [EDX] ;把DS段中EDX指向的字节单元复制到 AL
5:寄存器相对寻址
有效地址EA等于寄存器R中的内容与位移量X的和,即 EA = X + [R],该方式适用于数组、表格处理。
EAX,EBX,ECX,EDX,ESI,EDI --> 使用 DS 作为段寄存器
ESP,EBP --> 使用 SS 作为段寄存器
例:
MOV AX, Table[ESI] ;Table中存放表的首地址,ESI存放要访问的表项的索引
MOV AX, [Table + ESI] ;(MOV AX, [Table + ESI]) == (MOV AX, Table[ESI])
MOV AX, 100H[ESI] ;把DS段中ESI加100H的字存储单元的内容复制到 AX
MOV ARRAY[EDI], AL ;把AL的值复制到DS段中ARRAY中的第EDI字节单元中
MOV LIST[EDI+3], AX ;把AX的值复制到DS段中EDI+LIST+3的字单元中
MOV ARRAY[EBX],EAX ;把EAX的值复制到DS段中ARRAY+EBX的双字单元中
6:基址变址寻址
ESP不能作为变址寄存器。汇编器按如下规则区分基址寄存器和变址寄存器:指令的第二操作数中的第一个寄存器为基址寄存器,第二
个寄存器为变址寄存器。比如 MOV EAX, [EDX][ESI](或MOV EAX, [EDX+ESI])中,EDX 为基址寄存器,ESI 为变址寄存器。该方式适用
于数组、表格的处理。
例:
MOV AX, [EBX+ESI] ;DS段中地址为EBX+ESI的存储单元的字数据送AX
MOV AX, [EBP+ESI] ;SS段中地址为EBP+ESI的存储单元的字数据送AX
MOV AX, ES:[EBX+ESI] ;ES段中地址为EBX+ESI的存储单元的字数据送AX
7:相对基址变址寻址
该方式适用于二维数组的寻址。
EA = X + [BP] + [IR]
例:
MOV AX, Disp[EBX][EDI] 或
MOV AX, Disp[EBX+EDI] 或
MOV AX, [Disp+EBX+EDI]
以下三种方式中,任何32位通用寄存器都能用作基址寄存器,除ESP之外的32位通用寄存器均可作为变址寄存器;
若比例因子为1,指令的第二操作数中的第一个寄存器为基址寄存器,第二个寄存器为变址寄存器。若基址寄存器为EBP或ESP,则默认的段寄存器是SS;若基址寄存是其它的寄存器,则默认的段寄存器是DS。
若比例因子为2、4、8,则与比例因子相乘的那个寄存器是变址寄存器。
8:比例变址寻址方式
EA = X + [IR * K]
和寄存器相对寻址相比增加了比例因子,优点在于:对元素大小为2、4、8字节的数组,可在变址寄存器中给出数组元素的下标。
例:
MOV EAX, ARRAY[ESI*4] ;将ARRAY数组中第 (ESI) 个元素送EAX,其中ARRAY数组中元素大小为4
9:基址比例变址寻址
EA = [BR] + [IR * K]
例:
LEA EBP, ARRAY ;把数组开始地址送EBX
MOV EAX, [EBP][ESI*4] ;将ARRAY数组中第 (ESI) 个元素送EAX,其中ARRAY数组中元素大小为4
10:相对基址比例变址寻址
EA = X + [BR] + [IR * K]
例:
MOV AL, 0040400H[EBX][ESI*2]
MOV [EAX+EDI*2+15H], DX ; 把DX寄存器的内容复制到数据段的一存储单元,
; 该存储单元EA = EAX+EDI*2+15H
MOV AL, [EBP+ESI*2-30H] ; 把堆栈中的一字节单元的内容复制到AL中,
; 该存储单元EA = EBP+ESI*2-30H