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

时间:2013-02-15 06:54:54

标签: assembly x86 x86-64

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

  

EB CB JMP rel8

     

“跳短,RIP = RIP + 8位位移符号   扩展到64位“

     

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

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

  

eb 30 = jmp 0x00000032(+30)

     

eb e2 = jmp 0xffffffe4(-30)

     

然后EIP可以是有意的相同方向,因为fe + 2 00 EIP

     

eb fe = jmp 0x00000000

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

  

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

     
    

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

  

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

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

3 个答案:

答案 0 :(得分:18)

是否是短跳,它总是destination - (source + sizeof(instruction))

即。 dst - end_of_jmp

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

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

答案 1 :(得分:16)

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指令本身的关系。这可能会引起一些混乱。

答案 2 :(得分:5)

跳转短路相对于跳转指令的 end (两个字节长)采用EIP,并采用一个字节操作数,这是一个符号扩展并添加到EIP。