【CPU】堆栈和堆栈指针(个人草稿)
详细的 CPU 中堆栈指针(Stack Pointer, SP)及相关知识介绍
1. 什么是堆栈?
堆栈(Stack) 是一种后进先出(LIFO, Last In First Out)的数据结构,广泛用于计算机系统中,尤其是在程序执行过程中管理函数调用、局部变量、返回地址等。堆栈通常位于内存的特定区域,称为 堆栈段 或 栈区。
- 特性:
- 后进先出(LIFO):最后入栈的数据最先被弹出。
- 自动管理:大多数编程语言和操作系统会自动管理堆栈的分配和释放,程序员不需要手动操作。
- 快速访问:由于堆栈的操作(如压栈和弹栈)非常简单,因此访问速度较快。
2. 堆栈指针(Stack Pointer, SP)
堆栈指针(SP) 是一个特殊的寄存器,用于指向当前堆栈的顶部(即最后一个被压入堆栈的数据项)。每次有数据被压入或弹出堆栈时,堆栈指针都会相应地更新,以确保它始终指向堆栈的最新位置。
- 作用:
- 指示堆栈顶部:SP 寄存器保存了当前堆栈的顶部地址,使得处理器可以快速访问最新的数据。
- 动态调整:随着程序的执行,函数调用、局部变量的创建和销毁会导致堆栈的大小发生变化,SP 会根据这些变化动态调整。
- 支持函数调用:在函数调用时,返回地址、参数和局部变量会被压入堆栈,而 SP 会相应地移动。当函数返回时,SP 会恢复到调用前的位置。
3. 堆栈的工作原理
堆栈的工作原理可以通过以下步骤来理解:
-
初始化堆栈:
- 在程序启动时,操作系统会为每个进程分配一段内存作为堆栈空间,并将 SP 初始化为该内存区域的顶部(或底部,取决于堆栈的增长方向)。
- 堆栈通常从高地址向低地址增长(称为 向下生长),但有些架构也可能从低地址向高地址增长(称为 向上生长)。RISC-V 默认采用 向下生长 的堆栈。
-
压栈(Push):
- 当需要将数据压入堆栈时,CPU 会执行
push
指令(或等效操作)。首先,SP 会减小(对于向下生长的堆栈),然后将数据写入新的堆栈顶部。 - 例如,在 RISC-V 中,
sp
寄存器会减去 4 字节(32 位系统)或 8 字节(64 位系统),然后将数据存储到该地址。
- 当需要将数据压入堆栈时,CPU 会执行
-
弹栈(Pop):
- 当需要从堆栈中弹出数据时,CPU 会执行
pop
指令(或等效操作)。首先,从当前堆栈顶部读取数据,然后 SP 会增加(对于向下生长的堆栈),从而恢复到之前的状态。 - 例如,在 RISC-V 中,
sp
寄存器会加上 4 字节(32 位系统)或 8 字节(64 位系统),然后从该地址读取数据。
- 当需要从堆栈中弹出数据时,CPU 会执行
-
函数调用与返回:
- 函数调用:当调用一个函数时,返回地址、参数和局部变量会被压入堆栈。SP 会相应地移动,指向新的堆栈顶部。
- 函数返回:当函数执行完毕时,局部变量会被弹出堆栈,返回地址会被恢复,控制流返回到调用者。SP 会恢复到调用前的位置。
4. 堆栈帧(Stack Frame)
堆栈帧 是每次函数调用时在堆栈上创建的一个独立区域,用于存储该函数的局部变量、参数、返回地址等信息。每个函数调用都会创建一个新的堆栈帧,函数返回时会销毁该帧。
- 堆栈帧的组成:
- 返回地址:函数调用时,返回地址会被压入堆栈,以便在函数执行完毕后能够正确返回到调用点。
- 参数:函数的参数也会被压入堆栈,供被调用函数使用。
- 局部变量:函数内部声明的局部变量会被分配在堆栈帧中。
- 旧的基址指针(Base Pointer, BP):某些架构(如 x86)使用基址指针(BP)来引用堆栈帧中的数据。在进入函数时,旧的 BP 会被保存,新的 BP 会被设置为当前堆栈帧的起始位置。
5. 基址指针(Base Pointer, BP)
基址指针(BP) 是另一个重要的寄存器,通常用于引用当前堆栈帧中的数据。与堆栈指针(SP)不同,BP 通常指向堆栈帧的固定位置,使得函数可以方便地访问参数和局部变量。
-
作用:
- 引用堆栈帧中的数据:BP 通常指向堆栈帧的起始位置,使得函数可以使用相对偏移量来访问参数和局部变量。这使得代码更加清晰和易于维护。
- 保存旧的基址指针:在进入函数时,旧的 BP 会被保存到堆栈中,新的 BP 会被设置为当前堆栈帧的起始位置。函数返回时,BP 会恢复到调用前的状态。
-
示例(x86 架构):
push ebp # 保存旧的基址指针 mov ebp, esp # 设置新的基址指针 sub esp, 16 # 为局部变量分配空间
在这段代码中,
ebp
被用来引用当前堆栈帧中的数据,而esp
则继续作为堆栈指针使用。
6. 堆栈溢出(Stack Overflow)
堆栈溢出 是指堆栈的空间被耗尽,导致无法再分配新的堆栈帧或压入更多数据。堆栈溢出通常是由于递归调用过深、局部变量过多或缓冲区溢出引起的。
-
后果:
- 程序崩溃:如果堆栈溢出,程序可能会崩溃,甚至导致系统不稳定。
- 安全漏洞:堆栈溢出可能导致缓冲区溢出攻击,黑客可以通过这种漏洞注入恶意代码并执行。
-
预防措施:
- 限制递归深度:避免过深的递归调用,或者使用迭代代替递归。
- 检查堆栈大小:在编写代码时,确保堆栈的大小足够大,以容纳所有必要的数据。
- 使用栈保护机制:现代操作系统和编译器提供了栈保护机制(如栈金丝雀),可以在检测到堆栈溢出时立即终止程序,防止进一步的损害。
7. 堆栈与堆的区别
虽然堆栈和堆都是用于动态内存管理的,但它们的工作方式和用途不同:
-
堆栈(Stack):
- 自动管理:堆栈由编译器和操作系统自动管理,程序员不需要手动分配或释放内存。
- 快速访问:堆栈的操作非常简单,访问速度较快。
- 有限大小:堆栈的大小是固定的,通常较小,适合存储局部变量、函数调用信息等短期使用的数据。
- 后进先出(LIFO):堆栈遵循 LIFO 规则,最后入栈的数据最先被弹出。
-
堆(Heap):
- 手动管理:堆由程序员手动分配和释放内存,通常使用
malloc
、free
等函数。 - 灵活分配:堆的大小可以根据需要动态扩展,适合存储全局变量、动态分配的对象等长期使用的数据。
- 无序访问:堆没有固定的顺序,数据可以随意分配和释放。
- 较慢访问:由于堆的管理较为复杂,访问速度相对较慢。
- 手动管理:堆由程序员手动分配和释放内存,通常使用
8. RISC-V 中的堆栈指针
在 RISC-V 架构中,堆栈指针通常使用 x2
寄存器(也称为 sp
),专门用于管理堆栈。RISC-V 的堆栈默认是从高地址向低地址生长(即向下生长),这意味着每次压栈时,sp
会减小;每次弹栈时,sp
会增加。
- 典型指令:
- 压栈:
addi sp, sp, -16
(将sp
减少 16 字节,为局部变量分配空间) - 弹栈:
addi sp, sp, 16
(将sp
增加 16 字节,释放局部变量占用的空间) - 保存返回地址:
sw ra, 0(sp)
(将返回地址保存到堆栈顶部) - 恢复返回地址:
lw ra, 0(sp)
(从堆栈顶部恢复返回地址)
- 压栈:
9. 总结
- 堆栈 是一种后进先出(LIFO)的数据结构,广泛用于管理函数调用、局部变量和返回地址。
- 堆栈指针(SP) 是一个特殊的寄存器,用于指向当前堆栈的顶部。它会随着数据的压栈和弹栈操作动态调整。
- 堆栈帧 是每次函数调用时在堆栈上创建的一个独立区域,用于存储函数的局部变量、参数和返回地址。
- 基址指针(BP) 用于引用堆栈帧中的数据,使得函数可以方便地访问参数和局部变量。
- 堆栈溢出 是指堆栈空间耗尽,可能导致程序崩溃或安全漏洞。应采取适当的预防措施,如限制递归深度和使用栈保护机制。
- 堆栈与堆 的主要区别在于堆栈是自动管理的、快速访问的,而堆是手动管理的、灵活分配的。
希望这个详细的介绍能帮助你更好地理解 CPU 中的堆栈指针及其相关概念。如果你有任何具体问题或需要进一步的解释,欢迎继续提问! 😊
相关文章:
【CPU】堆栈和堆栈指针(个人草稿)
详细的 CPU 中堆栈指针(Stack Pointer, SP)及相关知识介绍 1. 什么是堆栈? 堆栈(Stack) 是一种后进先出(LIFO, Last In First Out)的数据结构,广泛用于计算机系统中,尤…...

