Intel-x86,对esp寄存器中的字节分配感到困惑

Intel-x86, confused about the allocation of bytes in the esp register

这个问题我有点卡住了。给定以下 C 代码:

#include <stdio.h>
#define BUF_SIZE 13

  int foo(){
    int i;
    int B[BUF_SIZE];
    for(i = 0; i < BUF_SIZE; i++)
      B[i] = 5;
    return i;
  }

  int main(){
    foo();
    return 0;
  }

生成了以下 Intel-x86 程序集:

1.           .file "code.c"
2.           .intel_syntax noprefix
3.           .text
4.           .globl foo
5.           .type foo, @function
6. foo:
7.           push ebp
8.           mov ebp, esp
9.           sub esp, 64
10.             mov DWORD PTR [ebp-4], 0
11.             jmp .L2
12.       .L3:
13.             mov eax, DWORD PTR [ebp-4]
14.             mov DWORD PTR [ebp-56+eax*4], 5
15.             add DWORD PTR [ebp-4], 1
16.       .L2:
17.             cmp DWORD PTR [ebp-4], 12
18.             jle .L3
19.             mov eax, DWORD PTR [ebp-4]
20.             leave
21.             ret
22.             .size foo, .-foo
23.             .globl main
24.             .type main, @function
25.       main:
26.             push ebp
27.             mov ebp, esp
28.             call foo
29.             mov eax, 0
30.             pop ebp
31.             ret
32.             .size main, .-main
33.             .ident "GCC: (Debian 6.3.0-18+deb9u1) 6.3.0 20170516"
34.           .section .note.GNU-stack,"",@progbits

我在尝试确定程序集中第 9 行的含义时遇到了困难。我的理解是,我们从堆栈寄存器中减去,以便在堆栈上为局部变量分配space。那么,我知道数组 B 减去 52 个字节,i 减去另外 4 个字节。但我想知道其他 8 个字节是从哪里来的?那些是 foomain 的 return 值吗?任何帮助将不胜感激。

添加到 esp 的字节数被四舍五入以保持一些堆栈对齐。想象一下,您只会添加 57 或其他内容。您要调用的函数需要在存储 4 字节整数之前首先重新对齐堆栈指针。如果每个人都保持堆栈对齐,每个人都会省去麻烦。