段寄存器的引用
由于8086/8088CPU有四个段寄存器,可保存四个段值,所以可同时使用四个段,但这个段有所分工。每当需要产生一个20位的物理地址时,BIU会自动引用一个段寄存器,且左移4位再与一个16位的偏移相加。
在取指令的时候,自动引用代码段寄存器CS,再加上由IP所给出的16位偏移,得到要取指令的物理地址。
当涉及到一个堆栈操作时,则自动引用堆栈段寄存器SS,再加上由SP所给出的16位偏移,得到堆栈操作所需的物理地址。当偏移涉及BP寄存器时,缺省引用的段寄存器也为堆栈段寄存器SS。
在存取一个普通存储器操作数时,则自动选择数据段寄存器DS或附加段寄存器ES,再加上16位偏移,得到存储器操作数的物理地址。此时的16位偏移,可以是包含在指令中的直接地址,也可以是某一个16位存储器指针寄存器的值,也可以是指令中的偏移再加上存储器指针寄存器中的值,这取决于指令的寻址方式。除了串操作时目的段选择附加段寄存器ES外,却省选择数据段寄存器DS。
在不改变段寄存器值的情况下,寻址的最大范围是64K字节。若某个程序使用的总的存储长度(包括代码、堆栈和数据区)不超过64K字节,则整个程序可以合用一个64K字节的段。若有一个程序,它的代码长度、堆栈长度和数据区长度均不超过64K字节,则可在程序开始时分别给DS和SS等段寄存器赋值,在程序的其他地方就可不再考虑这些段寄存器所含的段值,程序就能正常地运行。假如某个程序的数据区长度超过64K字节,那么就要在两个或多个数据段中存取数据。如果出现这种情况,只要再从存取一个数据段改变到存取另一个数据段时,改变数据段寄存器内的段值就可以了。
由于BIU能根据需要自动选择段寄存器,所以通常情况下在指令中不指明所需要的段寄存器。取指令和堆栈操作所引用的段寄存器分别规定为CS和SS,是不可变的;串操作中目的段的段寄存器规定位ES也是不可变的。但是,在存取一般存储器操作数时,段寄存器可以不一定是DS;当偏移涉及BP寄存器时,段寄存器也不是非要为SS。8086/8088允许使用段超越前缀,改变上述两种情况下所使用的段寄存器,也即用段超越前缀直接明确指定引用的段寄存器。表2.3列出了段寄存器的引用规定,其中“可选用的段寄存器”栏就列出了可作为段超越前缀改变的段寄存器,另外,有效地址EA(Effective Address)就是指段内偏移。
表2.3 段寄存器的引用规定
访问存储器涉及的方式 |
正常使用的段寄存器 |
可选用的段寄存器 |
偏移 |
取指令 |
CS |
无 |
IP |
堆栈操作 |
SS |
无 |
SP |
一般数据存取(下列情况除外) |
DS |
CS、ES、SS |
有效地址 |
源数据串 |
DS |
CS、ES、SS |
SI |
目的数据串 |
ES |
无 |
DI |
BP作为指针寄存器使用 |
SS |
CS、DS、ES |
有效地址 |
2.3 8086/8088的寻址方式
表示指令中操作数据所在的方法称为寻址方式。8086/8088有七种基本的寻址方式:立即寻址、寄存器寻址、直接寻址、寄存器间接寻址、寄存器相对寻址、基址加变址寻址和相对基址加变址寻址。
直接寻址、寄存器间接寻址、寄存器相对寻址、基址加变址寻址和相对基址加变址寻址,这五种寻址方式属于存储器寻址,用于说明操作数所在存储单元的地址。由于总线接口单元BIU能根据需要自动引用段寄存器得到段值,所以这五种方式也就是确定存放操作数的存储单元有效地址EA的方法。BIU能根据需要自动引用段寄存地址EA是一个16位的无符号数,在利用这五种方法计算有效地址时,所得的结果认为是一个无符号数。
除了这些基本的寻址方式外,还有固定寻址和I/O端口寻址等。
2.3.1 立即寻址方式
操作数就包含在指令中,它作为指令的一部分,跟在操作码后存放在代码前。这种操作数称为立即数。
立即数可以是8位,也可以是16位,那么按“高高低低”原则存放,即高位字节在高地址存储单元,低位字节在低地址存储单元。
指令“MOV AX, 1234H”的存储和执行情况如图2.7所示
这种寻址方式主要用于给寄存器或存储单元赋初值的场合。
图 2.6 立即方式示意图
2.3.2 寄存器寻址方式
操作数在CPU内部的寄存器中,指令中指定寄存器号。对于16位操作数,寄存器可以是AX、BX、CX、DX,SI、DI、SP和 BP等;对于8位操作数,寄存器可以是AL、AH、BL、BH、CL、CH、DL和DH。
例如,指令“MOV SI,AX”和指令“MOV AL,DH”中的源操作数和目的操作数均是寄存器寻址。再如,图2.7所示指令中,目的操作数采用寄存器寻址。
由于操作数在寄存器中,不需要通过访问存储器来取得操作数,所以采用这种寻址方式的指令执行速度较快。
2.3.3 直接寻址方式
操作数在存储器中,指令直接包含有操作数的有效地址。操作数一般存放在数据段,所以操作数的地址由DS加上指令中直接给出的16位偏移得到。如果采用段超越前缀,则操作数也可含在数据段外其他段中。
设数据段寄存器DS的内容是5000H字存储单元中的内容是6789H,那么在执行指令“MOV AX,[1234H]”后寄存器AX的内容是6789H。图2.8是此指令的存储和执行情况,为方便,本
章常用(reg)表示寄存器reg的内容。于是该例的假设用(DS)=5000H表示,执行结果用(AX)=6789H表示。
下面指令中目标操作数采用直接寻址,并且使用了段超越前缀:
MOV ES:5678H,BL ;用的段寄存器是ES
这种寻址方式常用于处理单个存储器变量的情况。它可实现在64k字节的段内寻找操作数。直接寻址的操作数通常是程序使用的变量。
注意立即寻址和直接寻址书写表示方法上的不同,直接寻址的地址要放在方括号中。在源程序中,往往用变量名表示。
2.3.4 寄存器间接寻址方式
操作数在存储器中,操作数有效地址在SI、DI、BX、BP这四个寄存器之一中,在一般情况(即不使用段超越前缀明确指定段寄存器)下,如果有效地址在SI、DI和BX中,则以DS段寄存器之内容为段值;如果有效地址在BP中,则以SS段寄存器值内容为段值。
例如,MOV AX,[SI]
假设,(DS)=5000H,(SI)=F1234H
那么,存取的物理存储单元地址是5124H。再设字存储单元的内容是6789H,那么,在执行该命令后,(AX)=6789H。图2.8反映该指令的存储和执行情况。
下面指令种源操作数采用寄存器间接寻址,并且使用了段超越前缀:
MOV DL, CS:[BX] ;引用的段寄存器是CS
下面指令中的操作数采用寄存器间接寻址,由于使用BP作为指针寄存器,所以缺省的段寄存器是SS:
MOV [BP],CX ;引用的段寄存器是BP
这种寻址方式可用于表格处理,在处理完表中的一项后,只要修改指针寄存器的内容就可以方便的处理表中的另一项。
图2.8 寄存间接寻址方式示意图
请注意在书写表示寄存器间接寻址时,寄存器名一定要放在方括号中。下面两条指令的目的操作数的寻址方式完全不同:
MOV [SI],AX ;目的操作数寄存器间接寻址
MOV SI,AX ;目的操作数寄存器寻址
2.3.5 寄存器相对寻址方式
操作数在存储器中,操作数的有效地址是一个基址寄存器(BX、BP)或变址寄存器的(SI、DI)内容加上指令中给定的8位获16位位移量之和。即:
EA=
在一般情况(即不使用段超越前缀明确指定段寄存器)下,如果SI、DI或 BX的内容作为有效地值的一部分,那么引用的段寄存器是DS;如果BP的内容作为有效地值的一部分,那么引用的段寄存器是SS。
在指令中给定的8位或16位位移量采用补码形式表示。在计算有效地址时,如位移量是8位,则被符号扩展成16位。当所得的有效地址超过FFFFH,则取其64K的模。
例如,MOV AX, [DI 1F223H]
假设,(DS)=5000H, (DI)=3678H
那么,存取的物理存储单元是5489BH。再设该字存储单元的内容是55AAH,那么在执该命令后,(AX)=55AAH。图2.10反映该指令的存储和执行情况。
下面指令中,源操作数采用寄存器相对寻址,引用的段寄存器是SS:
MOV BX,[BP-4]
下面指令中,目的操作数采用寄存器相对寻址,引用的段寄存器是ES:
MOV ES:[BX 5],AL
这种寻址方式同样可以用于表格处理,表格的首地址可设置为指令中的位移量,利用修改基址或变址寄存器的内容来存取表格中的项值,所以,这种方式很有利于实现高级语言中对结构或记录等数据类型所实施的操作。
请注意书写时基址或变址寄存器名一定要放在方括号中,而位移可不写在方括号中。下面两条指令源操作数的寻址方式是相同的,表示的形式等价:
MOV AX,[SI 3]
MOV AX,3[SI]
图2.9 寄存器相对寻址示意图
2.3.6 基址加变址寻址方式
操作数在存储器中,操作数的有效地址由基址寄存器之一的内容与变址寄存器之一的内容相加得到。即:
在一般情况(即不使用段超越前缀明确指定段寄存器)下,如果BP之内容作为有效地址的一部分,则以SS之内容为段值,否则以DS之内容为段值。
当所得的有效地址超过FFFFH时,就取其64K的模。
例如,MOV AX,[BX DI]
假设,(DS)=5000H,(BX)=1223H,(DI)=54H
那么,存取的物理存储单元地址是51277H。再设该字存储单元的内容是168H,那么,在执行该指令后,(AX)=168H。图2.10反映该指令的执行情况。
下面指令中,源操作数采用基址加变址寻址,通过增加段超越前缀来引用段寄存器ES:
MOV AX,ES:[BX SI]
下面指令中,目的操作数采用基址加变址寻址,引用的段寄存器是DS:
MOV DX:[BP SI],AL
图2.10 基址加变址寻址方式示意图
这种寻址方式适用于数组或表格处理。用基址寄存器存放数组首地址,而用变址寄存器来定位数组中的各元素,或反之。由于两个寄存器都可以改变,所以能更加灵活的访问数组或表格中的元素。
下面的二种方法是等价的:
MOV AX,[BX DI]
MOV AX,[DI][BX]