寻址方式与指令系统
5.2.1 寻址方式
80386支持先前微处理器的各种寻址方式。在立即寻址方式和寄存器寻址方式中,操作数可达32位宽。在存储器(内存)寻址方式中,不仅操作数可达32位,而且寻址范围和方式更加灵活。
80386继续采用分段的方法管理主存储器。存储器的逻辑地址由段地址(段起始地址)和段内偏移两部分表示,存储单元的地址由段基地址加上段内偏移所得。段寄存器指示段基地址,各种寻址方式决定段内偏移。
在实模式下,段基地址仍然是16的倍数,段的最大长度仍然是64K。段寄存器内所含的仍然是段基地址对应的段值,存储单元的物理地址仍然是段寄存器内的段值乘上16加上段内偏移。所以,尽管80386有32位地址线,可直接寻址物理地址空间达到4G字节,但在实模式下仍然与8086/8088相似。
在保护模式下,段基地址可以长32位,无须是16位的倍数,段的最大长度可达4G。段寄存器内所含的是指示段基地址的选择子,存储单元的地址是段基地址加上段内偏移,但不再是段寄存器之值乘16加上偏移,这与8086/8088完全不同。在保护模式下,段寄存器为选择子,间接指示段基地址。每次对存储器的访问或是隐含地、或是显式地、或是默认地指定了某个段寄存器。由于80386有6个段寄存器,所以在某一时刻程序可访问6个段,而不再是先前的4个段。
段寄存器CS所指定的段仍为当前代码段,SS所指定的段为当前推栈段,DS寄存器是主要的数据段寄存器,为默认的数据段寄存器。其它的ES、FS和GS都可作为访问数据时引用的段寄存器,但必须显式地在指令中指定,它们也即成为段超越前缀,这使得指令在长度和执行时间上的开销稍大一些。
例如:
MOV EAX,[SI] ;默认段寄存器DS
MOV [BP 2],EAX ;默认段寄存器SS
MOV AL,FS:[BX] ;显式指定段寄存器FS
MOV GS:[BP],DX ;显式指定段寄存器GS
80386支持先前微处理器所支持的各种存储器寻址方式,并且还支持32位偏移和存储器寻址方式。80386允许内存地址的偏移可以由三部分内容相加构成:一个32位基址寄存器,一个可乘上比例因子1、2、4或8的32位变址寄存器,及一个8位或32的常数偏移量。并且这三部分可省去任意的两部分。80386支持的32位偏移的存储器寻址方式可归纳如下:
EAX EAX
ECX + ECX Ï +
EDX EDX
EBX EBX
ESP …
EBP EBP
ESI ESI
EDI EDI
为了简化寄存器的分配,可以用8个通用寄存器中的一个作为基地址寄存器,以及用除ESP外的一个变址寄存器。变址寄存器的值可以直接地被使用(比例因子为1),或者按2、4或8的倍率用于16位、32、64位变量变址,而不需要计算位移的指令或使用一额外的寄存器。例如:
MOV EAX,[EDI ESI*8 36H]
5.2.2 指令系统
80386的指令系统保持了对以前机器指令的兼容,并且作了很大的扩展,使寻址更灵活,指令选择的余地更大,并增强了对高级语言的支持。下面介绍它的指令,主要介绍新增的部分,对在8086中原有的只略提一下。
另外,下面说明新增的指令只是相对于8086而言,有些指令在80186、80286中早已存在,并非都是80386指令系统新增的。
1. 通用传送指令
通用传送指令主要是MOV、MOVZX、MOVSX、XCHG、PUSH、POP、POPA。
MOV指令是以前的处理器就有的,MOVZX和MOVSX是新增的。这两条指令支持不同长度的寄存器之间或寄存器与内存之间的数据传送。例如:
MOVZX EAX,BL
MOVZX DWORD PTR[MEM],AX
MOVSX BX,AL
MOVSX WORD PTR[MEM],AL
MOVZX按无符号扩展来传送,即扩展的高位置0;MOVSX则按带符号扩展来传送,即原来最高位是什么,则扩展后的位就补什么,例如:
MOV AL,70H
MOVZX AX,AL ;AX得0070H
MOVSX AX,AL ;AX得0070H
MOV AL,80H
MOVZX AX,AL ;AX得0080H
MOVSX AX,AL ;AX得FF80H
XCHG是数据交换指令,如:
XCHG EAX,EDX ;交换EAX和EDX的内容
PUSH、POP、PUSHA、POPA是堆栈操作指令。其中PUSH和POP除了增加对32位的扩展外,还增加了支持立即数的操作,例如:
PUSH DWORD PTR 34567
指令PUSHA或POPA是英语PUSH ALL和POP ALL的缩写,它们一次过把所有通用寄存器压栈和出栈。
它有两种形式PUSHA、PUSHAD及POPA、POPAD,分别是对16位和32位寄存器进行栈操作。
PUSHAD的入栈顺序是:EAX、ECX、EDX、EBX、ESP、EBP、ESI、EDI,PUSHA与此类似。
2. 累加器传送指令
累加器的传送指令有IN、OUT、XLAT三条。
IN和OUT指令与8086的使用方法一样;XLAT则对32位寻址作了扩展,可以是XLAT和XLATB,其中XLAT以BX为基地址,XLATB是以EBX为基地址。
3. 标志传送指令
标志传送指令有以下四条:LAHF、SAHF、PUSHF、POPF。
其中PUSHF和POPF对32位标志寄存器作了扩展:PUSHFD、POPFD。这两组指令分别对16位和32位的标志寄存器FLAG和EFLAG进行压栈和出栈操作。
4. 地址传送指令
地址传送指令有5个:LDS、LES、LFS、LGS、LSS。它们把存储器中的内容送入段寄存器和指定的通用寄存器。其中LFS和LGS是为新增的两个段存器而设的。其使用如下:
LFS EBS,MEMORY1
LGS EDI,MEMORY2
5. 数据类型转换指令
数据类型转换指令包括:CBW、CWD、CWDE、CDQ。它们的功能如下:
CBW ;AL带符号扩展到AX
CWD ;AX带符号扩展到DX和AX
CWDE ;AX带符号扩展到EAX
CWQ ;EAX带符号扩展到EDX和EAX
6. 算术运算指令
80386指令系统的算术运算指令与8086并没有很大的区别,最大的改变只是对32位寄存器的支持。例如;
ADD EAX,EBX
7. 逻辑指令
逻辑指令包括NOT、AND、OR、XOR、TEST、SHL、SHR、SAL、SAR、ROL、ROR、RCL、RCR、SHRD、SHLD。前面的13个指令是8086中就有的,但它们增加了对32位寄存器的支持。移位指令还增加了一个特征,即对大于1的立即数的支持,例如要将AX左移3位,在8086中必须写成:
MOV CL,3
SHL AX,CL
但现在可以直接写成:
SHL AX,3
最后两个指令是80386指令系统新增的64位移位指令,例如:
SHLD EAX,EBX,10 ;EAX左移10位,低10位由EBS高10位补上,
;EBX不变
SHRD EAX,EBX,10 ;EAX右移10位,高10位由EBX低10位补上,
;EBX不变
需要注意,这2条指令不改变第二个操作数。
8. 串操作指令
串操作指令包括 MOVS、CMPS、SCAS、LODS、STOS、INS、OUTS。前5个指令是8086中原有的,在80386指令系统增加了对32位寄存器的支持,如MOVS可以写成MOVSB、MOVSW、MOVSD。它们的源变址寄存器、目的变址寄存器及计数器是用ESI、EDI、ECX还是用SI、DI、CX,由它所在的段决定。若是32位段,则使用前者,否则使用后者。
新增的INS和OUTS指令,可以是INSB、INSW、INSD和OUTSB、OUTSW、OUTSD,用它们对端口输入/输出连续的字符串,变址寄存器是ESI,端口号要放在EDX中。
9. 控制转移指令
控制转移指令包括如JMP、JZ、JB、LOOP、CALL、RET、INT、INTO、IRET等,它们与在8086中的意义基本相同。
但是,JZ、JB等条件跳转指令的跳转范围不再局限在-128~127之间,而与JMP指令一样,不过,这时生成的指令长度要长一些。
80386指令系统针对JCXZ指令增加了一个指令JECXZ。它的跳转条件是以ECX是否为0,而不是以CX是否为0作为标准。这个指令的跳转范围也仍然是-128~127。
循环指令LOOP的跳转范围也仍然是-128~127。
10. 条件设置指令
80386指令系统新增了条件设置指令,用于支持编译程序和高级语言生成的代码。这些指令根据当前的EFLAG中的标志,来设置对应的寄存器或存储器。例如下面的指令,当EAX与EBX相等时设置AL为1,否则为0:
CMP EAX,EBX
SETZ AL
条件设置指令如表5.1所示,条件设置指令的一般格式为:
SETcc OPRD
其中cc泛指所有的条件设置指令。
11. 标志指令
标志指令与8086一样,包括CLC、STC、CMC、CLD、STD、CLI、STI。
12.位处理指令
80386指令系统新增位处理指令,他们的处理对象是位,而不是通常的字节,字或双字。它们的功能如表5.2所示。前4条叫测试和设置指令。其一般格式为:
BTc OPRD1,OPRD2
其中的c泛指这4位指令。如:
BT AX,3
表5.1 80386指令系统新增条件设置指令的功能
指 令 |
功 能 |
SETZ或SETE |
ZF=1则置1 |
SETS |
SF=1则置1 |
SETO |
OF=1则置 |
SETP或SETPE |
PF=1则置 |
SETB或SETNAE或SETC |
CF=1则置 |
SETBE或SETNA |
CF=1或ZF=1则置1 |
SETL或SETNGE |
SF和OF不相等则置1 |
SETLE或SETNGE |
SF和OF不相等或ZF=1则置1 |
SETNZ或SETNE |
ZF=0则置1 |
SETNS |
SF=0则置1 |
SETNO |
OF=1则置1 |
SETNP或SETPO |
PF=0则置1 |
SETNB或SETAE或SETNC |
CF=0则置1 |
SETNBE或SETA |
CF=0且ZF=0则置1 |
SETNL或SETGE |
SF和OF相等则置1 |
SETNLE或SETG |
SF和OF相等且ZF=0则置1 |
13. 处理器控制与特权指令
处理器控制与特权指令包括HLT、WAIT、ESC、NOP和控制寄存器存取指令。控
表5.2 80386指令系统新增位处理指令的功能
指 令 |
功 能 |
BTS |
将测试位的值送CF,并把指定的测试位置1 |
BTR |
将测试位的值送CF,并把指定的测试位置0 |
BTC |
将测试位的值送CF,并把指定的测试位取反 |
BT |
测试指定的位,并将测试位的值送CF |
BSF |
从低到高扫描目标,如果全为0则ZF置1,否则ZF置0,并把为1的位的序号放入目的的寄存器 |
BSR |
从高到低扫描目标,如果全为0则ZF置1,否则ZF置0,并把为1的位的序号放入目的的寄存器 |
制寄存器存取指令如下:
MOV EAX,CR0
MOV CT0,EAX
MOV EAX,DR0
MOV DR0,EAX
MOV EAX,TR6
MOV TR6,EAX
注意CRn和DRn等几个寄存器只能用MOV指令来存取,其它如PUSH、POP、ADD等指令都不能对它们执行存取操作。