购买
下载掌阅APP,畅读海量书库
立即打开
畅读海量书库
扫码下载掌阅APP

3.1 80486微处理器的寻址方式

根据指令提供的基本信息,寻找操作数或操作数所在地址的规则即为寻址方式(Ad-dressing Mode)。80486的寻址方式可分为两类:操作数的寻址方式和转移地址的寻址方式。

为了讨论操作数寻址方式,利用基本传送指令“MOV ddata,sdata”举例说明,第1操作数ddata为目的操作数,第2操作数sdata为源操作数,该指令的功能是把源操作数的内容复制到目的操作数中。为了讨论转移地址的寻址方式,利用无条件转移指令JMP举例说明。

3.1.1 操作数寻址方式

操作数作为指令的操作对象,可以存储在存储单元中(称为存储器操作数)、存储在寄存器中(称为寄存器操作数)或直接包含在指令中(称为立即数),因此,与之对应有多种寻址方式。80486提供了3类10种操作数寻址方式,其中访问存储器操作数就有8种寻址方式。

1.立即寻址(Immediate Addressing

操作数直接包含在指令中的寻址方式称为立即寻址方式。

例3-1 MOV AX,1234H

这条指令的机器码为B8H,34H,12H,占3个字节。它的含义是将立即数1234H送到寄存器AX中。机器码在内存单元中是由上至下按从低到高的地址顺序排列的,这也是一般CPU取指令的顺序。操作码部分在前,操作数部分在后。若立即数为16位,则存放时低8位在低地址单元存放,高8位在高地址单元存放。如图3-1所示。

图3-1 例3-1立即寻址示意图

立即数可为8位、16位或32位的固定数值,即常数,不能是小数、变量或其他类型的数据,它只能作为源操作数,不能作为目的操作数。立即数跟随指令操作码一起存放在内存的代码段中,在CPU取指令时随指令操作码一起取出并直接参加运算。

汇编语言规定:该操作数必须以数字开头,若某个十六进制数以字母开头,其前面必须增加数字0作前缀;数制用后缀表示,B表示二进制数,H表示十六进制数,D或者默认表示十进制数,Q表示八进制数。汇编程序对于不同进制的立即数一律汇编成等值的二进制数,负数自动汇编成机器数补码形式,用单引号括起来的字符汇编成相应的ASCII码。此外,立即数还可以是算术表达式,汇编程序会按照一定的规则自动计算出结果。

2.寄存器寻址(Register Addressing)

在这种寻址方式下,操作数存放在CPU内部的某个8位、16位或32位的通用寄存器中。

例3-2 MOV AH,CL;将CL的内容复制到AH中

采用这种寻址方式的指令编码短,执行时操作就在CPU内部进行,无须访问存储器,故执行速度快。

3.存储器操作数寻址(Memory Operator Addressing)

除上述两类寻址方式外,以下各种寻址方式的操作数都在除代码段以外的内存单元中。通过不同寻址方式求得操作数地址,从而取得操作数。从第2章已经知道,操作数地址是由段基址和偏移地址共同形成,段基址在实模式和保护模式下可通过不同的途径取得,在这一节里要解决的问题是如何取得操作数的偏移地址。

为适应处理不同数据结构的需要,大多数情况下,在指令中并不直接给出操作数的偏移地址,而是在指令中给出计算操作数所在内存单元偏移地址的表达式,完整的地址表达式如下:

段寄存器:[基址寄存器+变址寄存器×比例因子+位移量]

其中,冒号之前的部分称为段超越前缀,80X86执行某种操作时有基本的段约定,即预先规定了采用的段和段寄存器,如果要改变默认的段约定,则需要在指令中明确指出来(即段超越),以通知CPU指令要访问的是哪一个逻辑段。冒号之后的部分为有效地址表达式,有效地址(Effective Address,EA)又称偏移地址,它表示在一个逻辑段中,某内存单元相对于段首单元的地址偏移量。

对于32位寻址(工作于保护方式)和16位寻址(工作于8086方式)时,可作基址、变址的寄存器,比例因子以及位移量的取值有所不同。表3-1给出了这两种情况下4个分量的规定。

表3-1 16位和32位寻址时的4个分量定义

根据指令中出现的操作数所在内存单元的地址表达式的不同,该类寻址方式共有8种,下面详细介绍这8种存储器操作数寻址方式。

(1)直接寻址(Direct Addressing)

直接寻址是指操作数所在内存单元的有效地址EA直接出现在指令中,EA可以是8位、16位或32位。这种寻址方式是对存储器操作数进行访问时可采用的最简单方式。

例3-3 MOV AX,DS:[1000H]

这条指令的含义是:将DS段中有效地址为1000H和1001H两单元中的内容送给AX。

假设DS=2000H,则源操作数所在单元的物理地址=20000H+1000H=21000H,其执行情况如图3-2所示。执行结果为AX=1234H。应注意的是,这种形式下,指令中的DS不能省略。

图3-2 例3-3直接寻址示意图

在汇编语言中,有时也用一个符号代替数值,以表示操作数的有效地址,一般将这个符号称为符号地址,这时操作数本身若无特殊声明,则默认存放在内存的DS所指数据段中。上例中若用ASDAT代替有效地址1000H,则该指令可写成:

其中ASDAT是符号地址,它必须在程序的开始处予以定义,有关内容将在第4章介绍。

需要注意,不能将直接寻址与前面介绍的立即寻址混淆,直接寻址指令中的数值不是操作数本身,而是操作数所在单元的有效地址。为了区分两者,指令系统规定有效地址必须用一对方括弧括起来。

(2)寄存器间接寻址(Register Indirect Addressing)

这种寻址方式下,操作数所在内存单元的有效地址由规定的寄存器指出。在该寻址方式中,80486微处理器规定:

● 16位寻址时,EA可以由SI、DI、BP或BX提供。

若以SI、DI、BX间接寻址,则默认操作数在DS段中。

若以BP间接寻址,则默认操作数在SS段中。

例3-4 MOV AX,[SI]

设DS=4200H,SI=5000H,则源操作数所在单元的物理地址=42000H+5000H=47000H,执行情况如图3-3所示。执行结果:AX=3525H。

图3-3 例3-4寄存器间接寻址示意图

例3-5 MOV CH,[BP]

设SS=3000H,DS=3500H,BP=1340H,则该指令执行后,将31340H单元的内容送给CH。

● 32位寻址时,8个32位通用寄存器均可作间址寄存器。除ESP、EBP默认段寄存器为SS外,其余6个通用寄存器均默认段寄存器为DS。

这种寻址方式中的寄存器常作为表格处理时的地址指针,修改寄存器的内容就可以指向表格的不同元素。

(3)寄存器相对寻址方式(Register Relative Addressing)

在这种方式中,操作数所在内存单元的有效地址为规定的基址寄存器或变址寄存器的内容与一个常量(即位移量,Displacement)之和。在指令格式中,地址表达式写成:

段寄存器:[基址寄存器/变址寄存器+位移量]

或者

段寄存器:位移量[基址寄存器/变址寄存器]

如果是访问约定的逻辑段,则段前缀可以省略。80486微处理器规定:

● 16位寻址时,BX和BP作为基址寄存器,SI和DI作为变址寄存器,位移量可以为8位或16位。在默认段超越前缀时,BX、SI、DI以DS作为默认段寄存器,BP以SS作为默认段寄存器。

● 32位寻址时,8个32位通用寄存器均可作基址/变址寄存器,位移量可以为8位或32位。在默认段超越前缀时,ESP、EBP以SS作为默认段寄存器,其余6个通用寄存器均以DS作为默认段寄存器。

例3-6 MOV AX,DISP[SI]或MOV AX,[DISP+SI]

设DS=3000H,SI=2600H,DISP=64H,则源操作数所在内存单元的物理地址为

30000H+2600H+64H=32664H

若内存储器的32664H字单元的内容为841BH,则执行上述指令后AX=841BH。

这种寻址方式适于对一维数组的元素进行检索操作,用位移量表示数组起始单元的偏移地址,基址寄存器/变址寄存器表示数组元素的下标。

需要注意的一个问题是,在寄存器间接寻址和寄存器相对寻址这两种寻址方式中,程序员可以使用16位的寄存器寻址,也可以使用32位的寄存器寻址。当CPU工作在实地址模式的时候,段长度最大为64KB,不论采用16位寄存器寻址还是32位寄存器寻址,都必须保证CPU最终算出的EA不超过FFFFH,而且操作数最高字节单元的EA也不能超过FFFFH,否则执行寻址操作时程序将出现异常,不能继续执行。例如:

(4)基址变址寻址方式(Based Indexed Addressing)

操作数的有效地址是一个基址寄存器和一个变址寄存器的内容之和。在指令格式中,地址表达式写成:

段寄存器:[基址寄存器+变址寄存器]

这里基址寄存器和变址寄存器的使用规定以及段寄存器的默认规定与前述相同。当基址寄存器和变址寄存器默认的段寄存器不同时,一般规定由基址寄存器来决定哪一个段寄存器为默认段寄存器。

基址变址寻址主要用于二维数组操作和二重循环等。数组首地址可存放在基址寄存器中,而用变址寄存器来访问数组中的各个元素。由于两个寄存器都可以修改,所以它比直接寻址方式更加灵活。

(5)相对基址变址寻址方式(Relative Based Indexed Addressing)

该方式中,操作数所在内存单元的有效地址是基址寄存器、变址寄存器的内容与一个常量(即位移量)之和。在指令格式中,完整的地址表达式为

段寄存器:[基址寄存器+变址寄存器+位移量]

段寄存器:位移量[基址寄存器+变址寄存器]

段寄存器:位移量[基址寄存器][变址寄存器]

有关规定如前所述。

这种寻址方式主要用于起始地址不为“0”的二维数组操作和二重循环等。

例如,存储器中存放着由多个记录组成的文件,位移量可指向文件首部,基址寄存器指向某个记录,变址寄存器则指向该记录中的一个元素。这种寻址方式也为堆栈的另一种处理提供了方便,利用BP指向栈顶,从栈顶到数组的首地址可用位移量表示,变址寄存器可用来访问数组中的某个元素。

(6)比例变址寻址方式(Scaled Indexed Addressing)

操作数的有效地址是变址寄存器的内容乘以比例因子再加上位移量之和,所以EA由3种成分组成。在指令格式中,完整的地址表达式为

段寄存器:[变址寄存器×比例因子+位移量]

段寄存器:位移量[变址寄存器×比例因子]

其中比例因子可以是1、2、4、8中的任一个数,变址寄存器乘以比例因子的操作是在CPU内部靠硬件完成的。除ESP外的任何通用寄存器均可作变址寄存器,且EBP默认SS作段寄存器,其余以DS作段寄存器。

该方式只适用于32位寻址的情况,可用于对一维数组的数组元素进行检索操作。位移量表示数组起始单元地址的偏移量,变址寄存器的内容表示数组元素的下标。当数组元素大小为2、4、8字节时,用带比例因子的变址寻址方式更方便、更高效。

例3-7 MOV EDX,COUNT[EDI∗4]

该条指令可以把双字数组COUNT中的元素3送到EDX中,用这种寻址方式可直接在EDI中放入3,选择比例因子4(数组元素为4字节长)就可以方便地达到目的(见图3-4),而不必像在寄存器相对寻址方式中要把变址值计算后装入寄存器中。

图3-4 例3-7比例变址寻址示意图

(7)基址比例变址寻址方式(Based Scaled Indexed Addressing)

操作数的有效地址是变址寄存器的内容乘以比例因子再加上基址寄存器的内容之和。在指令格式中,完整的地址表达式为

段寄存器:[变址寄存器×比例因子+基址寄存器]

段寄存器:[基址寄存器][变址寄存器×比例因子]

这种寻址方式与基址变址寻址方式相比,增加了比例因子,其优点是很明显的。寻址过程中,变址寄存器内容乘比例因子的操作是在CPU内部由硬件完成的。该方式也只适用于32位寻址的情况,主要用于数组元素大小为2、4、8字节时的二维数组检索操作等场合。

(8)相对基址比例变址寻址方式(Relative Based Scaled Indexed Addressing)

操作数的有效地址是变址寄存器的内容乘以比例因子,加上基址寄存器的内容,再加上位移量之和,所以有效地址由4部分组成。在指令格式中,完整的地址表达式为如下格式:

段寄存器:[基址寄存器+比例因子×变址寄存器+位移量]

段寄存器:位移量[基址寄存器+比例因子×变址寄存器]

段寄存器:位移量[基址寄存器][比例因子×变址寄存器]

这种寻址方式比相对基址变址方式增加了比例因子,便于对元素大小为2、4、8字节的二维数组的处理。寻址过程中,变址寄存器内容乘比例因子的操作是在CPU内部由硬件完成的。该方式也只适用于32位寻址的情况。

例3-8 假定80486工作在实模式下,请分别指出下列指令中两个操作数的寻址方式;如果是存储器操作数,请用表达式分别表示出对应的有效地址和物理地址。

特别地,在存储器中有一片按照LIFO规律存取数据的特殊存储区域——堆栈,堆栈在所有微处理器中都起着重要的作用,它可用于暂时存放数据,数据用PUSH指令压入堆栈,用POP指令弹出堆栈;也可为程序保存返回地址,子程序调用指令CALL用堆栈保存程序返回地址,子程序返回指令RET从堆栈取出返回地址。对于堆栈区域中存储单元的寻址是一种特殊的存储器操作数寻址方式,它利用两个寄存器访问:堆栈指针SP和堆栈段寄存器SS。

3.1.2 转移地址寻址方式

在程序运行过程中,往往需要根据不同的条件执行不同的程序段,因此程序的执行要产生分支或转移。在指令系统中,控制程序执行顺序的指令称为控制转移指令,这组指令的实质是根据需要修改IP或修改CS:IP的内容。控制转移指令的寻址方式涉及如何确定转移的目标地址。

根据指令中目标地址的出现形式,转移目标地址的寻址方式分为直接寻址和间接寻址。在指令中直接给出转移目标地址的方式是直接寻址方式;间接寻址方式是指在指令中给出的寄存器或内存单元中存放着转移的目标地址。

根据转移的目标地址是否在当前段内,转移指令可以分为段内转移和段间转移两大类型。

段间转移类型的指令在执行时要同时改变CS和IP的值,其转移目标地址的标号属性用FAR表示;段内转移类型的指令在执行时仅改变IP的值,其转移目标地址的标号属性用NEAR表示。对于距离很短的段内转移(-128~+127),可称为短转移,用SHORT运算符指出其转移的相对位移量不超过一个字节所能表示的范围。

1.段内直接寻址(Intrasegment Direct Addressing)

在这种寻址方式下,通过当前IP寄存器的内容与一个8位或16位位移量之和得到转移的目标地址。位移量为8位时,称为短程转移;位移量为16位时,称为近程转移。

指令的汇编语言格式表示为

其中,PROGRM和OUTSET均为转向目的地的符号地址,在机器指令中,用位移量来表示。在汇编指令中,如果位移量为16位,则在符号地址前加运算符NEAR PTR;如果位移量为8位,则在符号地址前加运算符SHORT。

对于386及其后继机型,代码段的偏移地址存放在EIP中,同样用相对寻址的段内直接方式,只是其位移量为8位或32位。8位对应于短跳转;32位对应于近跳转。由于位移量本身是个带符号数,所以8位位移量的跳转范围在-128~+127的范围内;16位位移量的跳转范围为±32KB;32位位移量的跳转范围为±2GB。所有机型的汇编格式均相同。

2.段内间接寻址(Intrasegment Indirect Addressing)

该方式中,转移的目标地址存放在寄存器或存储单元中。寄存器或存储单元的内容可以用数据寻址方式中除立即数寻址以外的任何一种寻址方式取得,所得到的内容将用来取代IP寄存器的值。该寻址方式不能用于条件转移指令。

段内间接寻址转移指令的汇编格式可以表示为

其中WORD PTR为运算符,用以指出其后的寻址方式所取得的目标地址是一个字的长度。

3.段间直接寻址(Intersegment Direct Addressing)

指令中直接提供转移目标地址的段基址和偏移地址,所以,只要用指令中指定的偏移地址取代IP寄存器的内容,用指令中指定的段基址取代CS寄存器的内容,即可完成从一个段到另一个段的转移操作。

指令的汇编语言格式可表示为

其中,NEXT为转移目的地的符号地址,FAR PTR则是表示该符号地址属性的运算符。

4.段间间接寻址(Intersegment Indirect Addressing)

该方式下,用存储器中两个相继字的内容来取代IP和CS寄存器中原来的内容,以达到段间转移的目的。这里,存储单元的地址是由指令指定除立即数寻址方式和寄存器寻址方式以外的任何一种数据寻址方式取得。

这种指令的汇编语言格式可表示为

其中,[REL+BX]说明数据寻址方式为寄存器相对寻址方式,DWORD PTR为双字属性运算符,说明转移的目标地址需取双字内容为段间转移指令所需的段基址与偏移地址。

3.1.3 指令的执行时间和占用空间

指令的执行时间取决于时钟周期的大小和执行指令所需要的时钟周期数。如果涉及内存操作,那么执行一条指令的时间为基本执行时间加上计算有效地址所需要的时间。

对同一种指令,如果寻址方式不同,其指令执行时间可能相差很大。寄存器操作数的指令执行速度最快,立即数操作数次之,存储器操作数的指令执行速度最慢。这是由于寄存器位于CPU的内部,执行寄存器操作数指令时,CPU可以直接从内部寄存器中取得操作数,不需要访问内存,因此执行速度很快。立即数操作数作为指令的一部分,在取指时已经被CPU取出后存放在指令队列中,执行指令时也不需要访问内存,因而执行速度也比较快。而存储器操作数则先要由CPU计算出其所在单元的物理地址,再执行存储器的读/写操作。所以相对前述两种操作数来说,指令的执行速度最慢。

从8086发展到Pentium的15年时间内,计算机生产厂商在提高计算机的运行速度上下了很大功夫,除时钟频率已从原来的5MHz提高到300MHz外,又在体系结构方面采用了如数据预取、高速缓冲、流水线等多项重叠或并发技术,使指令的执行速度有了很大的提高,自80X86引入流水线结构以来,指令执行的基本时间中,已不再计算取指令的时间。在有些指令的执行过程中要多次访问内存,因此,访问内存的次数是影响指令执行总时间的重要因素。

汇编语言源程序输入计算机后,由机器提供的“汇编程序”将它翻译成由机器指令组成的机器语言程序,才能由计算机识别并执行。80X86的机器指令是可变字节指令,即不同指令或不同寻址方式的机器指令长度不同,一条16位寻址格式指令的长度可为1~7个字节,32位寻址指令则最长可达14个字节,平均指令长度为3.2个字节。如计入前缀字节(如段超越前缀等)长度还会增加。这样,一个程序一旦装入计算机,它就会占有一定的存储空间。程序量越大,占有的存储空间也越大。

完成同样功能的不同程序,可能会在占用的存储空间和执行时间上有很大差别。因此,在编制程序时,如果对程序所占用的空间或程序的执行时间要求不高,只要根据题意编制出合乎要求的程序即可,当然也应尽量在空间和时间上提高运行效率。而对于程序所占用的存储空间或者对于程序执行的时间要求很高的情况下,应仔细斟酌程序的算法、数据结构以及指令与寻址方式的选用,以编制出符合要求的程序。 8obavnaMtEtK6QBMcCa6iFSjpYWdtLe+DSbkIXe8xlaH65cxtVAME/g0qrsPOAZK

点击中间区域
呼出菜单
上一章
目录
下一章
×