您的位置:首页 > 其它

保护模式、实地址模式及V8086模式下的指令格式(上)

2010-05-02 18:14 295 查看
保护模式、实地址模式及V8086模式下的指令格式(上)

本文译自《intel指令手册2.1节》,该手册地址为:
http://www.intel.com/products/processor/manuals/index.htm
Intel64和IA32架构的指令编码格式是图2-1格式的子集。指令有这几个部分组成:可选的指令前缀(顺序不限)、主操作码字节(最多3个字节)以及寻址方式说明(addressing-form specifier)字节(如果需要的话)。寻址方式说明由ModR/M字节、SIB字节、位移量(如果需要的话)和立即数(如果需要的话)组成。



图2-1Intel64和IA-32架构指令格式

2.1.1 指令前缀

指令前缀分成四块,每块都有一组前缀代码。对于每个指令来说,四块中每块只能使用一个前缀。这四块的前缀的顺序是不限定的。

•第一块

—锁前缀和重复前缀:

•LOCK锁前缀代码为F0H

•REPNE/REPNZ前缀代码为F2H。该前缀仅用于字符串和输入/输出指令(F2H在某些指令中还被用作强制前缀(mandatory prefix)).

• REP或者REPE/REPZ前缀代码为F3H。该前缀仅用于字符串和输入/输出指令(F3H在某些指令中还被用作强制前缀).

•第二块

—段超越前缀

• 2EH——CS段超越(在分支指令中使用未定义)

• 36H——SS段超越(在分支指令中使用未定义)

• 3EH——DS段超越(在分支指令中使用未定义)

• 26H——ES段超越(在分支指令中使用未定义)

• 64H——FS段超越(在分支指令中使用未定义)

• 65H——GS段超越(在分支指令中使用未定义)

—分支预测(branch hints)前缀

• 2EH——分支被使用(只用于条件转移JCC指令)

• 3EH——分支不被使用(只用于条件转移JCC指令)

• 第三块

•调整操作数大小(operand-size override)前缀代码为66H(在一些指令中66H被用作强制前缀)

• 第四块

•67H——调整地址大小(address-size override)前缀