BMS应用软件开发 — 2 单体电池的基本结构和工作原理
目录 1 单体电池基本组成 2 单体电池封装形式 3 电池充放电过程 4 不同电池材料性能差异 1 单体电池基本组成 单体电池其基本组成包括以下几个关键部分: 正极:正极材料通常由锂的金属氧化物构成,如锂钴氧化物(LiCoO2…...
uni-app开发-习惯养成小程序/app介绍
目录 一:功能概述 二:功能部分代码和截图 一:功能概述 1 习惯目标生成 创建习惯:用户可以添加新的习惯目标,每个习惯可以包含名称、描述、图标、目标天数。 关联习惯完成:用户通过设定达成目标以后,生成习惯养成记录。 2 习惯打卡 简单快捷的打卡:提供一个直观的界面…...

鸿蒙HarmonyOS开发:拨打电话、短信服务、网络搜索、蜂窝数据、SIM卡管理、observer订阅管理
文章目录 一、call模块(拨打电话)1、使用makeCall拨打电话2、获取当前通话状态3、判断是否存在通话4、检查当前设备是否具备语音通话能力 二、sms模块(短信服务)1、创建短信2、发送短信 三、radio模块(网络搜索&#x…...

Netty中用了哪些设计模式?
大家好,我是锋哥。今天分享关于【Netty中用了哪些设计模式?】面试题。希望对大家有帮助; Netty中用了哪些设计模式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 Netty 是一个高性能的网络通信框架,广泛…...
Mac 安装psycopg2出错:Error:pg_config executable not found的解决
在mac 上执行pip3 install psycopg2-binary出现如下错误: Error:pg_config executable not found然后我又到终端里执行 brew install postgresql16 显示 Warning: You are using macOS 15. We do not provide support for this pre-release version. It is expe…...
【vue3封装element-plus的反馈组件el-drawer、el-dialog】
vue2中封装el-drawer、el-dialog这类反馈类子组件,需要将父组件的visible值传递子组件,并且再通过$emit将关闭弹窗的组件值传回父组件,同事子组件还需要监听父组件传递过来的visible的值,来驱动弹窗显示隐藏,很麻烦&am…...
LeetCode:2274. 不含特殊楼层的最大连续楼层数(排序 Java)
目录 2274. 不含特殊楼层的最大连续楼层数 题目描述: 实现代与解析: 排序 原理思路: 2274. 不含特殊楼层的最大连续楼层数 题目描述: Alice 管理着一家公司,并租用大楼的部分楼层作为办公空间。Alice 决定将一些…...

生成树之STP
STP目的 STP:生成树协议,旨在将一个环型网络结构修剪成一个树型的结构,达到防环的作用 STP的步骤 STP有如下几个步骤,选举出四种角色,共同构建起STP生成树 1、开启生成树的交换机,会互相发送BPDU 2、交换…...

音视频入门基础:MPEG2-PS专题(6)——FFmpeg源码中,获取PS流的视频信息的实现
一、引言 通过FFmpeg命令可以获取到PS文件/PS流的视频压缩编码格式、色彩格式(像素格式)、分辨率、帧率信息: ./ffmpeg -i XXX.ps 本文以H.264为例讲述FFmpeg到底是从哪个地方获取到这些视频信息的。 二、视频压缩编码格式 (…...

深入解析HDFS:定义、架构、原理、应用场景及常用命令
引言 Hadoop分布式文件系统(HDFS,Hadoop Distributed File System)是Hadoop框架的核心组件之一,它提供了高可靠性、高可用性和高吞吐量的大规模数据存储和管理能力。本文将从HDFS的定义、架构、工作原理、应用场景以及常用命令等…...
Rust:运行调用 Lua 脚本
以下是一个Rust运行Lua脚本的简单例子: 首先,确保你的Rust项目中已经添加了rust-lua库的依赖。可以在Cargo.toml文件中添加以下内容: [dependencies] rust-lua "0.36" # 注意:版本号可能会更新,请根据实…...
PHP语言的数据库编程
PHP语言的数据库编程 引言 随着互联网的发展,各类网站和应用程序如雨后春笋般涌现,数据库作为它们数据存储和管理的核心,扮演着至关重要的角色。PHP作为一种流行的服务器端脚本语言,被广泛应用于Web开发。PHP不仅具有简单易学的…...

Formality:参数化设计的命名规则
相关阅读 Formalityhttps://blog.csdn.net/weixin_45791458/category_12841971.html?spm1001.2014.3001.5482 在Formality中使用set_top命令设置一个容器的顶层设计(elaborate)时,一个参数化的设计(或者说模块)可能因为其参数覆盖而出现不同…...

xss-labs关卡记录8-14
第八关 还是常规方法,先上传我们常用的试试,onfocus <script> <a hrefjavascript:alert()> 查看源码发现,value这里应该是对我们的<>进行了 处理,然后在href这里,对常用的关键词进行了替换处理&…...

SPSS实现中介效应与调节效应
1. 中介效应 SPSS 实现 本例研究的自变量(X) “工作不被认同”;中介变量(M)为“焦虑”,因变量(Y)为“工作绩效”。探讨焦虑是否在工作不被认同与工作绩效间的作用。 (2&…...
计算机的错误计算(二百零三)
摘要 利用两个大模型化简计算 其中一个大模型是数学解题器,它通过化简得出了正确结果;另外一个大模型给出了 Python代码。 例1. 化简计算摘要中算式。 下面是一个数学解题器大模型给的回答。 以上是数学解题器大模型给的回答。 下面是与另外一个大模型…...
【计算机网络】什么是AC和AP?
在现代的无线网络中,AC(Access Controller,接入控制器)和AP(Access Point,无线接入点)是两个至关重要的设备,它们在网络的管理、连接和优化中扮演着重要角色。理解它们的功能和区别&…...

python3中函数的参数
一. 简介 前面学习了Python3中函数的语法规则,文章如下: python3中函数的语法规则-CSDN博客 本文继续学习python中函数的参数。调用函数时可使用的正式参数类型: 必需参数,关键字参数,默认参数,不定长参…...

数据仓库建设方案和经验总结
在做数据集成的过程中,往往第二步的需求就是建设数仓由于数据分散在不同的存储环境或数据库中,对于新业务需求的开发需要人工先从不同的数据库中同步、集中、合并等处理,造成资源和人力的浪费。同时,目前的系统架构,无…...
MySQL 隔离级别:脏读、幻读及不可重复读的原理与示例
一、MySQL 隔离级别 MySQL 提供了四种隔离级别,用于控制事务之间的并发访问以及数据的可见性,不同隔离级别对脏读、幻读、不可重复读这几种并发数据问题有着不同的处理方式,具体如下: 隔离级别脏读不可重复读幻读性能特点及锁机制读未提交(READ UNCOMMITTED)允许出现允许…...

vscode(仍待补充)
写于2025 6.9 主包将加入vscode这个更权威的圈子 vscode的基本使用 侧边栏 vscode还能连接ssh? debug时使用的launch文件 1.task.json {"tasks": [{"type": "cppbuild","label": "C/C: gcc.exe 生成活动文件"…...

Mac软件卸载指南,简单易懂!
刚和Adobe分手,它却总在Library里给你写"回忆录"?卸载的Final Cut Pro像电子幽灵般阴魂不散?总是会有残留文件,别慌!这份Mac软件卸载指南,将用最硬核的方式教你"数字分手术"࿰…...
Matlab | matlab常用命令总结
常用命令 一、 基础操作与环境二、 矩阵与数组操作(核心)三、 绘图与可视化四、 编程与控制流五、 符号计算 (Symbolic Math Toolbox)六、 文件与数据 I/O七、 常用函数类别重要提示这是一份 MATLAB 常用命令和功能的总结,涵盖了基础操作、矩阵运算、绘图、编程和文件处理等…...
Axios请求超时重发机制
Axios 超时重新请求实现方案 在 Axios 中实现超时重新请求可以通过以下几种方式: 1. 使用拦截器实现自动重试 import axios from axios;// 创建axios实例 const instance axios.create();// 设置超时时间 instance.defaults.timeout 5000;// 最大重试次数 cons…...

html css js网页制作成品——HTML+CSS榴莲商城网页设计(4页)附源码
目录 一、👨🎓网站题目 二、✍️网站描述 三、📚网站介绍 四、🌐网站效果 五、🪓 代码实现 🧱HTML 六、🥇 如何让学习不再盲目 七、🎁更多干货 一、👨…...
管理学院权限管理系统开发总结
文章目录 🎓 管理学院权限管理系统开发总结 - 现代化Web应用实践之路📝 项目概述🏗️ 技术架构设计后端技术栈前端技术栈 💡 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 🗄️ 数据库设…...
动态 Web 开发技术入门篇
一、HTTP 协议核心 1.1 HTTP 基础 协议全称 :HyperText Transfer Protocol(超文本传输协议) 默认端口 :HTTP 使用 80 端口,HTTPS 使用 443 端口。 请求方法 : GET :用于获取资源,…...

如何更改默认 Crontab 编辑器 ?
在 Linux 领域中,crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用,用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益,允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...
区块链技术概述
区块链技术是一种去中心化、分布式账本技术,通过密码学、共识机制和智能合约等核心组件,实现数据不可篡改、透明可追溯的系统。 一、核心技术 1. 去中心化 特点:数据存储在网络中的多个节点(计算机),而非…...