llvm:如何生成避免基于 RIP 的寻址模式的 x64 代码?
llvm: How to generate x64 code avoiding RIP-based addressing mode?
我正在为自定义汇编器和链接器使用 clang 汇编语言输出。我对 x86 模式感觉很舒服,但对 PC 相对寻址的 x64 模式感觉不太舒服。考虑以下玩具示例。
C代码:
void sum()
{
static int a, b;
static int c;
c = a + b;
}
x86 输出片段:
sum:
call .L0$pb
.L0$pb:
pop EAX
.Ltmp0:
add EAX, _GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb)
mov ECX, DWORD PTR [EAX + sum.a@GOTOFF]
add ECX, DWORD PTR [EAX + sum.b@GOTOFF]
mov DWORD PTR [EAX + sum.c@GOTOFF], ECX
ret
x64 输出片段:
sum:
mov EAX, DWORD PTR [RIP + sum.a]
add EAX, DWORD PTR [RIP + sum.b]
mov DWORD PTR [RIP + sum.c], EAX
ret
我的问题是:是否有任何命令行开关允许我在不使用基于 RIP 的寻址模式的情况下生成 x64 代码?如果不是,是否可以修改 LLVM 代码以避免为 x64 模式生成基于 RIP 的寻址模式?如何?
您需要了解 x86-64 代码模型(例如,参见 X86-64 ABI 文档或 http://eli.thegreenplace.net/2012/01/03/understanding-the-x64-code-models)。默认情况下,代码模型很小——所有内容都应在 2Gb 范围内,因此应使用 rip-rel 寻址。如果您不想使用 rip-rel 寻址,那么您需要使用例如大代码模式。将 -mcmodel=large 传递给 clang 就大功告成了。
PS: Intel asmprinter 是listing quality,语法对大多数应用来说表达力不够,所以,总是使用at&t。
我正在为自定义汇编器和链接器使用 clang 汇编语言输出。我对 x86 模式感觉很舒服,但对 PC 相对寻址的 x64 模式感觉不太舒服。考虑以下玩具示例。
C代码:
void sum()
{
static int a, b;
static int c;
c = a + b;
}
x86 输出片段:
sum:
call .L0$pb
.L0$pb:
pop EAX
.Ltmp0:
add EAX, _GLOBAL_OFFSET_TABLE_+(.Ltmp0-.L0$pb)
mov ECX, DWORD PTR [EAX + sum.a@GOTOFF]
add ECX, DWORD PTR [EAX + sum.b@GOTOFF]
mov DWORD PTR [EAX + sum.c@GOTOFF], ECX
ret
x64 输出片段:
sum:
mov EAX, DWORD PTR [RIP + sum.a]
add EAX, DWORD PTR [RIP + sum.b]
mov DWORD PTR [RIP + sum.c], EAX
ret
我的问题是:是否有任何命令行开关允许我在不使用基于 RIP 的寻址模式的情况下生成 x64 代码?如果不是,是否可以修改 LLVM 代码以避免为 x64 模式生成基于 RIP 的寻址模式?如何?
您需要了解 x86-64 代码模型(例如,参见 X86-64 ABI 文档或 http://eli.thegreenplace.net/2012/01/03/understanding-the-x64-code-models)。默认情况下,代码模型很小——所有内容都应在 2Gb 范围内,因此应使用 rip-rel 寻址。如果您不想使用 rip-rel 寻址,那么您需要使用例如大代码模式。将 -mcmodel=large 传递给 clang 就大功告成了。
PS: Intel asmprinter 是listing quality,语法对大多数应用来说表达力不够,所以,总是使用at&t。