Compiler explorer 和 GCC 有不同的输出

Compiler explorer and GCC have different outputs

我有一些 C 代码,当提供给 Compiler Explorer 时,它输出:

        mov     BYTE PTR [rbp-4], al
        mov     eax, ecx
        mov     BYTE PTR [rbp-8], al
        mov     eax, edx
        mov     BYTE PTR [rbp-12], al

然而,如果我使用 GCC 或 G++,那么它会给我这个:

        mov     BYTE PTR 16[rbp], al
        mov     eax, edx
        mov     BYTE PTR 24[rbp], al
        mov     eax, ecx
        mov     BYTE PTR 32[rbp], al

我不知道为什么 BYTE PTR 不同。他们的地址完全错误,我不明白为什么他们在 [rdp] 部分之前。

如果您知道如何使用 gcc 或 g++ 重现第一个输出,请帮忙!

gcc.exe (GCC) 8.2.0

看起来 Windows x64 调用约定的 GCC 正在使用其调用者保留的影子 space(return 地址上方 32 个字节)。 Godbolt 的 GCC 安装目标 GNU/Linux,即 x86-64 System V ABI。

通过使用 __attribute__((ms_abi)) 标记您的函数,您可以在 Godbolt 上获得相同的代码。当然,这意味着您的调用者必须在原型中看到该属性,以便它知道保留那个 space,以及哪个寄存器来传递函数参数。

Windows x64 调用约定比 x86-64 System V 差很多;例如,更少的 arg 传递寄存器。它的唯一优点之一是更容易实现可变参数函数(因为影子 space),并具有一些调用保留的 XMM regs。 (可能太多了,但 x86-64 SysV 为零。)所以您更有可能想在 Windows 上使用交叉编译器(目标 GNU/Linux),或者在所有函数上使用 __attribute__((sysv_abi)) . (https://gcc.gnu.org/onlinedocs/gcc/x86-Function-Attributes.html)

调用约定的 XMM 部分通常与内核代码无关;大多数内核通过不让编译器使用 SIMD/FP 指令来避免 saving/restoring 内核 entry/exit 上的 SIMD/FPU 状态。