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

jin*_*ong 1 assembly x86-64

我正在阅读Randal E. Bryant 和 David R. O'Hallaron 撰写的《计算机系统:程序员的视角》第三版

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

数字

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

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

  • 分别为pushq %rbp和附加 16 个字节pushq %rbx
  • ,以及 8 个字节subq $8, %rsp

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

fuz*_*fuz 7

24 字节不是 2 的幂,因此不能对齐。真正的对齐是 16 字节,而您忘记了将call8 字节压入堆栈的指令。因此,堆栈指针总共移动了 32 个字节,保持与 16 个字节的对齐。


Giu*_*ini 5

这与 x64 ABI(Microsoft 和 SystemV)一致。在调用函数之前,堆栈必须在 16 字节边界上对齐(在示例中为“call 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