Изменение соглашения о вызовах в gcc / g ++ abi - PullRequest
0 голосов
/ 01 ноября 2019

Как я мог заставить gcc / g ++ не использовать регистры, а использовать только стек в x86_64 для передачи аргументов функциям, как это было в 32-битной версии (и, возможно, воспринимать результат функции таким образом). Я знаю, что это нарушает официальный ABI, и сторона вызова и вызываемая сторона должны быть скомпилированы таким образом, чтобы это работало. Мне все равно, если используются push / pop или mov / sub. Я ожидаю, что должен быть флаг компилятору, который мог бы обеспечить его выполнение, но я не смог его найти.

1 Ответ

1 голос
/ 01 ноября 2019

Кажется, вы не можете без взлома исходного кода 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 вернуться к аргументам стека. Но нет.)

...