数据寻址
指令中,“数据寻址”指操作数(源操作数和目的操作数)的寻址方式,源操作数和目的操作数可以有不同的寻址方式。
立即寻址
所谓立即,就是取数不需要再去访问存储器和寄存器,而直接在指令中给出(此时指令已经从存储器中加载到了指令队列缓冲器)。大多是常量被赋值给寄存器的情况,目的操作数一般不会出现立即寻址:
MOV AX, 12A2H;//源操作数立即寻址 MOV AL, 01H;//源操作数立即寻址
寄存器寻址
数据放在寄存器中。源和目的操作数都可能为该方式:
MOV AX,12A2H;//目的操作数寄存器寻址 MOV AX,BX;//目的和源操作数都是寄存器寻址
直接寻址
数据放在存储器中,用变量和[常数]来指出段内16位偏移量,其中变量定义后存在存储器的代码段CS里。例如下面,假如DS=0700H,那么物理地址为07034H的单元变为78H,物理地址为07035H的单元变为56H;AL获得地址07034H的内容78H,AH获得变量VAR1指向的字节34H,BL获得VAR1+1指向的字节12H(VAR2指向的内容)。这里的变量相当于[112H]、[113H],其中112H,113H分别是VAR1和VAR2的段内偏移量,而变量的默认段可以看做是CS。
ORG 100H MOV [34H],5678H;//[34H]为直接寻址 MOV AL,[34H]; MOV AH,VAR1;//VAR1直接寻址 MOV BL,VAR1+1;//VAR1+1直接寻址 ret VAR1 DB 34H;//定义变量 VAR2 DB 12H;
寄存器间接寻址
该方式下寄存器内容作为地址,指向存储器中的数据,用[寄存器名]来表示。可采用该方式的寄存器限定于BX、BP、SI、DI,BP的默认段地址是SS,其它三个则是DS。下面代码中BX和BP的值相同,但是由于默认段地址不同,1111H被赋到00100H地址区域,2222H被赋到10100H地址区域;最后由于指定BX使用SS段基地址,AX成功取到值2222H。
MOV AX,0000H; MOV DS,AX;//DS段地址设定 MOV AX,1000H; MOV SS,AX;//SS段地址设定 MOV BX,0100H;//基址寄存器设定 MOV BP,0100H;//基址指针寄存器设定 MOV [BX],1111H;//[BX]寄存器间接寻址 MOV [BP],2222H;//[BP]寄存器间接寻址 MOV AX,SS:[BX];
寄存器相对寻址
相对寻址是在寄存器间接寻址的基础上加上一定的偏移地址。有[寄存器名+常量]、常量[寄存器名]、变量[寄存器名]等等。下面,AL和AH分别得到了012AH和012BH地址的内容;而最后两行是将变量自己的偏移量加到了BX值上作为新地址,因此尽管变量值等于2AH,但是最后计算出的地址并非是012AH和012BH。这里也可以将变量理解为[DISP]形式,则与BX组成[BX][DISP],其偏移地址为BX+DISP。
MOV BX,0100H; MOV [012AH],1234H; MOV AL,2AH[BX];//BX+2AH寄存器相对寻址 MOV AH,2AH[BX+1H];//BX+2BH寄存器相对寻址 MOV CL,VAR1[BX];//BX+OFFSET VAR1寄存器相对寻址 MOV CH,[BX+VAR1+1];
ret
VAR1 DB 2AH;
基址变址寻址
即由基址寄存器BX、BP和变址指针寄存器DI、SI共同决定地址,形式固定为[基址][变址]。下列语句使得01001H地址内容变为1111H。
MOV AX,0000H;
MOV DS,AX;
MOV BX,1000H;
MOV DI,0001H;
MOV [BX][DI],1111H;
基址变址相对寻址
即在基址变址寻址基础上加上一定地址偏移,同样可以使用常量或者变量作为偏移,方式同寄存器相对寻址。下面代码实现01011H地址内容变成1111H。
MOV AX,0000H
MOV DS,AX; MOV BX,1000H; MOV DI,0001H; MOV [BX][DI+0010H],1111H;//BX+DI+0010H基址变址相对寻址
程序寻址
除了数据需要寻址,指令代码也是要通过CS和IP来进行寻址的。正常情况,每执行完一条指令,IP会自动增加,更复杂的情况则来源于跳转指令。
段内直接寻址
即通过标号、寄存器值、常数、变量等方式直接指定新的16位IP偏移地址。下面的例子通过标号ADD1记录指令地址,JMP进行跳转,最后程序实现AL的无限循环自增。当然,也可以用常量等代替标号实现寻址。
ADD1:ADD AL,01H;
JMP ADD1;
段内间接寻址
即将寄存器内容作为地址,到存储器中取数,取出的数作为新的16位IP地址。这类似于数据寻址中的寄存器间接寻址方式,同样地,寄存器只能使用BX、BP、DI、SI。但是,这里不能用方括号,而是使用WORD PTR,表示以寄存器值作为地址取数两个字节。以下代码跳转到地址为01000H的指令,而不是00000H处。
MOV AX,0000H;
MOV CS,AX;
MOV BX,0000H; MOV [BX],1000H;//数据的寄存器间接寻址 JMP WORD PTR BX;//程序的间接寻址
段间直接寻址
借助标号实现跳转,但是该标号指向的是另一段的指令。另外,通过常量和变量已经不能实现段间转移。
段间间接寻址
也是将寄存器内容作为地址,读取4个字节作为CS和IP的值,其中IP获得两个低字节,CS获得两个高字节。下例中,BX保存了VAR1的偏移地址,最终IP获取3344H,CS获取1122H。
MOV BX,OFFSET VAR1; JMP FAR PTR BX;//程序段间间接寻址 ret VAR1 DD 11223344H;