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。