在为 x86 平台构建汇编程序时,我遇到了一些编码问题JMP
操作说明:
OPCODE INSTRUCTION SIZE
EB cb JMP rel8 2
E9 cw JMP rel16 4 (because of 0x66 16-bit prefix)
E9 cd JMP rel32 5
...
(来自我最喜欢的 x86 指令网站,)
All are relative跳转,其中每个编码(操作+操作数)的大小位于第三列。
现在,我原来的(因此是错误的)设计为每条指令保留了最大(5 字节)空间。操作数尚不清楚,因为它跳转到未知位置。因此,我实现了一种“重写”机制,如果跳转的位置已知,则将操作数重写到内存中的正确位置,并用NOP
s。这在紧循环中是一个比较严重的问题。
现在我的问题是以下情况:
b: XXX
c: JMP a
e: XXX
...
XXX
d: JMP b
a: XXX (where XXX is any instruction, depending
on the to-be assembled program)
问题是我想要尽可能小的编码JMP
指令(并且没有NOP
填充)。
我必须知道指令的大小c
在我可以计算之间的相对距离之前a
and b
对于操作数d
。这同样适用于JMP
at c
:它需要知道的大小d
在它可以计算之间的相对距离之前e
and a
.
现有的汇编程序如何解决这个问题,或者您将如何做到这一点?
这就是我的想法,可以解决这个问题:
首先将所有指令编码为操作码JMP
它的目标,如果该区域包含可变大小的操作码,则使用最大大小,例如5
for a JMP
。然后对相对值进行编码JMP
通过选择尽可能小的编码大小(3、4 或 5)并计算距离来到达目标。如果对任何可变大小的操作码进行编码,请更改之前的所有绝对操作数以及跳过此编码指令的所有相对指令:当其操作数更改为选择最小可能大小时,它们将被重新编码。此方法保证结束,因为可变大小的操作码仅可能缩小(因为它使用它们的最大大小)。
我想知道,也许这是一个过度设计的解决方案,这就是我问这个问题的原因。