锁前缀(F0H)在多处理器情况下会迫使一个操作必须互斥地使用共享内存。(详见《“Instruction Set Reference, A-M,”》 第三章“LOCK—Assert LOCK# Signal Prefix”)

重复前缀(F2H,F3H)会使指令对字符串中的每一个元素都重复执行。该前缀只在字符串和I/O指令(MOVS,CMPS, SCAS,LODS,STOS,INS,OUTS)中使用。在其他未定义的操作码前使用重复前缀没有定义,这种使用会导致不可预见的后果。

一些指令会将F2H/F3H作为强制前缀来表示不同的功能(express distinct functionality)。强制前缀通常应置于其他可选前缀后面(例外情况在2.2.1“REX Prefixes”中讨论)。

分支预测前缀(2EH,3EH)允许程序预测一个分支最有可能的路径。此前缀只在条件转移指令(JCC)中使用。在其他未定义的操作码前使用分支预测前缀没有定义,这种使用会导致不可预见的后果。

调整操作数大小前缀(66H)允许程序在16位和32位操作数之间切换操作数。这两种大小都可以作为缺省值,使用本前缀可以切换为非缺省的那个大小值。

一些SSE2/SSE3/SSSE3/SSE4指令和主操作码为3字节的指令可能会将66H作为强制前缀来表示不同的功能。强制前缀通常应置于其他可选前缀后面(例外情况在2.2.1“REX Prefixes”中讨论)。

66H前缀的其他使用保留,如果使用可能会导致不可预见的后果。

调整地址大小前缀(67H)允许程序在16位和32位地址之间切换。这两种大小都可以作为缺省值,使用本前缀可以切换为非缺省的那个大小值。当指令的操作数是内存中不存在时,使用该前缀和/或者未定义的操作码是未定义的,这种使用会导致不可预见的后果。

.

2.1.2 操作码

主操作码可以是1个,2个或3个字节长。有时会有另外的3位操作码存在于ModR/M字节中。主操作码中还可以为定义更小的段(fields),比如操作方向、位移量(displacements)大小、寄存器编码、条件码(condition codes)或者符号扩展(sign extension)。操作码中的段随操作的类型不同而有很大的不同。

通用指令和SIMD指令的2个字节的操作码格式组成如下:

•一个逃逸码(escape opcode)0FH作为主操作码和一个第二操作码字节。或者

•一个强制前缀(66H、F2H或F3H),一个逃逸码字节和一个第二操作码字节。

举例说明,CVTDQ2PD的操作码序列为F3 0F E6。第一个字节就是强制前缀(不是重复前缀)。

通用指令和SIMD指令的3个字节的操作码格式组成如下:

•一个逃逸码0FH作为主操作码,加上两个额外的操作码字节。或者

•一个强制前缀(66H、F2H或F3H),一个逃逸码字节,加上两个额外的操作码字节。

举例说明,XMM寄存器的PHADDW指令的操作码序列为66 0F 38 01。第一个字节就是强制前缀。

所有有效的操作码列于附录A和附录B.

2.1.3 ModR/M和SIB字节

很多引用内存操作数的指令需要一个说明寻址方式的字节(称为ModR/M)紧跟在主操作码后面。ModR/M字节包含下面三个信息段(译注:见图2-1):

•Mod段和r/m段形成32种可能值:8种寄存器和24种寻址方式。

•Reg/Opcode段或者指定一个寄存器或者是主操作码的3位附加信息。Reg/opcode段的具体作用由主操作码决定。

•r/m段可以指定一个寄存器作为操作数,或者和mod段组合起来指定一种编码方式。有时候,这种mod段和r/m段的组合可以被用来表示一些指令的操作码信息。

一些ModR/M字节还需要第二个寻址字节(SIB)。32位的基址变址(base-plus-index)和比例变址(scale-plus-index)寻址方式需要一个SIB字节。SIB字节包含下面段(译注:见图2-1):

•比例段指出比例倍数(scale factor)

•变址段指出变址寄存器的寄存器数字

•基址段指出基址寄存器的寄存器数字

参看2.1.5节ModR/M和SIB字节的编码

2.1.4位移量和立即数字节

一些寻址方式在ModR/M(或者SIB,如果有的话)后面会有一个位移量。如果有位移量的话,它可以是1、2或4字节。如果一个指令指定一个立即数,那么这个立即数会跟在位移量字节后面,立即数可以是1、2和4字节。

2.1.5 ModR/M和SIB字节组成的寻址方式

由ModR/M和SIB字节组成的值和其对应的寻址方式列于表2-1到表2-3:由ModR/M字节指定的16位寻址方式列于表2-1;32位寻址方式列于表2-2;表2-3列出了由SIB字节指定的32位寻址方式。假如ModR/M字节中reg/opcode段表示一个扩展操作码,有效编码见附录B.

在表2-1和表2-2中,有效地址(Effective Address)列中列出了由Mod和R/M组成的可以赋给指令的第一个操作数的32种有效地址。前面24种指出了一个内存的位置;后面的8种(Mod=11B)是指出了通用寄存器、MMX寄存器和XMM寄存器。

表2-1和表2-2中的Mod和R/M列给出了要获得第一列这种有效地址方式的二进制编码。比如,看Mod=11B,R/M=000B那一行,该行标明的通用寄存器为EAX,AX和AL;MMX寄存器为MM0;XMM寄存器为XMM0.具体到底使用哪个寄存器是由操作码字节和操作数大小属性决定。

我们再来看表2-1或2-2任一个表的第7行(标有“REG=”的那行)。该行指出如何使用3位的Reg/Opcode段来获得第二个操作数的位置。第二个操作数必须是通用寄存器、MMX寄存器或者XMM寄存器。第1到5行列出了表中值所对应的寄存器。和上面一样,使用哪种寄存器是由操作码字节和操作数大小属性决定的。

如果指令不需要第二个操作数,Reg/Opcode段可以被用作操作码的扩展。由表的第6行(标有“/DIGIT(OPCODE)”的那行)标出。注意该行值是十进制形式的。

表2-1和表2-2的主体部分(在标有“Value of ModR/M Byte (in Hexadecimal)”的下面)包含一个由32*8数组所表示的256个ModR/M值(16进制)。第3/4/5位由字节所在列指出,第0/1/2位和第6/7位由行指出。下图演示如何计算出表中值的。



图2-2 解释如何得到ModR/M(C8H)字节





表2-3显示的是256中SIB字节的可能值(16进制)。用作基址的通用寄存器列在表的上部,并同时显示了在SIB字节中的对应值。表的主体部分的行是作为变址的寄存器和比例倍数(由SIB字节的第6/7位表示).



参考文献

1. http://linux.chinaunix.net/bbs/thread-1050480-1-1.html。
2. http://blog.ftofficer.com/2010/04/n-forms-of-call-instructions/
3. http://baike.baidu.com/view/889427.htm?fr=ala0_1
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: