【问题标题】:How encode a relative short jmp in x86如何在 x86 中编码相对较短的 jmp
【发布时间】:2023-03-22 04:18:01
【问题描述】:

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

EB CBJMP rel8

"跳短,RIP = RIP + 8位位移符号 扩展至 64 位”

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

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

eb 30 = jmp 0x00000032 (+30)

eb e2 = jmp 0xffffffe4 (-30)

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

eb fe = jmp 0x00000000

我发现 overoffset 出现分叉令人惊讶,尽管该数字是负数。但在英特尔我发现没有提及(可能是因为 3000 页)。

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

接近跳跃,跳跃范围从当前 EIP 值限制为 –128 到 +127

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

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

【问题讨论】:

    标签: assembly x86 x86-64


    【解决方案1】:

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

    dst - end_of_jmp

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

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

    【讨论】:

    • 我对这个术语感到困惑:什么是“短跳”?我无法在网络上的任何地方找到它的定义。
    • @AndersonGreen 短跳转编码为 jmp rel8 (EB XX),其中相对距离(dest-source)小于 0x80。另一种叫做跳远,编码为jmp rel32(E9 XXXXXXXX)。请注意,这可以使用 66H 前缀进行编码,这会将操作数更改为 rel16
    • 我必须调整这个公式才能起作用。我用destination - source - sizeof(instruction)
    • @byxor:好点,已修复。实际上最容易记住它为dst - end_of_jmp
    【解决方案2】:

    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 之后的下一条指令进行编码。然而,反汇编程序(至少ndisasmudcli)显示它相对于jmp 指令本身。这可能会引起一些混乱。

    【讨论】:

      【解决方案3】:

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

      【讨论】:

        猜你喜欢
        • 2019-07-10
        • 2011-02-18
        • 2016-08-17
        • 2019-01-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-06-22
        相关资源
        最近更新 更多