C++ 为什么x64上的函数epilog没有“leave”指令?

C++ 为什么x64上的函数epilog没有“leave”指令?,c++,c,assembly,x86-64,red-zone,C++,C,Assembly,X86 64,Red Zone,我正在了解堆栈在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

我正在了解堆栈在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
现在使用x64

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时-我错过了leave指令或精确的以下顺序:
mov-rsp,rbp
then
pop-rbp
。怎么了

更新

似乎
leave
丢失了,只是因为它以前没有被更改。但是,还有一个问题——为什么框架中没有本地变量的分配



对于这个问题给出了非常简单的答案——因为“红色区域”。这基本上意味着不调用其他函数(leaf)的函数可以在不分配空间的情况下使用堆栈下面的前128个字节。因此,如果我在一个
add()
到任何其他哑函数的内部插入一个调用-
子rsp,X
add rsp,X
将分别添加到序言和尾声中。

Esp未被更改,因此无需执行任何操作。为什么要恢复一些不受影响的东西是的,我现在明白了,就在你提到之前。我已经更新了帖子。现在,还有另一个问题..看.如果调用add()中的函数会发生什么?e、 g使用
intf(){return 5;}
将其更改为
a+b+c+f()
。我很好奇在调用
f
之前,
rsp
会发生什么。应该调整它,否则局部变量将被覆盖。@AndreasH。它添加了
推送rbx;将rsp 16分到序言中,并将rsp 16添加到序言中;弹出rbx
至尾声