如何判断跳跃是绝对的还是相对的?

时间:2015-07-21 15:59:52

标签: assembly architecture nasm x86-16

我正在学习装配测试和“位置无关代码”的主题,我发现相对跳跃和绝对跳跃混淆之间的区别。 我怎么知道它是什么样的跳跃?

我理解相对跳跃是什么(与当前行的偏移)。 但绝对跳跃是什么样的呢?什么时候发生?

3 个答案:

答案 0 :(得分:5)

任何看起来像普通jmp label的东西都是相对的。

绝对跳跃看起来像

  • jmp register
  • jmp [address]
  • jmp segment:absoluteaddr
  • jmp far [address]

任何远距离跳跃都是绝对的,任何间接跳跃都是绝对的,因此组合(远,间接)也是绝对的。远程跳转只在必要时发生(您必须更改cs并且它不是call)。间接跳转用于函数指针,分支表(在某些情况下用于switch语句),动态调度(虚拟方法)以及可能用于导入的函数(通常你称之为,但也许它是尾部调用) )。

答案 1 :(得分:4)

根据架构和汇编程序或助记符,相对跳转可能无法与绝对跳转区分开。
某些体系结构对于每种分支类型具有不同的助记符(由某些机器代码编码的指令的名称),其他具有相同的助记符。

通常,汇编程序会根据目标指令的距离来编写正确的跳转指令 相对寻址是首选,因为:

  • 它允许我们创建位置无关代码,这是有用的,但前提是我们也可以以PIC方式访问数据。一般而言,现代操作系统PIC不是必需的 感染向量和shellcode反而充分利用了PIC代码,以及动态移动的代码段(例如,在IA32上使用固定向量的进程间中断需要例程处于精确的地址)。
  • 大大减少了代码大小。相对跳跃可能只使用8位的操作数!这在具有宽位地址空间的系统中非常有用。
  • 有些机器别无选择,例如在RISC计算机中,指令长度是固定的,ARM中非Thumb为32位(和一些Thumb),你不能用32位代码operation_field + 32bit_operand

关于人为因素,我们通常在编程时处于“这种或那种,它不关心”的状态,所以我们让汇编器选择。有时当我们编写低级例程时,我们可能需要在内存中移动它们并强制使用相对跳转。有时我们想要跳转到固定位置(例如0000h或0ffff0h处的复位向量),无论代码最终在内存中。

一些不完整的跳转示例

MIPS

beqbnebgtzbgezbltzblez都是相对跳跃的

jjal有点混合,它们是绝对的,但保留了PC的高半字节。

jrjalr是绝对的(是间接的,即使用寄存器的值)。

有关详细信息,请参阅here

ARM

bblblx是相对的。

bxblx是绝对的。

如果直接修改PC,则绝对跳转。

请注意,即时间的指令是相对的,而间接的指令则不是。这在RISC中很常见。

有关详细信息,请参阅here

IA32E

jmp这是相对的或绝对的,具体取决于所使用的机器代码。更具体地说,跳跃可以是近或远。没有近乎绝对的直接跳跃。绝对近似跳跃总是间接的(它们使用内存操作数或寄存器) 远程跳转始终是绝对的,可以是直接的(地址在指令操作数中)或间接的。

jmp label是一个近乎跳跃的亲戚 jmp [dest]jmp eax接近绝对(间接)跳跃 jmp 0ffff0:0000h绝对是直接的。 jump FAR [dest]绝对是间接的。

有关详细信息,请参阅here

答案 2 :(得分:0)

从我记得的,当代码是位置独立时使用的相对跳转(代码不期望被加载到特定的内存范围。例如动态加载的dll库)。因此,此代码中的所有分支都不能假设它们知道要跳转的确切地址,而是分支IP和目标IP之间的相对偏移量。)

绝对跳转获取目标的确切地址,并在代码具有静态地址空间时使用。

希望它有所帮助,

相关问题