如何在x86中编码相对较短的jmp

use*_*569 16 x86 assembly x86-64

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

EB CBJMP rel8

"跳转,RIP = RIP + 8位位移符号扩展到64位"

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

也许总是偏移量将偏移+ 2,因为此短跳转中的执行时间(参考方向)中的EIP是twobyte指令的基础,但加数始终发生

eb 30 = jmp 0x00000032(+30)

eb e2 = jmp 0xffffffe4(-30)

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

eb fe = jmp 0x00000000

我发现令人惊讶的是,虽然数字是负数,但是过度偏移也会出现分叉.但在英特尔,我发现没有提及(可能因为3000页).

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

近跳跃,其中跳跃范围从当前 EIP值限制为-128到+127 .

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

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

Jos*_*phH 18

不管它是否是短跳,它总是如此destination - (source + sizeof(instruction)).在你的情况下(无条件短跳),dst - end_of_jmp是2.这个加法背后的原因是因为一旦cpu执行了指令获取阶段,指令指针将指向分支后面的指令.

  • @AndersonGreen短跳编码为*jmp rel8*(EB XX),其中相对距离(dest-source)小于0x80.另一个称为跳远,编码为*jmp rel32*(E9 XXXXXXXX).请注意,这可以使用66H前缀进行编码,这会将操作数更改为*rel16*. (2认同)

nrz*_*nrz 16

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

@label:
    jmp @label
    nop
Run Code Online (Sandbox Code Playgroud)

这反汇编为(有了ndisasm,它在16位,32位和64位代码中是相同的):

EBFE jmp short 0x0
90   nop
Run Code Online (Sandbox Code Playgroud)

然后,另一个可执行

    jmp @label
@label:
    nop

EB00 jmp short 0x2
90   nop
Run Code Online (Sandbox Code Playgroud)

因此,rel8始终相对于下一条指令进行编码jmp.然而,反汇编程序(至少ndisasmudcli)表示它与jmp指令本身有关.这可能会引起一些混乱.


Sec*_*att 5

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