在为 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 指令网站,http: //siyobik.info/index.php?module=x86&id=147 )
都是相对跳转,其中每个编码(操作+操作数)的大小在第三列。
现在我原来的(因此是错误的)设计为每条指令保留了最大(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
填充)。
在计算操作数 at之间的c
相对距离之前,我必须知道指令的大小。这同样适用于at :它需要知道 的大小才能计算 和 之间的相对距离。a
b
d
JMP
c
d
e
a
现有的汇编程序如何解决这个问题,或者您将如何解决这个问题?
这就是我想解决问题的方法:
首先将所有指令编码为
JMP
和它的目标之间的操作码,如果该区域包含可变大小的操作码,则使用最大大小,5
例如JMP
.JMP
然后通过选择可能的最小编码大小(3、4 或 5)并计算距离,对相对于它的目标进行编码。如果对任何可变大小的操作码进行编码,则更改之前的所有绝对操作数,以及跳过此编码指令的所有相对指令:当它们的操作数更改以选择可能的最小大小时,它们将被重新编码。此方法保证结束,因为可变大小的操作码只能缩小(因为它使用它们的最大大小)。
我想知道,也许这是一个过度设计的解决方案,这就是我问这个问题的原因。