程序栈的增长方向究竟是什么?

我正在阅读理查德·布鲁姆(Richard Blum)的专业汇编语言Professional Assembly Language) ,我对本书的不一致感到困惑,我想知道程序堆栈的增长方向到底是什么? 这是从第312页的图片,这是build议程序堆栈成长。

在这里输入图像说明

但是,当我到达第322页时,我看到另一个版本,这表明程序堆栈增长缓慢。 在这里输入图像说明

和这个

在这里输入图像说明

这本书不矛盾; 每幅图画在顶部显示更高的地址。

第一张图说明了一个向下生长的堆栈。 调用者将参数推入堆栈,然后调用新函数。 调用行为将返回地址压入堆栈。 然后被调用者将基指针的当前值压入堆栈,将堆栈指针复制到基指针中,并减少堆栈指针以为被调用者的局部变量腾出空间。

堆栈增长的方向随着操作系统,CPU架构以及其他许多事情而变化。

最常见的布局是堆栈从内存顶部开始,向下堆积,而堆堆从底部开始堆积。 有时候是相反的,例如。 OSX之前的MacOS把堆栈放在代码区域的上方,长大了,而堆栈则从内存的顶端开始,逐渐减小。

一些背景:

对于不同的处理器,堆栈指针的含义和堆栈的方向可能不同。 对于TMS,Piccolo控制器堆栈正在成长,所以“PUSH”会增加堆栈指针。 堆栈指针可能指向上一次推送的值,或者指向要写入下一个值的位置。 ARM处理器允许所有4种可能的堆栈组合,所以必须有关于如何使用堆栈指针的约定。

在x86处理器上:

在x86处理器堆栈总是向下增长,所以“PUSH”指令会减少堆栈指针; 堆栈指针总是指向最后一个推送的值。

第一张图显示堆栈指针(地址>堆栈指针)之后的地址已包含值。 如果将更多的值存储到堆栈中,则将其存储到堆栈指针下方的位置(下一个值将存储为地址-16(%ebp))。 这意味着页面312中的图片也显示了一个递减的堆栈。

– 编辑 –

如果处理器具有“PUSH”指令,堆栈增长的方向由CPU给出。 对于没有“PUSH”指令的CPU(如PowerPC或没有ARM-THUMB代码的ARM),操作系统必须定义堆栈增长的方向。

更为引人注目的堆栈增长方向的定义是(如果处理器有)中断堆栈。 有些体系结构(如PowerPC)根本没有硬件堆栈。 然后系统设计人员可以决定实现堆栈的方式:预增,后增。 预先递减或后递减。

在PPC中,调用使用链接寄存器,而下一次调用将覆盖它,如果返回地址没有以编程方式保存。

PPC中断使用2个特殊寄存器 – “返回地址”和机器状态。 这是因为指令可以在中断之后“重新启动” – 一种处理流水线架构中的中断的方法。

预增量:堆栈指针在存储之前递增,堆栈指针指向上次使用的项目。 见过更奇怪的8位体系结构(一些第四处理器等)。

后递增:在堆栈指针递增之前完成存储 – 堆栈指针指向第一个空闲堆栈元素。

递减前后:与上面类似,但是堆栈向下增长(更常见)。

最常见的是后递减。