前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >栈论 : 递归与栈式访问,如何用栈实现所有递归操作(函数调用底层篇)

栈论 : 递归与栈式访问,如何用栈实现所有递归操作(函数调用底层篇)

作者头像
执生
发布2020-09-27 10:26:25
8440
发布2020-09-27 10:26:25
举报
文章被收录于专栏:立权的博客立权的博客

重大错误说明 : 栈顶的指针始终是指向最后一个入栈元素的位置的,不是最后一个入栈元素的位置上面!请读者留意 (PS : 后来又看了一下,好像也不是什么大问题...)

上一篇 :

栈论 : 递归与栈式访问,如何用栈实现所有递归操作(基础知识篇)

2.函数调用底层篇(了解递归调用的硬件实现)

一开始,main函数没有调用add之前他的栈帧如下图,当然,下面只是简略介绍,实际上内存布局比下面更复杂(省略了寄存器等)。

当要调用add函数的时候main 将 自己的变量拷贝后压入栈中,我们称之为“形参”

上图中变量c 和变量d的拷贝就是所谓的”形参“

接下来将main函数的ebp地址压入栈中保存,以便add函数调用完之后恢复main在内存中的栈帧

接着 就是重要的环节,add函数的栈帧创建,add函数的栈帧创建在add函数自己的操作里。

没想到吧?add函数的栈帧是add函数自己创建的。一般的思维都是父对象为子对象创建空间,再让子对象自己发挥,可能这是比较袒护孩子的行为吧,你看函数调用却是让自己的孩子去开创天地,值得学习。(当然 这是win10下汇编的得出的结果,可能不同系统不一样)

add函数本身操作 :

1.将esp 的值赋给ebp,这里的ebp就是add函数自己栈帧的栈底了。

2.让esp = esp - X ; X是一个位移量,表示esp要上移,esp上移的这个位移量差不多是add函数栈帧的大小。(还有一些寄存器之类的会占用空间,忽略不计)

如图:

这时候的栈应该是这样的

接下来,涉及到最重要环节!栈帧之间的通信

add函数的内部操作是 两个数相加,这两个数是形参,难道在add函数的栈帧中要访问在main函数栈帧中的形参吗?没错,就是直接访问。

我们来看看a + b 的汇编过程

对汇编不了解的同学可以先把 eax理解成一个变量,这个变量不在内存中(当然也就不在我们的栈区中)。mov是放进去的意思,理解把逗号右边的值放到(赋给)左边变量上(eax)去。 add是把逗号左右两边的数加起来,放到左边去。

我们发现,a + b 无非是把 ebp + 8, ebp + 12(十六进制数0Ch的十进制数)读取到的值加起来并且放到eax变量里而已。

而从 ebp + 8 和 ebp + 12 读取到的正好是main函数栈帧中的形参

栈帧通信总结1.

子函数直接调用父函数栈帧内的形成,访问父函数

这是子向父索求信息,那么父向子索取信息呢?聪明的你可能已经猜到了,返回值!

子函数返回过程:

子函数完成之后,子函数的栈帧会被废弃掉

上面大圈里的小圈,两句汇编就是把栈顶和栈底移动回原来的main栈帧处。

在我们刚刚看到的a+b之后,子函数已经没什么大动作了,也就是说我们操作完之后的数是放在eax里的。

父函数就是通过访问子函数结束后遗留在eax中的数来和子函数通信,也就是说,eax里的是子函数的返回值!

从汇编也可以看到main在调用完add函数之后,为e赋值的时候直接访问了eax;

add    esp,8

这句还是要好好说一说的,子函数返回之后esp还在形参的上面,既然子函数完成了,形参也没必要存在,于是需要把他们废弃掉,废弃的方法是把他们移除esp和ebp之间,也就是让esp下降就好了。

栈帧通信总结2.

父函数直接访子函数在EAX中遗留的返回值

综上,我们得出以下几点结论。

1.子函数直接调用父函数栈帧内的形成,访问父函数

2.父函数直接访子函数在EAX中遗留的返回值

3.父函数调用子函数,子函数创建栈帧,子函数完成后子函数的栈帧销毁

下一篇 :

栈论 : 递归与栈式访问,如何用栈实现所有递归操作(幼儿园题目篇)

护眼绿:

没人看的结语:

首先很感谢你看到这里,辛苦了。

文章中某些地方可能不正确或不准确,代码也可能不够高效可读,希望读者能够帮忙指正,共同学习进步。

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019-11-04 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档