首页 > 解决方案 > 更改 gcc/g++ abi 中的调用约定

问题描述

我怎么能强制 gcc/g++ 不使用寄存器,而只使用 x86_64 中的堆栈来将参数传递给函数,就像它在 32 位版本中一样(并且可能以这种方式获取函数结果)。我知道它破坏了官方 ABI 并且调用方和被调用方都必须以这种方式编译才能正常工作。我不在乎是否使用 push/pop 或 mov/sub 方式。我希望编译器应该有一个可以强制执行它的标志,但我找不到它。

标签: gccassemblyx86-64calling-conventionabi

解决方案


看来你不能不破解 GCC 的源代码。

没有使用低效堆栈参数的标准 x86-64 调用约定。

GCC 只知道如何使用标准调用约定,在本例中为 x86-64 SysV 和 MS Windows fastcall 和 vectorcall。(例如__attribute__((ms_abi))vectorcall)。通常没有人想要这个;MS 的调用约定对于包装器或可变参数函数已经足够友好了。__attribute__即使在为 Linux、MacOS、*BSD 等编译时,您也可以将它用于某些功能(由 控制),如果有帮助的话。很难想象纯堆栈参数的用例。


GCC 允许您将寄存器指定为固定(GCC 从未触及,如-ffixed-rdi)、调用破坏或调用保留。 但是使用带有参数传递寄存器的那些只会创建错误的代码,而不是你想要的。

例如

int foo(int a, int b, int c);

void caller(int x) {
    foo(1,2,3);
    //foo(4,x,6);
}

gcc9.2编译-O3 -fcall-saved-rdi

caller:
        push    rdi
        mov     edx, 3
        mov     esi, 2
        pop     rdi
        jmp     foo

它保存/恢复 RDI,但1在调用foo.

并且它不会将 RDI 排除在 arg 传递序列之外并在以后碰撞其他 args。(我在想你也许可以发明一个调用约定,其中所有传递参数的寄存器都是,fixed或者call-saved,也许让 GCC 回退到堆栈参数。但不是。)


推荐阅读