我正在学习汇编测试,在“位置独立代码”主题中,我发现相对跳跃和绝对跳跃之间的区别令人困惑。我怎么知道它是一种什么样的跳跃?
我明白什么是相对跳跃(从当前行的偏移量)。但是绝对跳跃是什么样的?什么时候发生?
我正在学习汇编测试,在“位置独立代码”主题中,我发现相对跳跃和绝对跳跃之间的区别令人困惑。我怎么知道它是一种什么样的跳跃?
我明白什么是相对跳跃(从当前行的偏移量)。但是绝对跳跃是什么样的?什么时候发生?
任何看起来很简单的东西jmp label
都是相对的。
绝对跳跃看起来像
jmp register
jmp [address]
jmp segment:absoluteaddr
jmp far [address]
任何远跳都是绝对的,任何间接跳跃都是绝对的,因此组合(远,间接)也是绝对的。远跳只在必要时发生(你必须改变cs
,它不是 a call
)。间接跳转用于函数指针、分支表(在某些情况下用于switch
语句)、动态调度(虚拟方法),也可能用于导入函数(通常您调用它们,但也可能是尾调用)。
根据架构和汇编程序或助记符的不同,相对跳转可能无法与绝对跳转区分开来。
一些架构对每种分支类型有不同的助记符(由某些机器代码编码的指令的名称),而另一些则具有相同的助记符。
通常由汇编程序负责根据目标指令的距离编写右跳转指令。
相对寻址是首选,因为:
operation_field + 32bit_operand
用 32 位编码!关于人为因素,我们在编程时通常处于“一种或另一种,它不关心”的状态,所以我们让汇编程序来选择。有时当我们编写低级例程时,我们可能需要将它们移动到内存中并强制使用相对跳转。有时我们想跳转到一个固定的位置(例如在 0000h 或 0ffff0h 处的复位向量),无论代码最终在内存中的什么位置。
一些不完整的跳跃示例
beq
,
bne
,
bgtz
,
bgez
,
bltz
,
blez
都是相对跳跃
j
,jal
有点混合,它们是绝对的,但保留了 PC 的高半字节。
jr
,
jalr
是绝对的(间接的,即使用寄存器的值)。
有关更多信息,请参见此处。
b
, bl
,blx
是相对的。
bx
,blx
是绝对的。
如果直接修改PC,那是绝对的跳跃。
请注意,采用立即数的指令是相对的,而间接指令则不是。这在 RISC 中很常见。
有关更多信息,请参见此处。
jmp
这取决于使用的机器代码是相对的还是绝对的。更具体地说,跳跃可以是近的也可以是远的。没有近乎绝对的直接跳跃。绝对近跳转总是间接的(它们使用内存操作数或寄存器)。
远跳转总是绝对的,可以是直接的(地址在指令操作数中)或间接的。
jmp label
是近跳亲戚。
jmp [dest]
,jmp eax
接近绝对(间接)跳跃。
jmp 0ffff0:0000h
是绝对直接的。
jump FAR [dest]
是绝对间接的。
有关更多信息,您可以在此处查看。
据我回忆,当代码与位置无关时使用相对跳转(代码不希望加载到特定的内存范围。例如动态加载的dll库)。因此,这段代码中的所有分支都不能假设它们知道要跳转的确切地址,而是知道分支 IP 和目标 IP 之间的相对偏移量)。
绝对跳转获取目标的确切地址,当代码具有静态地址空间时使用。
希望能帮助到你,