调用函数时栈指针递减为局部变量分配空间

问题描述

我在某处读到堆栈指针会在调用函数时递减以为局部变量分配空间。

我不明白这是怎么回事,因为据我说它应该增加。有人能解释一下吗?

解决方法

首先,它是增加还是减少并不重要——区别只是CPU在push/pop操作时增加或减少SP。这并不影响栈的本质是什么:我们从它读取的数据与我们放入它的顺序完全相反。

这是历史原因:在没有基于分页的虚拟内存支持的机器上,我们有一个固定的地址空间。应该以某种方式放置代码、堆和堆栈 - 不会相互覆盖。

程序的代码部分通常不会改变(除了 ASM 级别的自覆盖代码 - 这在今天几乎是超现实的,但即使在很久以前也很少见)。堆(数据)段的大小有时会增长,有时会缩小,也会出现碎片。堆栈只会增长或缩小,但不会碎片化。

这导致进程地址空间的典型内存布局是这样的:

  1. 代码(开头)
  2. 堆(紧跟在代码之后,但注意:它的大小是变化的,不能与栈重叠!)
  3. 堆栈(因为我们不知道堆将如何增长,所以需要尽可能将其放置在远离数据的地方)。

这导致堆栈必须位于地址空间的末尾,但为了使其增长成为可能,必须在数据插入时减少。

另一种内存布局也是可能的,有些 CPU 的堆栈随着数据插入而增长。

后来,随着基于分页的内存虚拟化的出现,这个问题就可以大致解决了(虽然如果虚拟地址空间的大小不够大,减少堆栈仍然更好)。但是没有必要为了零到一点的改进而破坏兼容性。