2011-11-21 97 views
1

我在解碼x87 FPU指令時遇到了模糊的情況。請參閱第2A卷Intel指令集手冊[1]頁的第3-380頁中的以下說明。解碼特定x87 FPU指令時的歧義

D9 /0 --> FLD m32fp --> Push m32fp onto the FPU register stack. 
D9 C0+i --> FLD ST(i) --> Push ST(i) onto the FPU register stack. 

這兩條指令都有相同的單字節基本操作碼0xD9。第一條指令的擴展操作碼爲0x00。擴展操作碼將在ModR/M字節的'reg'字段中指定。但第二條指令是帶有「添加到獲取寄存器」功能的2字節操作碼。這意味着:

D9 C0 --> FLD ST0 
D9 C1 --> FLD ST1 
(and so on) 

我在區分這兩個指令方面存在一個小問題。一個小例子是:

現在,假設我得到操作碼序列"D9 C1"。如果我需要檢查它是否是指令"FLD m32fp",那麼我必須檢查ModR/M字節的'reg'字段是否爲0x00。如果是這樣,那麼它的確使用了"FLD m32fp"指令。

C1的二進制表示是"1100 0001"。假設bit0是LSB,則bit3-bit5(含)構成ModR/M字節"C1"的'reg'字段。我們看到它確實是0x00(3個零)。

因此我將操作碼序列"D9 C1"映射到"FLD m32fp"指令。進一步解碼,我們看到在這種情況下操作數實際上變成了"ecx"。但是我們看到"FLD ST1"也具有操作碼序列"D9 C1",這是用於該操作碼序列的實際指令。

實際上,我怎麼能確定操作碼序列"D9 C1"對應指令"FLD ST1"而不是"FLD ecx"

"FMUL"指令也會出現類似的問題,因爲操作數與"FLD"的操作方式相同。

[1] http://www.intel.com/design/intarch/manuals/243191.HTM

感謝和問候,
Hrishikesh穆拉利

回答

3

這在所描述的,相關部分的存在 「A.2.6轉義操作碼的說明。」:

如果ModR/M字節在 範圍內,00H到BFH,ModR/M字節的第5,4和3位用作操作碼擴展,類似於用於1字節和2字節操作碼的技術(請參閱到A.2.5節,「作品代碼 單字節和雙字節操作碼的擴展「)。如果ModR/M字節通過BFH超出00H 的範圍,則整個ModR/M字節將用作操作碼擴展。

上的問題:

現在,假設我得到的操作碼序列 「D9 C1」。如果我需要檢查它是否是指令「FLD m32fp」,那麼我必須檢查ModR/M字節的'reg'字段是否爲0x00。如果是這樣,那麼它確實使用了「FLD m32fp」指令。

當您遇到x87指令時,您必須檢查mod/rm字節是否大於等於0xC0(對應於mod域爲0b11或3),在這種情況下請在表A-10中查找(用於D9)。看那裏你會看到D9 C1 = FLD ST(0),ST(1)

當mod/rm字節爲< 0xC0時,要使用的表是A-9。 D9 01(mod = 0b00,操作碼擴展(reg)= 0b000,rm = 0b001)爲「FLD single-real」,查看錶2-2,結果爲fld dword [ecx]

由於不能直接從整數寄存器加載到FPU堆棧,因此不存在「FLD ecx」這樣的指令。

+0

謝謝!這確實幫助我理解它。 :-)那麼這個檢查'> = C0'是否適用於每一條指令?還是隻適用於FPU相關指令? –

+0

這僅適用於x87指令。你基本上首先要檢查'mod = 0b11',在這種情況下,查找64條目大表(modrm&0x3F)中的指令,否則使用reg字段確定指令,rm字段指定操作數。 – user786653

+0

嗯,好的。謝謝! :-) –