天天看點

保護模式、實位址模式及V8086模式下的指令格式(上)

保護模式、實位址模式及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位表示).

繼續閱讀