Почему в x64 функции epilog нет инструкции `отпуска`?

Я собираюсь понять, как работает стек на компьютерах с архитектурой x86 и x64. Однако я заметил, что когда я вручную пишу код и разбираю его, он отличается от того, что я вижу в коде, который предоставляют люди (например, в своих вопросах и руководствах). Вот маленький пример:

Источник

int add(int a, int b) {
    int c = 16;
    return a + b + c;
}

int main () {
    add(3,4);
   return 0;
}

x86

add(int, int):
        push    ebp
        mov     ebp, esp
        sub     esp, 16
        mov     DWORD PTR [ebp-4], 16
        mov     edx, DWORD PTR [ebp+8]
        mov     eax, DWORD PTR [ebp+12]
        add     edx, eax
        mov     eax, DWORD PTR [ebp-4]
        add     eax, edx
        leave (!)
        ret

main:
        push    ebp
        mov     ebp, esp
        push    4
        push    3
        call    add(int, int)
        add     esp, 8
        mov     eax, 0
        leave (!)
        ret

Сейчас идет х64

add(int, int):
        push    rbp
        mov     rbp, rsp
        (?) where is `sub rsp, X`?
        mov     DWORD PTR [rbp-20], edi
        mov     DWORD PTR [rbp-24], esi
        mov     DWORD PTR [rbp-4], 16
        mov     edx, DWORD PTR [rbp-20]
        mov     eax, DWORD PTR [rbp-24]
        add     edx, eax
        mov     eax, DWORD PTR [rbp-4]
        add     eax, edx
        (?) where is `mov rsp, rbp` before popping rbp?
        pop     rbp
        ret

main:
        push    rbp
        mov     rbp, rsp
        mov     esi, 4
        mov     edi, 3
        call    add(int, int)
        mov     eax, 0
        (?) where is `mov rsp, rbp` before popping rbp?
        pop     rbp
        ret

Как вы можете видеть, моя главная путаница в том, что когда я компилирую с x86 - я вижу то, что ожидаю. Когда это x64 - я пропускаю инструкцию или точную следующую последовательность: mov rsp, rbp затем pop rbp, Что за работа?

ОБНОВИТЬ

Это похоже на leave отсутствует только потому, что он не был изменен ранее. Но тогда возникает другой вопрос - почему в кадре нет выделения для локальных переменных?


На этот вопрос @melpomene дает довольно прямой ответ - из-за "красной зоны". Что в основном означает, что функция, которая не вызывает дальнейшие функции (лист), может использовать первые 128 байтов под стеком без выделения места. Так что, если я вставлю звонок внутри add() к любой другой тупой функции - sub rsp, X а также add rsp, X будут добавлены к прологу и эпилогу соответственно.

0 ответов

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