【发布时间】:2017-05-31 15:09:06
【问题描述】:
我有一个我已经反汇编的 C++ 程序,看起来程序集正在使用指令指针来获取字符串文字。例如:
leaq 0x15468(%rip), %rsi ## literal pool for: "special"
和
leaq 0x15457(%rip), %rsi ## literal pool for: "ordinary"
为什么编译器使用指令指针来获取字符串字面量?这似乎会让任何人类程序员都非常头疼,尽管对编译器来说可能并不那么难。
不过,我的问题是 为什么? 是否存在基于机器或历史原因的原因,还是编译器编写者只是随意决定使用 %rip?
【问题讨论】:
-
它允许您通过使引用相对于指令指针而不是固定的内存地址来创建与位置无关的代码。
-
但这只是 amd64 RIP 相对寻址。 x64 中的大多数指令都使用它。在这种情况下,有效地址是通过将位移添加到下一条指令的 64 位 RIP 中形成的。在您的示例中
0x15468和0x15457这是位移。您的反汇编程序以这种形式向您显示说明。另一个disasm可以以另一种形式显示相同的指令-显示计算出的有效地址而不是位移-但这只是不同形式的可视化。 -
这种形式可以节省 4 个字节 - 如果我们在 x64 长模式下使用绝对地址作为有效地址 - 我们需要 8 个字节(64 位)。但是使用 rip-addressing 我们只使用 4 字节(32 位)有符号偏移量来 rip - 所以我们可以评估
[rip-0x80000000, rip+0x7fffffff]内存范围。这为我们节省了 4 个字节的指令 -
因为您的文字字符串位于您的二进制文件中,并且如果您的二进制文件在内存中小于 2GB - 文字将在
[rip-0x80000000, rip+0x7fffffff]范围内