18

假设我想使用以下操作码进行短跳转:

EB CBJMP rel8

“跳短点,RIP = RIP + 8 位位移符号扩展为 64 位”

(其中 CB 是一个字节符号值,表示与EIP寄存器中的方向相关的相对偏移量)

也许偏移量总是偏移量+2,因为在这个短跳转中执行时间(参考方向)的 EIP 是双字节指令的基数,但加数总是发生

eb 30 = jmp 0x00000032 (+30)

eb e2 = jmp 0xffffffe4 (-30)

那么 EIP 可以故意是相同的方向,因为 fe + 2 是00EIP

eb fe = jmp 0x00000000

我发现令人惊讶的是,尽管这个数字是负数,但过度偏移却出现了分叉。但在英特尔我发现没有提及(可能是因为 3000 页)。

英特尔® 64 和 IA-32 架构软件开发人员手册:卷。2A 3-423

跳跃范围限制为当前EIP 值的 –128 到 +127 的近跳跃。

然后我考虑了三种可能性:

  1. 是 +2,因为是EIP 在执行时间中的后/未来值
  2. 编码值不是 2s 分量编码的有符号数。
  3. 这出现在手册中,但我没有看到,因为我很愚蠢
4

3 回答 3

19

不管是不是短跳,都是destination - (source + sizeof(instruction))

IEdst - end_of_jmp

在你的情况下(短跳),sizeof(instruction)是 2。

这个添加背后的原因是因为一旦 cpu 执行了取指阶段,指令指针就已经指向分支之后的指令。rel8 或 rel32 分支位移与该 EIP/RIP 值相关。

于 2013-02-15T07:13:23.837 回答
18

rel8下一条指令的内存地址相关,可以通过创建两个可执行文件并反汇编它们来轻松确认:

@label:
    jmp @label
    nop

这反汇编为(使用 ndisasm,在 16 位、32 位和 64 位代码中相同):

EBFE jmp short 0x0
90   nop

然后,另一个可执行文件:

    jmp @label
@label:
    nop

EB00 jmp short 0x2
90   nop

因此,rel8总是相对于 之后的下一条指令进行编码jmp。然而,反汇编程序(至少ndisasmand )显示它相对于指令本身。这可能会引起一些混乱。udclijmp

于 2013-02-15T10:55:57.293 回答
6

jump short 采用相对于跳转指令末尾的 EIP (长度为两个字节),并采用一个字节的操作数,该操作数经过符号扩展并添加到 EIP。

于 2013-02-15T07:15:27.800 回答