如何使用相对跳跃?

时间:2012-06-22 17:14:49

标签: assembly x86 nasm ia-32

关于相对跳跃,我有以下问题:

  1. 我知道JMP SHORT <displacement>将相对于当前PC跳转到<displacement>个字节。这是对的吗?
  2. 汇编程序是否会自动生成相对跳转的操作码?即,当我只写JMP <label>时,如果该标签位于当前PC的128个字节之内,它将产生相对跳跃?
  3. 如果我想使用JMP SHORT <displacement>,计算位移的正确方法是什么?通过检查列表文件并计算偏移量?

2 个答案:

答案 0 :(得分:5)

每个汇编程序(程序)和汇编程序的每个版本都可以选择默认为long或short。因此,我不会寻找一个全面的声明,所有汇编程序都默认为一件事。如果好奇,试试看看会发生什么。

使用x86和可变长度指令,简单地编码位移是非常棘手的,必须提醒自己永远不要触摸跳转和目标之间的代码。

是的,我首先让汇编程序使用标签对指令进行编码,然后获取指令集参考手册和带地址的反汇编,并弄清楚如何计算位移。如果汇编程序允许您自己设置位移,这可能是汇编程序特定的事情,您需要知道它可能需要该位移的单位。 x86可能是字节,但固定字长指令集可能必须以指令为单位给出位移而不是字节。或字节不是指令,所以我会使用置换然后再次反汇编,看它计算出正确的指令。

答案 1 :(得分:2)

假设汇编程序自动使用短编码或普通编码。乍一看,如果可能的话,总是可以切换到短编码似乎没问题,但实际上可以做到这一点,以便其他分支必须再次更改为长编码。

例如(没有测试或任何东西,只是为了得到这个想法):

  jmp _skip          ; relative offset depends on
               the size of "other code", which may include other jumps
  ; other code
_skip:

所以你不能做一个“前进”传球来确定尺寸 - 当你在跳跃时,你还不知道它是否适合,因为你还没有决定如何处理其他的跳跃。

然后呢? (没有测试或任何东西,只是为了得到这个想法)

  .fill 124
  jmp _somewhere     ; 2 bytes, or 5?
  jmp _quiteFarAway  ; relative offset is either 130 or 127
  .align 256
_quiteFarAway:

不,也不能做向后传递,当决定跳转到_quiteFarAway的编码时你还不知道它是否适合,因为你还没有决定如何处理其他跳跃。

做到第2点很难,有很多不同的方法可以解决这个问题。这样做了一个明确的“短”修饰符,一个明确的“长”修饰符,进行安全猜测并最终得到了在极少数情况下不需要的长版本等。