3

我正在了解堆栈如何在 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 时 - 我错过了离开指令或确切的以下序列:mov rsp, rbp然后pop rbp. 穿什么?

更新

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


对于这个问题@melpomene给出了非常简单的答案 - 因为“红色区域”。这基本上意味着不调用其他函数(叶)的函数可以使用堆栈下方的前 128 个字节而无需分配空间。因此,如果我在 an 内插入add()对任何其他哑函数的调用 -sub rsp, X并将add rsp, X分别添加到序言和结尾。

4

0 回答 0