【发布时间】:2011-02-18 08:44:03
【问题描述】:
在为 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 个字节)空间。操作数尚不为人所知,因为它是到一个未知位置的跳转。所以我实现了一个“重写”机制,如果跳转的位置已知,它会在内存中的正确位置重写操作数,并用NOPs 填充其余部分。这在紧密循环中是一个有点严重的问题。
现在我的问题是以下情况:
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 处指令的大小,然后才能计算d 处操作数的a 和b 之间的相对距离。 JMPc 也是如此:在计算e 和a 之间的相对距离之前,它需要知道d 的大小。
现有的汇编程序如何解决这个问题,或者您将如何解决?
这就是我想解决问题的方法:
首先将所有指令编码为
JMP与其目标之间的操作码,如果此区域包含可变大小的操作码,则使用最大大小,例如5为JMP。然后通过选择可能的最小编码大小(3、4 或 5)并计算距离,将相对JMP编码到它的目标。如果对任何可变大小的操作码进行编码,则更改之前的所有绝对操作数,以及跳过此编码指令的所有相对指令:当它们的操作数更改以选择可能的最小大小时,它们将被重新编码。此方法保证会结束,因为可变大小的操作码只能缩小(因为它使用它们的最大大小)。
我想知道,也许这是一个过度设计的解决方案,这就是我问这个问题的原因。
【问题讨论】:
-
+1 获取漂亮的 asm 文档链接
标签: encoding x86 instruction-set