1

关于解码 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 字节的“reg”字段"C1"。我们看到它确实是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

4

1 回答 1

5

这在“A.2.6. Escape Opcode Instructions”中有描述,相关部分是:

如果 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, opcode extension (reg) = 0b000, rm = 0b001) 是“FLD single-real”,从表 2-2 可以看出是fld dword [ecx].

顺便说一句,没有“FLD ecx”这样的指令,因为您不能直接从整数寄存器加载到 FPU 堆栈上。

于 2011-11-21T06:46:28.223 回答