从汇编层看64位程序运行——程序中的栈(Stack)结构及其产生的历史原因

如果要讲程序在系统层的运行,一个绕不开的名词就是“栈”。所以深入理解“栈”是这个系列重要的基础。本文也将深入浅出,只讲明白程序运行中使用的栈是什么。

传统栈

有计算机基础的同学都知道栈的特点:先进后出的有序结构。比如我们按顺序将1,2,3压入(push)栈,只能按3,2,1的顺序将数据从栈中弹出(pop)。
在这里插入图片描述

程序栈

但是对于运行在系统上的程序,操作系统并不会如上图物理性的搬运栈上元素,而是一开始就统一分配了一定大小的连续空间作为栈。
在我的开发环境Ubuntu22TLS上,默认的程序所拥有的栈大小是8192kbytes,即8MB。
我们可以通过下面的这个命令来查看

ulimit -a | grep stack

stack size (kbytes, -s) 8192

在这里插入图片描述
那这个连续的内存如何做到栈的特点,即有入栈和出栈的行为呢?
当一个问题不能解决的时候,我们就可以通过引入一个中间层来解决。
很容易想到,我们可以通过一个指向该连续空间中某个位置的指针来实现出入栈。
在这里插入图片描述

X86体系栈

以上只是理论性的讲解,而现实中,我们对栈的理解要“换个角度”。
怎么换“角度”?要反过来看。
在X86体系架构中,栈是反着的。如下图,栈的底部位于“上方”,栈的顶部位于“下方”。
在这里插入图片描述
那评判“上方”或者“下方”的标准是什么?是地址大小。
在这里插入图片描述
所以需要记住以下几点:

  • 在X86体系下,栈是“反向”的。
  • 栈的底部(上)地址值大,栈的顶部(下)地址值小。
  • 栈在增长(Push),则其栈顶地址在减小。栈在回退(Pop),则其栈顶地址在增大。

反向的原因

如果不去看计算机发展的历史,很难想象为什么早期的计算机科学家会做出如此反常的设计。现在我们假想自己回到计算机早期设计阶段,会面对什么样的问题,以及如何解决。
我们知道,和“栈”对应的结构是“堆”。我们平时经常将“堆栈”放在一起来描述计算机一些原理。
堆栈就是用于动态保存程序运行时数据的结构。如果我们要在内存中给它们分配空间,肯定需要考虑一个问题:

  • 如何尽量大的利用内存?

一种比较简单的想法就是:堆和栈用一块内存空间,即它们相连,但是又要有一个明显的间隔。这个间隔区分了堆和栈,以防止数据污染。
上述我们讲过,栈的大小是固定的(默认8MB)。这个大小就帮助“间隔”的产生。
于是存在下面两种可能:

  • 栈在顶部,堆在底部。
  • 栈在底部,堆在顶部。
    在这里插入图片描述
    这两个设计没有本质性的区别。但是最终早期的计算机科学家选择了栈在顶部、堆在底部的设计。
    这样的设计,就意味着:
  • 栈的底部是高地址空间,栈的增长方向是向下(向低地址空间发展)。
  • 堆的底部是低地址空间,堆的增长方向是向上(向高地址空间发展)。

如下图,是我们未来要讲解的一个例子。rbp是栈帧的栈底指针寄存器,rsp是栈帧的栈顶指针寄存器。可以看到rbp比rsp的值要大,即栈底的地址大于栈顶的地址。
在这里插入图片描述

参考资料

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-07-12 05:26:04       67 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-07-12 05:26:04       71 阅读
  3. 在Django里面运行非项目文件

    2024-07-12 05:26:04       58 阅读
  4. Python语言-面向对象

    2024-07-12 05:26:04       69 阅读

热门阅读

  1. 【算法】反转链表

    2024-07-12 05:26:04       27 阅读
  2. NoSQL之REDIS配置与优化

    2024-07-12 05:26:04       20 阅读
  3. 阿里云API安全2.0全新发布

    2024-07-12 05:26:04       24 阅读
  4. (三)大模型/人工智能/机器学习/深度学习/NLP

    2024-07-12 05:26:04       19 阅读
  5. 数据库常见问题(持续更新)

    2024-07-12 05:26:04       25 阅读
  6. DevSecOps在数字政府建设中的实践研究

    2024-07-12 05:26:04       25 阅读
  7. Flask 不同版本项目的终端命令运行方式

    2024-07-12 05:26:04       22 阅读
  8. 使用GPT-4和ChatGPT构建应用项目

    2024-07-12 05:26:04       22 阅读
  9. 65、Flink 的 DataStream Connectors 概述

    2024-07-12 05:26:04       24 阅读
  10. stm32使用pwm和编码器模式(包含重映射)

    2024-07-12 05:26:04       25 阅读