5

假设以下 x86-32 指令:

add ebx,1

有(至少)两种方法来组装这个操作码:

81 c3 01 00 00 00

或者

83 c3 01

第一个将 1 保留为 4 个字节的 dword,第二个将 1 保留为一个字节

是否有将 1 保留为 2 个字节的指令?如果没有为什么?

4

3 回答 3

12

您偶然发现了 x86 指令集的一个怪癖。Intel 在 stem 下包含一组指令83,其第一个操作数是 type Ev,第二个操作数是一个立即字节,被解释为与操作数相同的大小Ev。因此对于83 c3 0101被解释为 32 位值;对于66 83 c3 01, 01 被解释为 16 位值(目标是 16 位ax寄存器)。push在词干下编码的助记符6A在其单个操作数的大小方面的行为方式相同。

您的问题的更广泛的答案是否定的,没有将 16 位常量解释为 32 位常量的编码。

资料来源:我写了一个反汇编程序。

于 2013-06-29T11:13:55.033 回答
0

在编程中使用小整数是很常见的——不管目标大小。好处是减少了指令编码。许多指令都支持这一点:IMUL、ADD、ADC、SUB、SBB、AND、CMP 等……此外,寻址模式支持字节大小的符号扩展偏移,以帮助减少代码大小。

至于为什么不这样做:与字节编码的节省相比,我认为增加的节省是最小的。ENTER 指令确实使用 16 位立即数,但它是无符号的并且固定用于更新寄存器 RSP/ESP/SP。

于 2013-07-01T02:26:24.357 回答
0

66 81 C3 01 00(在 32 位模式下为“add bx, 01”)可能被认为是它的一个例子。

没有这样的示例不需要覆盖,因为不需要它。第一个示例需要四个字节的原因是它可以跨越整个 4Gb 范围。第二个只使用一个字节,因为它被限制为 +/-128(总共 256 个值)。通过使用覆盖,我们可以将第一个示例限制为 64kb,但实际上它不是两个字节中的一个字节,它仍然是两个字节。

于 2013-06-30T02:39:41.570 回答