Шахматы с ABI в стековом фрейме Windows x64

Итак, я делаю игрушечный компилятор для сборки, и моя программа дает сбой на границе моего сгенерированного кода и кода C. Вот как выглядит сборка:

      (Pseudo-code from my compiler)
def test(x: int) -> int:
    return magic_func(magic_func(x, x), magic_func(x, x))
(Actual output assembly:)
test:
push rcx
mov rdx, rcx
call magic_func
mov rdx, rax
pop rcx
push rdx
mov rdx, rcx
call magic_func
mov rcx, rax
pop rdx
call magic_func
ret

Код C выглядит следующим образом:

      int magic_func(int x, int y) {
    printf("magic_func(%d, %d)\n", x, y);
    return x + y * 2;
}
extern int test(int);
int main() {
    printf("%d\n", test(44));
    return 0;
}

Иmagic_funcфункция конкретно такая: (из objdump)

      push   rbp
mov    rbp,rsp
sub    rsp,0x20
mov    DWORD PTR [rbp+0x10],ecx
mov    DWORD PTR [rbp+0x18],edx
mov    eax,DWORD PTR [rbp+0x18]
mov    r8d,eax
mov    edx,DWORD PTR [rbp+0x10]
lea    rcx,[rip+0x0]        # 1e <magic_func+0x1e>
call   23 <magic_func+0x23>
mov    eax,DWORD PTR [rbp+0x18]
lea    edx,[rax+rax*1]
mov    eax,DWORD PTR [rbp+0x10]
add    eax,edx
add    rsp,0x20
pop    rbp
ret

Теперь с помощью GDB я обнаружил, что ошибка сегментации возникает вretинструкция моей функции (test), но всегда при третьем (последнем) вызове. Адрес возврата, который должен был быть сохранен в стеке, перезаписывается с каким-то мусором. Я уверен, что это какие-то махинации со стеком Windows с выравниванием или какими-то красными зонами, или я не выделяю достаточно места, но я не могу в этом разобраться. Кто-нибудь, имеющий опыт работы с соглашениями о вызовах Windows, может дать мне совет?

0 ответов

Другие вопросы по тегам