关于堆栈的一些理解

关于堆栈的一些理解

一、定义:

从计算机科学的角度来看,栈指的是一种数据结构,是一种先进后出的数据表。栈的最常见操作有两种:压栈(PUSH)、弹栈(POP):用于标识栈的属性也有两个:栈顶(TOP)、栈底(BASE)。可以把栈想象成一个糖葫芦,都是从上往下吃的!

二、原理

堆栈是使用了两个工具:
ebp :扩展基址指针寄存器(extended base pointer) 其内存放一个指针,该指针指向系统栈最上面一个栈帧的底部。
edp:扩展栈指针寄存器(extended stack pointer),是指针寄存器的一种,用于存放函数栈顶指针。
堆栈通过这两个指针来实现堆栈空间大小的变化。
在这里插入图片描述
在这里插入图片描述

三、应用

堆栈一个最大的好处就是为调用函数提供了方便。
这里不得不提到两个汇编指令:

call 指令 (call 函数名称)
内部工作过程:1.push当前指令的下一条指令的首地址,并且使ESP-=4,并且保存当前的edp,使edp的值入栈。2.跳转到所调用的函数入口地址函数入口处。

ret 指令
内部工作过程:1.pop系统堆栈栈顶值,并赋值给“能够控制取指令的系统“
2.取出第一步的指令,返回调用处,继续执行保存的下一步指令。在这里插入图片描述

这里也就引出了一个很关键的点:形参与实参。
我们经过以上堆栈得知,一个程序共用一个堆栈,那么,当我们调用函数时,形参的值会随之入栈,但当这个函数结束后,形参所占用的栈的空间也会随之释放。那么,在主函数中去返回形参的首地址是一个极其错误的决定,这样会得到无法预知的结果,这对程序来说,是不可接受的!

四、总结

1.每一个运行的进程,是多个函数的彼此调用,每一个运行的进程都会分配得到一段长度有限的系统堆栈空间,且,这个系统堆栈的栈底与栈顶指针相同,构成一个空栈。
2.局部变量、形参与实参都会使用这段系统堆栈空间。
3.每一个函数运行之初,都会先保存上一个函数(主调函数)的系统堆栈栈底指针,这会消耗4B空间
4.在调用一个函数前,call指令会保存“返回地址”到系统堆栈;而这一步是先于第三步执行的,也会消耗4B空间
5.局部变量占用的空间是直接提高esp的值,即esp减len,得到的空间
6.在调用一个函数前,若该函数存在参数,则,从右向左将实参的值入栈
7.实参值入栈所占用的空间,就是与之对应的形参变量空间
8.当韩束运行结束后,首先将esp下降到与edp相同的位置,即,恢复到函数运行之初的“空栈“状态
9.然后,将栈顶原本保存的前一个函数(主调函数)的堆栈栈底值出栈并赋值给edp,使edp恢复到调用前的堆栈栈底状态
10.接着,将栈顶当前保存的“返回地址”出栈,并赋值给能控制cpu取下一条指令的特殊寄存器,以实现执行代码回到被调函数的调用语句的下一条语句

注意:
1.由于系统堆栈空间是所有当前进程的函数所共用的空间,因此,不同函数的局部变量所占用的空间可能会彼此覆盖;所以,不要返回一个函数的局部变量的首地址到被调函数
2.局部变量所占用的空间,是通过执行该函数的指令得到的;因此,在函数没有执行前,其相关变量不存在
3.递归调用,如果不控制其递归深度,因目前每次调用至少消耗8B系统堆栈空间,因此,会极快的造成系统堆栈空间的一处,这会使得该程序执行崩溃!

在这里特别感谢要铁血教主!
2020.7.16于机房

部分摘自:作者:幸运的芳1990
链接:https://www.jianshu.com/p/ffe303d96dbd

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值