730 likes | 901 Views
第 3 章 IA-32 指令系统. 3.1 基本数据类型 3.2 IA-32 的指令格式 3.3 IA-32 指令的操作数寻址方式 3.4 IA-32 的通用指令. 退出. 3.1 基本数据类型. IA-32 结构的基本数据类型是字节、字、双字、四字和双四字,如图 3-1 所示。. 一个字节是 8 位,一个字是两个字节( 16 位),双字是 4 字节( 32 位),四字是 8 字节( 64 位),双四字是 16 字节( 128 位)。 3.1.1 字、双字、四字和双四字的对齐
E N D
第3章 IA-32指令系统 • 3.1 基本数据类型 • 3.2 IA-32的指令格式 • 3.3 IA-32指令的操作数寻址方式 • 3.4 IA-32的通用指令 退出
3.1 基本数据类型 • IA-32结构的基本数据类型是字节、字、双字、四字和双四字,如图3-1所示。
一个字节是8位,一个字是两个字节(16位),双字是4字节(32位),四字是8字节(64位),双四字是16字节(128位)。一个字节是8位,一个字是两个字节(16位),双字是4字节(32位),四字是8字节(64位),双四字是16字节(128位)。 • 3.1.1 字、双字、四字和双四字的对齐 • 字、双字和四字在内存中并不需要对齐至自然边界(字、双字和四字的自然边界是偶数编号的地址,对于双字和四字来说,地址要分别能被4和8整除)。 • 然而,为改进程序的性能,数据结构(特别是堆栈)只要可能应对齐在自然边界上。这样做的理由是:对于不对齐的存储访问,处理器要求做两次存储访问操作;而对于对齐的访问只要做一次存储访问操作。
3.1.2 数字数据类型 • 1.整数 • IA-32结构定义两种类型整数:无符号整数和符号整数。无符号整数是原始二进制值,范围从0到所选择的操作数尺寸能编码的最大正数。符号整数是2的补码二进制值,能用于表示正的和负的整数值。 • (1)无符号整数 • 无符号整数是包含字节、字、双字和四字中的无符号的二进制数。它们的值的范围,对于字节是从0到255;对于字,从0到65535;对于双字,从0到232–1;对于四字,从0到264–1。
(2)符号整数 • 符号整数是保存在字节、字、双字或四字中的带符号的二进制数。对于符号整数的所有操作都假定用2的补码表示。 • 整数值的范围,对于字节,从–128到+127;对于字从–32 768到+32 767;对于双字,从–231到+231–1;对于四字,从–263到+263–1。 • 2.浮点数据类型 • IA-32结构定义和操作三种浮点数据类型:单精度浮点、双精度浮点和双扩展的精度浮点。 • 这些数据类型的数据格式与IEEE标准754二进制浮点算术所规定的格式直接相对应。
3.1.3 指针数据类型 • 指针是内存单元的地址(见图3-4)。IA-32结构定义两种类型的指针:近(Near)指针(32位)和远(Far)指针(48位)。Near指针是段内的32位偏移量(也称为有效地址)。Near指针在平面存储模式中用于所有存储器引用;或在分段存储模式中用于同一段内的存储器引用。Far指针是一个48位的逻辑地址,包含16位段选择子和32位的偏移。Far指针用于在分段存储模式中的跨段存储引用。
3.1.4 位字段数据类型 • 一位字段是连续的位序列。它能在内存中任何字节的任一位位置开始,并能包含多至32位。 • 3.1.5 串数据类型 • 串是位、字节、字或双字的连续序列。位串能从任一字节的任一位开始并能包含多至232–1位。字节串能包含字节、字或双字,其范围能从0至232–1字节(4G字节)。
3.2 IA-32的指令格式 • 指令有以下格式: • label(标号):mnemonic(助记符)argument1(参数1),argument2(参数2),argument3(参数3) • 其中: • 标号(label)是一标识符后面跟有冒号(∶)。 • 助记符(mnemonic)是一类具有相同功能的指令操作码的保留名。
操作数参数1(argument1)、参数2(argument2)和参数3(argument3)是任选的。可以有零至三个操作数,取决于操作码。若存在,它们可能是文字或数据项的标识符、操作数标识符,或者是寄存器的保留名,或者是在程序的另一部分中声明的赋予数据项的标识符。 操作数参数1(argument1)、参数2(argument2)和参数3(argument3)是任选的。可以有零至三个操作数,取决于操作码。若存在,它们可能是文字或数据项的标识符、操作数标识符,或者是寄存器的保留名,或者是在程序的另一部分中声明的赋予数据项的标识符。
3.3 IA-32指令的操作数寻址方式 • 3.3.1 立即数 • 某些指令用包含在指令中的数据作为源操作数。这些操作数称为立即操作数(或简单称为立即数)。
3.3.2 寄存器操作数 • 源和目的操作数能在寄存器中。 • 3.3.3 存储器操作数 • 在内存中的源和目的操作数由段选择子和偏移量引用。 • 1.规定段选择子 • 段选择子能隐含或显式规定。规定段选择子的最简单的方法是把它加载至段寄存器,然后允许处理器根据正在执行的操作类型,隐含地选择寄存器。
2.规定偏移量 • 内存地址的偏移量部分或者直接作为一个静态值(称为位移量)规定或者由以下一个或多个成员通过计算得到地址: • 位移量——一个8位、16位或32位值。 • 基地址——在通用寄存器中的值。 • 索引——在通用寄存器中的值。 • 比例系数——值2、4或8,用于与索引值相乘。 • 由这些成员相加的结果称为有效地址。这些成员中,除比例系数外其它的每一个都能为正或负(2的补码)。图3-9显示了这些成员能组合成在所选择的段中的有效地址的所有可能的方法。
3.3.4 I/O端口寻址 • 处理器支持多至包含65536个8位I/O端口的I/O地址空间。在I/O地址空间中也可以定义16位和32位的端口。I/O端口可以用立即操作数或在DX寄存器中的值寻址。用立即数寻址,只能用8位立即数,可寻址I/O地址空间的前256个端口;用DX寄存器间接寻址,可寻址全部I/O地址空间。
3.4 IA-32的通用指令 • 3.4.1 数据传送指令 • 数据传送指令在内存和通用寄存器和段寄存器之间传送数据。它们也执行特殊的操作,例如条件传送、堆栈访问和数据转换。
1.MOV指令 • MOV指令是最常用的数据传送指令。它的格式是: • MOV DOPD,SOPD • 它有两个操作数,左边的是目标操作数(DOPD),右边的是源操作数(SOPD)。它把8位、16位或32位源操作数传送至目的地。它在通用寄存器之间、存储器和通用寄存器或段寄存器之间传送数据,或把立即数传送至通用寄存器。
2.条件传送指令 • CMOVcc DOPD,SOPD • 这是由Pentium PRO(即第六代处理器结构)引入的条件传送指令。在传送前,先检查由EFLAGS的状态位(主要是进位标志CF、符号标志SF、零标志ZF和溢出标志OF)构成的条件是否符合指定的条件,若符合指定的条件,则源操作数(SOPD)传送至目标操作数(DOPD);否则,目标操作数不变。
3.交换指令 • (1)XCHG指令 • XCHG DOPD,SOPD • 这是一条交换指令,它有两个操作数:DOPD和SOPD,指令的功能是使两个操作数交换。这条指令的操作数可以是一个字节或一个字。 • (2)BSWAP指令 • 这是一条字节对换指令。它的格式为: • BSWAP DOPD • 它只有一个操作数,它使32位(目标)寄存器的字节顺序反向,即使位0到7与位24到31对换,位8到15与位16到23对换。此指令用于小数在前的值与大数在前的值相互转换。
(3)XADD交换并相加指令 • 指令的格式为: • XADD DOPD,SOPD • 它用第二个操作数(源操作数)与第一个操作数(目的操作数)交换,然后把两个值的和装入目的操作数。目的操作数可以是寄存器或内存单元,源操作数是一寄存器。
(4)CMPXCHG 比较和交换指令 • 指令的格式为: • CMPXCHG DOPD,SOPD • 此指令有两个操作数,它把累加器AL、AX或EAX寄存器的值(取决于操作数的尺寸)与目标操作数相比较。若两值相等,则把源操作数(SOPD)的值加载至目标操作数(DOPD);否则,目标操作数加载至累加器(AL、AX或EAX)。
(5)CMPXCHG8B比较和交换8字节指令 • 此指令的格式为: • CMPXCHG8B DOPD(64位内存操作数) • 此指令把64位在内存中的目标操作数与EDX:EAX中的64位值相比较,若相等,则把包含在ECX:EBX中的64位值存储至目标操作数;否则,把目标操作数中的值存入EDX:EAX寄存器对。目标操作数是8字节的内存单元。对于EDX:EAX和ECX:EBX寄存器对,EDX和ECX包含64位值的高32位,而EAX和EBX包含64位值的低32位。
4.堆栈操作指令 • (1)入栈指令 • PUSH DOPD • 操作数的长度为字或双字,在入栈操作时,把一个字(或双字)从源操作数传送至由SP(ESP)所指向的堆栈的顶部。 • 每一个指令分两步执行: • 先SP-1→SP,然后把AH(寄存器中的高位字节)送至SP所指的单元;再次使SP-1→SP,把AL(寄存器中的低位字节)送至SP所指的单元。
(2)出栈指令 • POP DOPD • 把现行SP所指向的堆栈顶部的一个字(或双字),送至指定的目的操作数;同时进行修改堆栈指针的操作,即SP+2→SP。 • (3)PUSHA/PUSHAD 推入通用寄存器至堆栈 • PUSHA(Push All)推入所有的16位(即8086)的通用寄存器至堆栈。 • PUSHAD(Push All Double)推入所有32位的通用寄存器至堆栈。
(4)POPA/POPAD自堆栈弹出至通用寄存器 • POPA(Pop All)自堆栈弹出至16位通用寄存器。 • POPAD(Pop All Double)自堆栈弹出至32位通用寄存器。 • 5.输入输出指令 • (1)IN • 输入指令。允许把一个字节或一个字由一个输入端口(port),传送至AL(若是一个字节)、AX(若是一个字)或EAX(双字)。 • (2)OUT • 输出指令。允许把在AL中的一个字节、在AX中的一个字或在EAX中的一个双字,传送至一个输出端口。
6.扩展指令 • (1)CWD/CDQ • CWD能把在AX中的字的符号扩展至DX中(形成32位操作数)。若AX<8000,则0→DX;否则FFFFH→DX。 • CDQ把在EAX中的双字的符号扩展送至EDX中(形成64位操作数)。若EAX<80000000H,则0→EDX;否则,FFFFFFFFH→EDX。
(2)CBW/CWDE • CBW把在寄存器AL中的字节的符号送至AH中(形成16位操作数)。若AL<80H,则扩展后0→AH;若AL>=80H,则扩展以后FFH→AH。 • CWDE把在寄存器AX中的字的符号送至EAX的高16位中(形成32位操作数)。若AX<8000H,则把0→EAX的高16位;否则,把FFFFH送至EAX的高16位。
(3)MOVSX传送并符号扩展。 • 此指令的格式为: • MOVSX DOPD,SOPD • 其中,目标操作数DOPD是寄存器操作数(某一通用寄存器)。源操作数SOPD可以是寄存器或内存操作数,源操作数可以是字节或字。此指令是把一字节源操作数按符号扩展为字或双字传送至目标寄存器中;或把字操作数按符号扩展为双字传送至目标寄存器中。
(4)MOVZX传送且零扩展 • 此指令的格式为: • MOVZX DOPD,SOPD • 其中,目标操作数DOPD是寄存器操作数(某一通用寄存器)。源操作数SOPD可以是寄存器或内存操作数,源操作数可以是字节或字。此指令是把一字节源操作数按零扩展为字或双字传送至目标寄存器中;或把字操作数按零扩展为双字传送至目标寄存器中。
3.4.2 二进制算术指令 • 1.加法指令 • (1)ADD DOPD,SOPD • 这条指令完成两个操作数相加,结果送至目标操作数,即DOPD←DOPD+SOPD • 目的操作数可以是累加器、任一通用寄存器以及存储器。 • (2)ADC(Add with Carry) • 此指令的格式为: • ADC DOPD,SOPD • 这条指令与上一条类似,只是在两个操作数相加时,要把进位标志C的现行值加上去,结果送至一个目标操作数(DOPD)。
2.减法指令 • (1)SUB指令 • 此指令的格式为: • SUB DOPD,SOPD • 这条指令完成两个操作数相减,也即从DOPD中减去SOPD,结果放在DOPD中。具体地说,可以从累加器中减去立即数;或从寄存器或内存操作数中减去立即数;或从寄存器中减去寄存器或内存操作数;或从寄存器或内存操作数中减去寄存器操作数等。 • (2)SBB(Subtract with Borrow)指令此指令的格式为: • SBB DOPD,SOPD • 这条指令与SUB指令类似,只是在两个操作数相减时,还要减去借位标志CF的现行值。
3.乘法指令 • (1)MUL无符号数乘法指令 • 此指令的格式为: • MUL SOPD • 本指令完成在AL(字节)或AX(字)中的操作数以及另一个操作数(两个无符号数)的乘法。双倍长度的乘积,送回到AL和AH(在两个8位数相乘时),或送回到AX和它的扩展部分DX(在两个字操作数相乘时)。 • (2)IMUL符号数乘法指令 • 整数乘法指令。这条指令除了是完成两个带符号数相乘以外,其它与MUL完全类似。
4.除法指令 • (1)DIV • 这条无符号数的除法指令,能把在AX和它的扩展部分(若是字节相除则在AH和AL中,若是字相除则在DX:AX中)中的无符号被除数被源操作数除,且把相除以后的商送至累加器(8位时送至AL,16位时送至AX),余数送至累加器的扩展部分(8位时送至AH,16位时送至DX)。 • (2)IDIV(Integer division) • 这条指令除了完成带符号数相除以外,与DIV完全类似。
5.增量减量指令 • (1)INC增量 • 这条指令完成对指定的操作数加1,然后返回此操作数。 • (2)DEC减量 • 本指令对指定的操作数减1,然后把结果送回操作数。 • 6.NEG取补指令 • 这条指令是对操作数取补,也即用零减去操作数,再把结果送回操作数。 • 7.CMP比较指令 • 比较指令完成两个操作数相减,使结果反映在标志位上,但两操作数不变。
3.4.3 十进制算术指令 • 1.DAA(Decimal Adjust for Addition)在加法后进行十进制调整 • 这条指令能对在AL中的由两个组合的十进制数相加的结果,进行校正,以得到正确的组合的十进制和。 • 2.DAS(Decimal Adjust for Subtraction)在减法后进行十进制调整 • 本指令与DAA指令类似,能对在AL中的由两个组合的十进制数相减以后的结果,进行校正,以得到正确组合的十进制差。
3.AAA(Unpacked BCD[ASCll] Adjust for Addition)在加法后进行ASCII调整 • 这条指令对在AL中的由两个未组合的十进制操作数相加后的结果进行校正,产生一个未组合的十进制和。 • 4.AAS(Unpacked BCD[ASCII] Adjust for Subtraction)在减法后进行ASCII调整 • 本指令与AAA指令类似、能把在AL中的由两个未组合的十进制数相减的结果,进行校正,在AL中产生一个正确的未组合的十进制数差。
5.AAM(Unpacked BCD[ASCII] Adjust for Multiply)在乘法后进行ASCII调整 • 这条指令能把在AX中的两个未组合的十进制数相乘的结果,进行校正,最后在AX中能得到正确的未组合的十进制数的乘积(即高位在AX中,低位在AL中)。 • 6.AAD(Unpacked BCD[ASCII] Adjust for Division)在除法前进行调整 • 这条指令能把在AX中的两个未组合的十进制数在两个数相除以前进行校正,这样在两个未组合的十进制数相除以后,可以得到正确的未组合的十进制结果。
3.4.4 逻辑指令 • 1.AND执行按位逻辑与 • (1)AND指令 • 这条指令对两个操作数进行按位的逻辑“与”运算,即只有相“与”的两位全为1,与的结果才为1;否则与的结果为0。“与”以后的结果送至目的操作数。 • (2)TEST • 本指令完成与AND指令同样的操作,结果反映在标志位上,但并不送回至目标操作数,即TEST指令不改变操作数的值。
2.OR执行按位逻辑或 • 此指令对指定的两个操作数进行逻辑“或”运算。即进行“或”运算的两位中的任一个为1(或两个都为1),则或的结果为1;否则为0。或运算的结果送回目的操作数。 • 3.XOR执行按位逻辑异或 • 这条指令对两个指定的操作数进行“异或”运算,当进行“异或”运算的两位不相同时(即一个为1,另一个为0),“异或”的结果为1;否则为0。异或运算的结果送回一个操作数。 • 4.NOT执行按位逻辑非 • 这条指令对源操作数求反,然后送回原操作数。
3.4.5 移位和循环移位指令 • 1.移位指令 • 有四条移位指令:SAL(算术左移)、SHL(逻辑左移)、SAR(算术右移)和SHR(逻辑右移)。这些指令的格式为: • SAL DOPD,OPD2 • SHL DOPD,OPD2 • SAR DOPD,OPD2 • SHR DOPD,OPD2
第一个操作数是目标操作数,即对它进行移位操作。目标操作数可以是任一通用寄存器或一内存操作数(可用所有寻址方式)。第二个操作数规定移位的次数(或移位的位数)。在8086中,第二个操作数或是1(规定移一位)或为寄存器CL(在寄存器CL中规定移位的次数)。在IA-32处理器中,不仅把目标操作数扩展至32位,而且第二个操作数可以是CL或8位立即数,用于规定移位次数为0至31。第一个操作数是目标操作数,即对它进行移位操作。目标操作数可以是任一通用寄存器或一内存操作数(可用所有寻址方式)。第二个操作数规定移位的次数(或移位的位数)。在8086中,第二个操作数或是1(规定移一位)或为寄存器CL(在寄存器CL中规定移位的次数)。在IA-32处理器中,不仅把目标操作数扩展至32位,而且第二个操作数可以是CL或8位立即数,用于规定移位次数为0至31。
2.双移位指令 • (1)SHLD双左移 • 此指令的格式为: • SHLD DOPD,SOPD,OPD3 • 其中,第一个操作数为目标操作数,它执行左移操作;目标操作数可以为16位或32位通用寄存器或内存操作数(可用所有寻址方式)。第二个操作数为寄存器操作数,其尺寸必须与目标操作数相同。第三个操作数规定移位的次数,可以是8位立即数或寄存器CL,规定移位次数为1至31。 • (2)SHRD双右移 • 除了移位方向相反,此指令与上一指令完全相同。
3.循环移位指令 • 有四条循环移位指令ROL(Rotate Left)、ROR(Porate Right)、RCL(Rorate through CF Left)和RCR(Rotate through CF Right)。 • 指令格式为: • ROL DOPD,OPD2 • 其中,第一个操作数是要对其进行移位操作的目标操作数。第二个操作数是8位立即数或寄存器CL,用以规定移位的次数(1至31)。 • 前两条循环移位指令,未把标志位CF包含在循环的环中。后两条把标志位CF包含在循环的环中,作为整个循环的一部分。
3.4.6 位和字节指令 • 1.位操作指令 • 有四条位操作指令: • BT位测试 • BTS位测试并置位 • BTR位测试并复位 • BTC位测试并置反 • 这些指令的格式为: • BT DOPD,SOPD • 第一个操作数是目标操作数,规定一个位串(称为位基),第二个操作数规定在位串中的偏移(从位0开始算起)。
2.位扫描指令 • 有两条位扫描指令: • BSF向前位扫描 • BSR反向位扫描 • 这些指令的格式为: • BSF DOPD,SOPD • 源操作数SOPD是16位或32位的寄存器或存储操作数,BSF指令的功能是从源操作数的最低有效性(位0)开始向前扫描,查找第一个为1的位。若找到这样的位把它与最低有效位的偏移值存入目标操作数。目标操作数是16位或32位寄存器。若源操作数为0,则目标操作数的内容不定。
3.条件字节设置指令SETcc • 此类指令的格式为: • SETcc DOPD • 此类指令只有一个操作数——目标操作数,它是一个8位寄存器。若满足指令规定的条件,置目标操作数为1;否则,把它置0。
3.4.7 控制传送指令 • 1.无条件转移指令JMP转移 • 这是一条无条件转移指令,它转移程序控制至指令流的不同点而不保留返回信息。目标操作数规定指令要转移到的地址。此操作数可以是立即数、一通用寄存器或一内存单元。 • 指令的格式为: • JMP DOPD
近转移——转移至当前码段(由CS寄存器当前指向的段),有时称为段内转移。 近转移——转移至当前码段(由CS寄存器当前指向的段),有时称为段内转移。 • 短转移——一种near转移,其转移范围限制在当前EIP的–128到+127之内。 • 远转移——转移至与当前码段不同的段内的指令,但在相同特权级,有时称为段间转移。 • 任务切换——转移至不同任务中的指令。