在汇编语言程序中,一个存储单元的地址采用逻辑地址来表示,其形式为:
段基值(或选段择器):偏移地址
操作数地址(物理地址)是根据段基值(或段选择器)和偏移地址通过一定的方法得到。
段基址在实模式和保护模式下可从不同的途径取得。
偏移地址是指存放操作数的存储单元与段起始地址(段基址)之间的字节距离。
在80x86里,把按寻址方式计算出来的操作数偏移地址称为有效地址EA(Effective Address)。
存储器操作数的寻址方式不同,则形成有效地址EA的方法就不同。有效地址EA可由4个地址分量的某种组合求得,分别是:
① 位移量 :指令代码中的一个8位、16位或32位二进制数,但它不是立即数,而是一个地址量。在源程序中,位移量通常以符号地址(变量名或标号)的形式出现,也可以是常数,经汇编后,这些符号地址的偏移地址或常数就转换为指令代码中的位移量。
② 基地址:基址寄存器或基址指针的内容。
③ 变址量 :变址寄存器的内容。
④ 比例因子(Scale Factor) :80386及其后继机型新增加的寻址方式中的一个术语,其值可为1,2,4或8。在含比例因子的寻址方式中,可用变址寄存器的内容乘以比例因子来取得变址值。
8086/80286只能使用16位寻址,而80386及其后继机型则既可用32位寻址,也可用16位寻址。在这两种情况下,对以上4个地址分量的组成有不同的规定,如下表所示:
16/32位寻址时有效地址4种分量的组成
对不同的存储器寻址方式,构成其有效地址EA的地址分量是不同的,但这些寻址方式的有效地址的计算都可以用下式表示:
EA= 基地址 +(变址量 X比例因子)+位移量
上式中的每一个地址分量均可空缺,但比例因子只能与变址寄存器同时使用。
6种存储器寻址方式
1.直接寻址方式(Direct Addressing)
指令所需的操作数存放在存储单元中,操作数的有效地址EA直接由指令代码中的位移量提供,即EA只包含位移量这一种地址分量。此时,位移量的值就是操作数的有效地址,如下图所示:
① 用数值地址表示EA
在采用直接寻址方式的汇编指令中,如用数值表示操作数的有效地址,则操作数所在段的段寄存器必须指明,不能省略。
例如,传送指令源操作数的有效地址用数值地址表示:
MOV BX,DS:[ 1000H ]
这条指令完成将当前数据段偏移1000H个字节的字单元内容1234H送入BX中,如下图所示,其中源操作数的有效地址EA是1000H。“MOD R/M”是指令代码中的寻址字段。
② 用符号地址表示EA
在源程序中,常用符号地址表示存放操作数的存储单元,因此在汇编指令中,可用符号地址表示的直接寻址方式来存取操作数。
操作数如果存放在数据段中,则指令中不必给出数据段寄存器名(即默认使用DS);如果操作数不是存放在数据段中,则必须给出段寄存器名。例如:
MOV BX,VAR ;将VAR指向的字单元内容送到BX中
MOV DA_BYTE,0FH ; 将立即数0FH置入DA_BYTE指向的字节单元
MOV CL,DA+3 ; 把由DA地址偏移3个字节的字节单元内容送到CL中
上述3条指令分别等价于:
MOV BX,DS:VAR
MOV DS:DA_BYTE,0FH
MOV CL,DS:DA+3
2.寄存器间接寻址方式(Register Indirect Addressing)
寄存器间接寻址:指令所需的操作数在存储单元中,操作数的有效地址EA直接从基址寄存器或变址寄存器中获得,即EA只包含基址寄存器内容(或变址寄存器内容)这一种地址分量。
这种寻址方式实际上是将有效地址事先存放在一个寄存器中,因此这个寄存器就如同一个地址指针。
寄存器间接寻址方式:
16位寻址时可用的寄存器是BX、BP、SI和DI;
32位寻址时可用EAX、EBX、ECX、EDX、ESP、EBP、ESI和EDI等8个通用寄存器。
使用BP、ESP和EBP时,其默认段为SS段。其他寄存器的默认段为DS寄存器。
由于用寄存器作为地址指针,因此在程序中只要修改间址寄存器的内容,就可以用同一条指令访问不同的存储单元。这种寻址方式的使用格式如下:
3.寄存器相对寻址方式(Register Relative Addressing)
也称变址寻址方式或基址寻址方式
指令所需的操作数在存储单元中,操作数的有效地址EA是两个地址分量之和:基址寄存器(或变址寄存器)的内容与指令中指定的位移量之和。这种寻址方式如下图所示 :
若使用变址寄存器称为变址寻址方式;
若使用基址寄存器称为基址寻址方式。
所使用的寄存器及与其对应的默认段情况同寄存器间接寻址方式。
在汇编指令中,位移量部分可用数值表示,也可用符号地址表示(此时用符号地址的偏移地址作为位移量),其寻址方式的使用格式如下:
MOV AX, 10H[SI];位移量为8位常数,EA=10H + (SI),默认DS
MOV TAB1[BP], CL;位移量为符号地址TAB1的16位偏移地址,
默认段寄存器是SS
寄存器相对寻址方式常用来访问顺序存放在主存中的一维数组、表、字符串等。其典型用法是将指令中不能修改的位移量作为基准地址,而将变址或基址寄存器内容作为修改量。例如数组的起始单元位置是固定的,因此由指令中的位移量给出;而被访问的数组元素相对其起始单元的距离由变址或基址寄存器提供,通过修改寄存器的内容就可以访问数组中不同的元素。
例:如下图,一维数组ARY存放在主存的数据段,每个元素长度相同且都占2个字节单元。从数组的首址起依次存放各数组元素 ARY(0)、ARY(1)、ARY(2)…、ARY(i)、…。
传送指令:
MOV AX,ARY[SI]
•指令中的符号地址ARY指向该数组的首址;
•变址寄存器SI的内容表示所访问元素与数组首址之间的字节距离,则所访问元素的有 效地址:
EA= ARY的偏移地址+( SI)
•当SI内容为0时访问ARY(0)元素;
•SI内容为1*2时访问ARY(1);
•SI内容为 i*_2时访问ARY(_i),即通过修改SI的内容可以访问数组中任何一个元素。
4.基址变址寻址方式(Based Indexed Addressing)
基址变址寻址方式**:指令所需的操作数在主存单元中,操作数的有效地址EA是三个地址分量之和:基址寄存器内容、变址寄存器内容与指令中的位移量(0位、8位、16位或32位)之和。
寻址过程如下图所示:
基址变址寻址方式的位移量可用数值或符号地址表示,
其使用格式如下:
MOV AX, 200H[BX][SI] ; 位移量为16位常数, EA=200H+(BX)+(SI),
默认段寄存器为DS
MOV AX, ARRAY[BP][SI]; 位移量为符号地址ARRAY的16位 偏移地址,
默认段寄存器为SS
MOV [BP][DI],DL;位移量为0,EA=(BP) +(DI ) ,默认段寄存器SS
由于基址变址寻址方式中有两个地址分量可以在程序执行过程中进行修改,因此常用来访问存放在主存中的二维数组。
如上图所示,ARRAY数组是10行、10列的二维数组,按行存放在主存堆栈段中。每个元素占用一个字节单元。从数组的首址ARRAY起依次存放各数组元素:
第0行元素为ARRAY(0,0)~ARRAY(0,9)共10个,
第1行元素为ARRAY(1,0)~ARRAY(1,9),…。**
5.比例变址寻址方式(Scaled Indexed Addressing)
指令所需的操作数在主存单元中,操作数的有效地址EA是变址寄存器的内容乘以指令中指定的比例因子再加上位移量之和,所以EA由4种成分组成。这种寻址方式如下图所示:
这种寻址方式与相对寄存器寻址相比,增加了比例因子,其优点在于:对于元素大小为2,4,8字节的数组,可以在变址寄存器中给出数组元素下标,而由寻址方式通过用比例因子把下标转换为变址值。
例:MOV EAX,COUNT[ESI * 4]
如要求把双字数组COUNT中的元素3送到EAX中,采用比例变址寻址
方式可直接在ESI中放入3,选择比例因子4(数组元素为4字节长)就能达到目的。如右图所示。而不必像在相对寄存器寻址方式中那样,把变址值直接装入寄存器中。
6.基址比例变址寻址方式(Based Scaled Indexed Addressing)
指令所需的操作数在主存单元中,操作数的有效地址是变址寄存器的内容乘以比例因子,加上基址寄存器的内容,再加上位移量(0位、8位或32位)之和。所以有效地址EA由4种成分组成。这种寻址方式如下图所示。
这种寻址方式比基址变址方式增加了比例因子,便于对元素为2,4,8字节的二维数组进行处理。
【例4-10】 MOV EAX,TABLE[EBP][EDI*4]