解码特定x87 FPU指令时的模糊性

时间:2011-11-21 06:03:13

标签: opcode fpu x87

我在解码x87 FPU指令方面遇到了一个模棱两可的案例。请参阅第2A卷英特尔指令集手册[1]第3-380页的以下说明。

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 Murali

1 个答案:

答案 0 :(得分:4)

这在“A.2.6。逃避操作码指令”中有描述,相关部分为:

  

如果ModR / M字节在   00H到BFH的范围,ModR / M字节的第5位,第4位和第3位用作操作码扩展,类似于用于1和2字节操作码的技术(参见第A.2.5节,“操作码   单字节和双字节操作码的扩展“)。如果ModR / M字节超出00H的范围   通过BFH,整个ModR / M字节用作操作码扩展。

关于问题:

  

现在,假设我得到操作码序列“D9 C1”。如果我需要检查它是否是“FLD m32fp”指令,那么我必须检查ModR / M字节的'reg'字段是否为0x00。如果是这样,那么确实使用了“FLD m32fp”指令。

当您遇到x87指令时,您必须检查mod / rm字节是否为> = 0xC0(对应于0b11或3的mod字段),在这种情况下,请在表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]

另外,没有“FLD ecx”这样的指令,因为你不能直接从整数寄存器加载到FPU堆栈上。