假设以下x86-32指令:
add ebx,1
(至少)有两种方法可以组装此操作码:
81 c3 01 00 00 00
或
83 c3 01
第一个保留1作为4字节的双字第二个保持1作为字节
是否有将1保持为2字节的指令?如果没有,为什么?
您偶然发现了x86指令集的一个怪癖。英特尔在干83
下包含了一组指令,其第一个操作数为Ev
类型,第二个操作数是立即数字节,被解释为与Ev
操作数大小相同。因此,对于83 c3 01
,01
被解释为32位值;对于66 83 c3 01
,01被解释为16位值(并且目的地是16位ax
寄存器)。在词干6A
下编码的push
助记符在其单个操作数的大小方面以相同的方式表现。
你的问题的更广泛的答案是否定的,没有将16位常数解释为32位常数的编码。
来源:我写了一个反汇编程序。
66 81 C3 01 00(在32位模式下为"add bx,01")可能被认为是一个例子
没有这样的例子不需要重写,因为不需要重写。第一个例子需要四个字节的原因是它可以跨越整个4Gb范围。第二个只使用一个字节,因为它被限制为+/-128(总共256个值)。通过使用覆盖,我们可以将第一个示例限制为64kb,但实际上它不是两个字节中的一个,它仍然是两个字节。
无论目标大小,在编程中使用小整数是非常常见的。好处是减少了指令编码。许多指令支持这一点:IMUL、ADD、ADC、SUB、SBB、AND、CMP等。此外,寻址模式支持字节大小符号扩展偏移,以帮助减少代码大小。
至于为什么不:我认为与字节编码的节省相比,增加的节省是最小的。ENTER指令确实使用16位立即数,但它是无符号的,并且固定为更新寄存器RSP/ESP/SP。