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