10

例如,给定一个十六进制: 83 E4 F0

通过查看英特尔开发人员手册,我可以弄清楚这83意味着. 看着,我可以解码源/目标寄存器是 SP 或 ESP。andFO-16E4

因此,我可以得出结论,十六进制表示要么and $-16, %ESP要么and $-16, %SP。但是,在手册中,这两者都被列为83 /4 ib.

我怎样才能区分这两者?

4

2 回答 2

10

正如哈罗德所说,默认操作数大小未在指令中编码,但取决于当前处理器模式。

在实模式和 16 位保护模式下,默认操作数大小为 16 位,因此83 E4 F0解码为and $-16, %sp.

在 32 位模式下,操作数大小默认为 32 位,所以它是and $-16, %esp.

在 x64 模式下,大多数指令再次默认为 32 位操作数大小(分支和间接使用堆栈的指令除外,例如推送、弹出、调用和返回),因此它再次解码为and $-16, %esp.

可以使用前缀覆盖默认操作数大小。例如,前缀 66h 在 32 位和 16 位操作数大小之间切换,因此66 83 E4 F0解码为and $-16, %esp16 位模式和and $-16, %sp32 位或 64 位模式。要获得 64 位操作数大小,您需要使用设置了 W 位的REX 前缀,因此48 83 E4 F0解码为and $-16, %rsp(但仅限于 64 位模式!)。

于 2013-02-20T13:27:19.057 回答
0

在保护模式下,只能是 32 位版本,16 位和 64 位版本都需要前缀大小覆盖字节,在这种情况下,16 位版本需要 0x66 前缀覆盖,所以你得到66:83 E4 F0. 英特尔在 AND 的描述中明确说明了这一点:

在 64 位模式下,指令的默认操作大小为 32 位。

以及 066H 的参考,第 2.2.1 章:

操作数大小覆盖前缀允许程序在 16 位和 32 位操作数大小之间切换。任何一种尺寸都可以是默认值;使用前缀选择非默认大小。

于 2013-02-19T16:54:55.013 回答