8086/8088寻址方式
所谓寻址方式,主要是指获得操作数所在的地址的方式,在8088/8086系统中,一般将寻址方式分为两种不同的类型
- 寻找操作数的地址
- 寻找要执行的下一条指令的地址,即程序的地址。后者主要在程序转移或过程调用时用来寻找目标地址或入口地址。这将在调用指令(CALL)和程序转移指令(JMP)中使用的较多。
在8086指令系统中,说明操作数所在地址的寻址方式可分为8种。
立即寻址
立即寻址方式只针对源操作数,此时源操作数是一个立即数,它作为指令的一部分。紧跟在指令的操作码之后,存放于内存的代码段中,在CPU取指令时随指令码一起取出并直接参与计算。这里立即数可以是8位或16位的整数。若为16位,则存放时低8位在低地址单元存放,高8位在高地址单元存放。
mov ax,3102h ;表示将16位立即数3102h送入累加器。执行后,ah=31h,al=02h
直接寻址
直接寻址方式表示参加运算的数据存放在内存中,存放的地址由指令直接给出,即指令中的操作数是存储器操作数,"[]"内用16位常数表示存放数据的偏移地址,数据的段基地址默认的数据段,可以允许重设。
mov ax,[3102h] ;表示将数据段中偏移地址为3102h和3103h两单元的内容送到ax中。默认段基地址为DS
mov bl,ES:[1200h] ;表示将ES段中偏移地址为1200h单元的内容送到bl寄存器。
若操作不是放在ds段,则在指令中要用段重设符号加以声明。
在汇编语言中,有时也会用一个符号代替数值以表示操作数的偏移地址,通常把这个符号称为符号地址。例如:用buffer代替偏移地址1200h,则指令表示为
mov bl,es:[buffer]
寄存器寻址
在寄存器方式下,指令的操作数为CPU的内部寄存器。它们可以是数据寄存器,也可以是地址指针、变址寄存器或段寄存器。
mov si,ax ;表示将ax的内容送到寄存器si中,若指令执行前ax=2233h,si=4455h,则指令执行后si=2233h。
采用寄存器寻址方式,虽然指令操作码在代码段中,但操作数在内部寄存器中,指令执行时不必通过访问内存就可以取得操作数。因此执行速度较快。
寄存器间接寻址
寄存器间接寻址是用寄存器的内容表示操作数的偏移地址。此时寄存器中的内容不再是操作数本身,而是存放数据的偏移地址,操作数本身在内存储器中。
寄存器间接寻址方式中存放操作数偏移地址的寄存器只允许SI、DX、BX和BP,它们可简称为间址寄存器或称为地址指针,选择不同的间址寄存器涉及的段寄存器不同。在默认情况下,选择SI、DI、BX作间址寄存器时,操作数在数据段,段基地址由DS决定;选择BP作间址寄存器,则操作数在堆栈段,段基地址由SS决定,但无论选择哪一个间址寄存器都允许段重设,可在指令中用段重设符指明当前操作数在哪一段。
因为间址寄存器中存放的操作数的偏移地址,所以指令中的间址寄存器必须加上方括号,以避免与寄存器寻址混淆。
例如:已知DS=6000H,SI=1200H,61200H存放数据为44H,612001H存放数据为33H,执行指令:mov ax,[si]
。
解释:因为指令中没有指定段重设,所以寻址时使用默认的段寄存器DS,由已知条件可计算出操作数的物理地址为 6000 H ∗ 10 H + 1200 H = 61200 H 6000H*10H+1200H=61200H 6000H∗10H+1200H=61200H,执行结果为:AX=3344H。
若操作数存放在附加段,则本利的指令应为
mov ax,es:[si]
。若间址寄存器采用BP,则操作数默认存放在堆栈段。
例如:若已知SS=8000H,BP=0200H,指令mov bx,[bp]
,因为BP为16字节,所以BL和BH存放的内容各不相同,而指令为低位地址。执行后:
B
L
=
[
80200
H
]
BL=[80200H]
BL=[80200H]单元中的内容,
B
H
=
[
80201
H
]
BH=[80201H]
BH=[80201H]单元中的内容。
使用BX、BP作为间址寄存器的寄存器寻址方式称为基址寻址方式,而将SI,DI作为间址寄存器的寄存器寻址方式称为变址寄存器。
寄存器相对寻址
在寄存器相对寻址中,操作数在内存中的存放地址(偏移地址)由间址寄存器的内容加上指令中给出的一个8位和16位的位移量组成。操作数所在段由间址寄存器决定(规则与寄存器间接寻址方式相同)。因位移量可看作相对量,故把这种带位移量的寄存器间接寻址方式称为寄存器相对寻址。
例如:指令mov ax,data[bx]
的寻址过程示例。设DS=6000H,BX=1000H,DATA=0008H。
解释:操作数所在单元的物理地址为 6000 H ∗ 10 H + 1000 H + 0008 H = 61008 H 6000H*10H+1000H+0008H=61008H 6000H∗10H+1000H+0008H=61008H,执行结果为AX=5566H
例如:某数据表的首地址(偏移地址)为TABLE,要取出该表中的第10个字节并存放到AL中,可用如下指令段实现(注意位移量是从0开始的)。
mov si,9 ;第10个数的偏移量为9
mov al,[table+si] ;第10个数的偏移量为table+9
相对寻址方式书写格式允许有几种不同的形式。例如:以下几种写法实质是完全等价的。
mov al,data[si]
mov al,si[data]
mov al,data+[si]
mov al,[si]+data
mov al,[data+si]
mov al,[si+data]
基址—变址寻址
基址—变址寻址方式由一个基址寄存器(BX或BP)的内容和一个变址寄存器(SI或DI)的内容相加而形成操作数的偏移地址,称为基址—变址寻址,在默认的情况下,指令中若有BX作基址寄存器,则段地址在DS中;如果用BP作基址寄存器,则段地址在SS寄存器中,但允许使用段重设。
例如:指令mov ax,[bx][si]
的寻址过程,设DS=8000H,BX=2000H,SI=1000H
解释:操作数的物理地址为 8000 H ∗ 10 H + 2000 H + 1000 = 83000 H 8000H*10H+2000H+1000=83000H 8000H∗10H+2000H+1000=83000H,指令执行后AL=[83000H],AH=[83001H]。
注意:使用基址—变址方式时,不允许将两个基址寄存器或两个变址寄存器组合在一起寻址。
基址—变址—相对寻址
基址—变址—相对寻址方式事实上是基址—变址方式的扩充,指令中指定一个基址寄存器和一个变址寄存器。同时还给出一个8位或16位的位移量,将三者相加便可得到操作数的偏移地址。至于默认的段寄存器仍由所用的基址寄存器决定,指令允许使用段重设。
例如:指令mov ax,5[di][bx]
的寻址过程。该指令将段地址为DS,偏移地址为BX+DI+5的连续两个内存中的内容送到ax。
使用这种寻址方式可以很方便地访问二维数组,例如:用基址寄存器存放数组的首地址(偏移地址),而变址寄存器和位移量分别存放行和列的值,指令就可以直接访问二维数组指定的行和列的元素。
与寄存器间接寻址方式类似,基址—变址—相对寻址指令同样有很多种表示。
mov ax,data[si][bx]
mov ax,[bx+data][si]
mov ax,[bx+si+data]
mov ax,[bx]data[si]
mov ax,[bx+si]data
隐含寻址
有些指令的操作码不仅包含了操作的性质,还隐含了部分操作数的地址,如乘法指令MUL,在这条指令中只需指明乘数的地址,而被乘数以及乘积的地址是隐含且固定的。这种将一个操作数隐含在指令码中的寻址方式称为隐含寻址。
例如:mul bl
的功能把AL中的内容与BL的内容相乘,乘积送到AX寄存器中。
上一篇: PHP浮点数的一个常见问题
下一篇: 汇编程序设计:01基础知识