我怎么知道跳跃是绝对的还是相对的?
How can I tell if jump is absolute or relative?
我正在学习汇编和 "Position-Independent-Code" 主题的测试,我发现相对跳跃和绝对跳跃之间的区别令人困惑。
我怎么知道它是哪种跳跃?
我明白什么是相对跳转(与当前行的偏移量)。
但是绝对跳跃是什么样的呢?什么时候发生?
据我所知,当代码与位置无关时使用相对跳转(代码不希望加载到特定的内存范围内。例如动态加载的 dll 库)。因此,这段代码中的所有分支不能假定它们知道确切的跳转地址,而是分支IP与目标IP之间的相对偏移量。
绝对跳转获取目标的确切地址,当代码有静态地址时使用space。
希望对您有所帮助,
任何看起来很普通的东西 jmp label
都是相对的。
绝对跳跃看起来像
jmp register
jmp [address]
jmp segment:absoluteaddr
jmp far [address]
任何远跳都是绝对的,任何间接跳都是绝对的,组合(远,间接)因此也是绝对的。远跳仅在必要时发生(您必须更改 cs
而不是 call
)。间接跳转用于函数指针、分支表(在某些情况下用于 switch
语句)、动态分派(虚方法)并且可能用于导入函数(通常你调用它们,但也可能是尾调用)。
根据体系结构和汇编程序或助记符,相对跳转可能无法与绝对跳转区分开来。
某些体系结构对每种分支类型具有不同的助记符(由某些机器代码编码的指令名称),其他体系结构具有相同的助记符。
通常是汇编程序负责根据目标指令的距离编写正确的跳转指令。
首选相对寻址,因为:
- 它允许我们创建与位置无关的代码,这很有用,但前提是我们还可以以 PIC 方式访问数据。一般来说,现代 OS PIC 不是必需品。
相反,感染向量和 shellcode 充分利用了 PIC 代码以及动态移动的代码段(例如,IA32 上具有固定向量的进程间中断需要一个位于精确地址的例程)。
- 它极大地减少了代码大小。相对跳转可能使用一个低至 8 位的操作数!这在具有宽地址 space 位项的系统中非常有用。
- 有些机器别无选择,例如在 RISC 计算机中指令长度是固定的,在 ARM 中非 Thumb(和一些 Thumb)是 32 位的,你不能在 32 位中编码
operation_field + 32bit_operand
!
关于人为因素,我们在编程时通常处于“这样那样,它不关心”的状态,所以我们让汇编程序选择。有时当我们编写低级例程时,我们可能需要在内存中移动它们并强制使用相对跳转。有时我们想跳转到代码可能在内存中结束的固定位置(例如 0000h 或 0ffff0h 处的复位向量)。
一些不完整跳转示例
MIPS
beq
,
bne
,
bgtz
,
bgez
,
bltz
,
blez
都是相对跳跃
j
、jal
有点混合,它们是绝对的,但保留了PC的高半字节。
jr
,
jalr
是绝对的(间接的,即使用寄存器的值)。
有关详细信息,请参阅 here。
手臂
b
、bl
、blx
是相对的。
bx
、blx
是绝对的。
如果直接修改PC那绝对是跳转
注意带立即数的指令是相对的,而间接指令不是。这在 RISC 中很常见。
有关详细信息,请参阅 here。
IA32e
jmp
这是相对的还是绝对的取决于所使用的机器代码。更具体地说,跳跃可以很近也可以很远。没有近乎绝对的直接跳跃。绝对近跳转总是间接的(它们使用内存操作数或寄存器)。
远跳转总是绝对的,可以是直接的(地址在指令操作数中)或间接的。
jmp label
是近跳相对。
jmp [dest]
、jmp eax
接近绝对(间接)跳跃。
jmp 0ffff0:0000h
绝对直接。
jump FAR [dest]
绝对是间接的。
有关更多信息,请参阅 here。
我正在学习汇编和 "Position-Independent-Code" 主题的测试,我发现相对跳跃和绝对跳跃之间的区别令人困惑。 我怎么知道它是哪种跳跃?
我明白什么是相对跳转(与当前行的偏移量)。 但是绝对跳跃是什么样的呢?什么时候发生?
据我所知,当代码与位置无关时使用相对跳转(代码不希望加载到特定的内存范围内。例如动态加载的 dll 库)。因此,这段代码中的所有分支不能假定它们知道确切的跳转地址,而是分支IP与目标IP之间的相对偏移量。
绝对跳转获取目标的确切地址,当代码有静态地址时使用space。
希望对您有所帮助,
任何看起来很普通的东西 jmp label
都是相对的。
绝对跳跃看起来像
jmp register
jmp [address]
jmp segment:absoluteaddr
jmp far [address]
任何远跳都是绝对的,任何间接跳都是绝对的,组合(远,间接)因此也是绝对的。远跳仅在必要时发生(您必须更改 cs
而不是 call
)。间接跳转用于函数指针、分支表(在某些情况下用于 switch
语句)、动态分派(虚方法)并且可能用于导入函数(通常你调用它们,但也可能是尾调用)。
根据体系结构和汇编程序或助记符,相对跳转可能无法与绝对跳转区分开来。
某些体系结构对每种分支类型具有不同的助记符(由某些机器代码编码的指令名称),其他体系结构具有相同的助记符。
通常是汇编程序负责根据目标指令的距离编写正确的跳转指令。
首选相对寻址,因为:
- 它允许我们创建与位置无关的代码,这很有用,但前提是我们还可以以 PIC 方式访问数据。一般来说,现代 OS PIC 不是必需品。
相反,感染向量和 shellcode 充分利用了 PIC 代码以及动态移动的代码段(例如,IA32 上具有固定向量的进程间中断需要一个位于精确地址的例程)。 - 它极大地减少了代码大小。相对跳转可能使用一个低至 8 位的操作数!这在具有宽地址 space 位项的系统中非常有用。
- 有些机器别无选择,例如在 RISC 计算机中指令长度是固定的,在 ARM 中非 Thumb(和一些 Thumb)是 32 位的,你不能在 32 位中编码
operation_field + 32bit_operand
!
关于人为因素,我们在编程时通常处于“这样那样,它不关心”的状态,所以我们让汇编程序选择。有时当我们编写低级例程时,我们可能需要在内存中移动它们并强制使用相对跳转。有时我们想跳转到代码可能在内存中结束的固定位置(例如 0000h 或 0ffff0h 处的复位向量)。
一些不完整跳转示例
MIPS
beq
,
bne
,
bgtz
,
bgez
,
bltz
,
blez
都是相对跳跃
j
、jal
有点混合,它们是绝对的,但保留了PC的高半字节。
jr
,
jalr
是绝对的(间接的,即使用寄存器的值)。
有关详细信息,请参阅 here。
手臂
b
、bl
、blx
是相对的。
bx
、blx
是绝对的。
如果直接修改PC那绝对是跳转
注意带立即数的指令是相对的,而间接指令不是。这在 RISC 中很常见。
有关详细信息,请参阅 here。
IA32e
jmp
这是相对的还是绝对的取决于所使用的机器代码。更具体地说,跳跃可以很近也可以很远。没有近乎绝对的直接跳跃。绝对近跳转总是间接的(它们使用内存操作数或寄存器)。
远跳转总是绝对的,可以是直接的(地址在指令操作数中)或间接的。
jmp label
是近跳相对。
jmp [dest]
、jmp eax
接近绝对(间接)跳跃。
jmp 0ffff0:0000h
绝对直接。
jump FAR [dest]
绝对是间接的。
有关更多信息,请参阅 here。