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

lol*_*olu 1 architecture assembly nasm x86-16

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

我理解相对跳跃是什么(从当前线的偏移).但绝对跳跃是什么样的?它什么时候发生?

har*_*old 5

任何看似简单的东西jmp label都是相对的.

绝对跳跃看起来像

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

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


小智 5

根据体系结构以及汇编程序或助记符,相对跳转可能与绝对跳转没有区别。
对于每个分支类型,某些体系结构具有不同的助记符(由某些机器代码编码的指令名称),而其他结构则具有相同的助记符。

通常是汇编程序负责根据目标指令的距离编写右跳转指令。
首选相对寻址,因为:

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

关于人为因素,在编程时我们通常处于“ 一种或另一种方式,无关紧要 ”的状态,因此我们让汇编器选择。有时,当我们编写低级例程时,我们可能需要将其移至内存中并强制使用相对跳转。有时我们想跳到一个固定的位置(例如,在0000h或0ffff0h处有一个复位向量),无论代码最终会出现在内存中的哪个位置。


一些不完整的跳跃例子

MIPS

beqbnebgtzbgezbltzblez都是相对的跳跃

jjal是种混合,它们是绝对的,但PC的高位保留。

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

有关更多信息,请参见此处

bblblx 是相对的。

bxblx是绝对的。

如果直接修改PC,那是绝对的跳跃。

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

有关更多信息,请参见此处

IA32e

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

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

有关更多信息,请参见此处