我正在学习汇编和“位置无关代码”主题的测试,我发现相对跳转和绝对跳转混淆之间的区别。 我怎么知道它是什么样的跳跃?如何判断跳转是绝对还是相对?
我明白什么是相对跳转(从当前行的偏移量)。 但绝对跳跃是什么样子?它何时发生?
我正在学习汇编和“位置无关代码”主题的测试,我发现相对跳转和绝对跳转混淆之间的区别。 我怎么知道它是什么样的跳跃?如何判断跳转是绝对还是相对?
我明白什么是相对跳转(从当前行的偏移量)。 但绝对跳跃是什么样子?它何时发生?
任何看起来像只是普通jmp label
是相对的。
绝对跳跃的样子
jmp register
jmp [address]
jmp segment:absoluteaddr
jmp far [address]
任何远跳是绝对的,任何间接跳转是绝对的,组合(远,间接)也是绝对的。只有在必要时才会发生远跳(您必须更改cs
而不是call
)。间接跳转用于函数指针,分支表(在某些情况下用于switch
语句),动态调度(虚拟方法)以及可能用于导入的函数(通常您称它们,但可能是尾部调用)。
从我记得,当代码是位置无关(代码不希望被加载到特定的内存范围,例如动态加载的DLL库)时使用的相对跳转。因此,此代码中的所有分支都不能假定他们知道跳转的确切地址,但分支IP与目标IP之间的相对偏移)。
绝对跳转得到目标的确切地址,当代码具有静态地址空间时使用它。
希望它能帮助,
根据体系结构以及汇编程序或助记符,相对跳转可能与绝对跳转无法区分。
对于每个分支类型,某些体系结构具有不同的助记符(由某些机器代码编码的指令名称),其他体系具有相同的助记符。
通常,汇编程序会根据目标指令的距离来编写正确的跳转指令。
相对寻址是首选,因为:
operation_field + 32bit_operand
!关于人的因素,我们通常是在国家“这种或那种方式,它并不关心”编程,所以当我们让汇编选择。有时候当我们编写低级例程时,我们可能需要将它们移动到内存中并强制使用相对跳转。有时我们想跳到一个固定的位置(例如0000h或0ffff0h的复位向量),无论代码在内存中何处结束。
跳跃
beq
, bne
, bgtz
, bgez
, bltz
, blez
都是相对的跳跃
j
,jal
是一种混合,他们是绝对的,但PC的高啃保持。
jr
, jalr
是绝对的(是间接的,即使用一个寄存器的值)。请参阅here。
b
,bl
,blx
是相对的。
bx
,blx
是绝对的。
如果您直接修改PC,则是绝对跳转。
请注意采取立体定向的指令是如何相对的,而间接指令则不然。这在RISC中很常见。
欲了解更多信息,请参阅here。
IA32Ejmp
这是相对或绝对取决于所使用的机器代码。更具体地说,跳跃可以接近或远离。没有接近绝对的直接跳跃。绝对靠近跳转总是间接的(它们使用内存操作数或寄存器)。
远跳总是绝对的,可以是直接的(地址在指令操作数中)或间接的。
jmp label
是一个近跳相对。
jmp [dest]
,jmp eax
接近绝对(间接)跳跃。
jmp 0ffff0:0000h
是绝对的直接。 jump FAR [dest]
是绝对间接的。
欲了解更多信息,你可以看到here。
尝试混淆OP甚至更多?有了像__8086__这样的标签,用户_lolu_将不会从您的高质量答案中学到很多东西。 – Fifoernik
@Fifoernik OP可能不是。未来的谷歌可能会。 – 2015-07-22 11:38:59
对于像x86这样的体系结构而言,取决于工具链,知道的唯一方法是反汇编最终的二进制文件,链接器可以根据需要更改跳转,即使对于arm和其他链接器也可以修改那里的代码或添加额外的代码使蹦床具有从编译器生成到需要的任何转换的整体效果。依赖于架构和工具链的旧连接器只会给出一个错误,但仍有一些错误,但例如gnu已经开始添加更多的代码 –