为什么堆栈帧按 24 字节对齐?

Why stack frame aligned by 24 bytes?

我正在阅读 Randal E. Bryant 和 David R. O'Hallaron 的 Computer Systems: A Programmer's Perspective 第 3 版

在第3章和7.5节中,有图演示了堆栈帧是如何分配的,如下所示:

我不明白为什么需要第 4 行和第 12 行。似乎不需要这些行,因为根本没有使用多余的 8 字节堆栈内存。

如评论所示,恕我直言,似乎不可避免地分配了 24 个字节对齐堆栈帧:

所以,我的问题可以概括为“为什么堆栈帧按 24 字节对齐?

24 字节不是 2 的幂,因此不能对齐。真正的对齐是 16 个字节,你忘了考虑 call 指令也将 8 个字节压入堆栈。因此,堆栈指针总共移动了 32 个字节,保持对齐到 16 个字节。

这与 x64 ABI(Microsoft 和 SystemV)一致。在调用函数之前,堆栈必须在 16 字节边界上对齐(在您的示例中为“调用 Q”)。假设堆栈最初位于 16 字节边界处。当程序到达“P”标签时(由于“call P”指令),RSP 指向下面的 8 个字节,因为“call”将 RSP 减 8 并将 RIP(8 个字节)保存在 *RSP 处。然后,有两个“pushq”(第 2 行和第 3 行),每个都将 RSP 减少 8,因此 RSP 仍然未对齐。这就是为什么编译器必须在第 8 行和第 10 行执行“call Q”之前减去 8 以对齐 RSP。

这篇文章很好地描述了 x86/x64 ABI: https://en.wikipedia.org/wiki/X86_calling_conventions