【数据结构和算法初阶(C语言)】二叉树铺垫--栈帧的创建与销毁--细节全解

 前言:

  • 学习这么久以来,可能有很多疑问:
  • 局部变量怎么创建的?
  • 为什么局部变量的值是随机的?
  • 函数是怎么传参的?传参的顺序是怎么样的?
  • 形参和实参是什么样的关系?
  • 函数调用是怎么做的?
  • 函数调用结束后是怎么返回的?
  • 那么本篇博文就来一一讲解一下。
  • 环境:vs2021,大家也可以使用更低版本的编译器更容易观察出现象。(推荐vc6.0)在不同的编译器下面,函数调用的过程中栈帧的创建是稍有差异的,大体逻辑是一样的具体差异的细节取决于编译器的实现。(越新的编译器封装的就越复杂,不容易抽离出函数栈帧这个过程)

目录

 前言:

1.铺垫

寄存器

main函数被谁调用

2.正题

结论: 


1.铺垫

寄存器

百度百科链接

寄存器中有eax/ebx/ecx/ edx    /ebp/esp

重点是esp/ebp两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。

一般吧ebp叫做栈底指针,把esp叫做栈顶指针,栈区的使用习惯是先使用高地址再使用低地址。我们今天测试环境中是rbp,rsp

每一个函数调用都要在栈区上创建或者开辟一块空间。

main函数被谁调用

我们调试调用堆栈

不会调试的可以先看我的这篇文章:vs2021环境调试详细

调用关系

那接下来我们就来看看具体的过程剖析

2.正题

F10运行调试起来,右键来到反汇编,看我们的反汇编代码

刚进入,我们的rbp和rsp在为我们的调用main函数的函数维护栈帧,进入main函数过后

先压入了一个rbp和一个rdi

再讲rsp减148h(这是一个16进制数字)

接着往下:

lea的意思是:load effective address 就是1加载一个地址造rbp中

那么现在的rbp和rsp就维护了main函数维护的这块空间。

main函数的空间开辟好了过后,开始执行main函数中的代码:

往下执行:

edx  存储20

ecx 存储10

然后call调用add函数

先将edx的值放到rsp+10的位置

将ecx的值放到rsp+8的位置

压入rbp和rdi

 return后,将rbp+E8h给rsp,相当于销毁了add的栈帧

将rbp和rid出栈(这里由于我重新启动了一次所以数据不一样,不过还是可以看到rbp和rsp之间相差20.回到了起点,原先的空间被释放了)

结论: 

那到这里我们就已经可以回答了

局部变量是如何创建的:

调用函数的时候在栈上开辟空间过后,在这块空间里给变量分配空间。

为什么局部变量不初始化是随机值?

因为随机值是随机写入的,创建好空间后就会将这块空间的值变为随机值。初始化就将随机值覆盖

函数如何传参:

还没有调用函数的时候,就将这参数的值通过寄存器(ebx,ecx)push到了栈顶,通过指针偏移的方式找到形参。

形参和实参的关系:

形参是在压栈时独立开辟的空间(ebx,ecx),值相同,空间二者各自独立。

函数是如何返回的

调用函数之前,都会调用call指令,会将调用call指令的后一条指令的地址先压入栈,然后将函数调用的上一个函数的rdp也压入栈,函数调用结束返回pop(弹出edp)就得到我们上一个函数的函数栈帧的维护地址,就回到了原始栈帧空间,又有下一条指令的地址,就可以继续运行。返回值通过寄存器eax带回。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/544522.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Vue | 使用 ECharts 绘制折线图

目录 一、安装和引入 ECharts 二、使用 ECharts 2.1 新增 div 盒子 2.2 编写画图函数 2.3 完整代码结构 三、各种小问题 3.1 函数调用问题 3.2 数据格式问题 3.3 坐标轴标签问题 3.4 间隔显示标签 参考博客:Vue —— ECharts实现折线图 本文是在上…

HTML5CSS3提高导读

HTML5CSS3提高导读 2024/2/20 HTML5 的新增特性主要是针对于以前的不足,增加了一些新的标签、新的表单和新的表单属性等。 这些新特性都有兼容性问题,基本是 IE9 以上版本的浏览器才支持,如果不考虑兼容性问题,可以大量使用这 …

面向对象(C# )

面向对象(C# ) 文章目录 面向对象(C# )ref 和 out传值调用和引用调用ref 和 out 的使用ref 和 out 的区别 结构体垃圾回收GC封装成员属性索引器静态成员静态类静态构造函数拓展方法运算符重载内部类和分布类 继承里氏替换继承中的…

SPSS k-均值聚类的 anova分析表解读

from&#xff1a;SPSS K均值聚类&#xff08;k-means&#xff09;和可视化方法 - CollinsLi - 博客园 (cnblogs.com) F值&#xff1a;变量对聚类的贡献 显著性水平&#xff1a;<0.05 则因子显著

vanna:基于RAG的text2sql框架

文章目录 vanna简介及使用vanna的原理vanna的源码理解总结参考资料 vanna简介及使用 vanna是一个开源的利用了RAG的SQL生成python框架&#xff0c;在2024年3月已经有了5.8k的star数。 Vanna is an MIT-licensed open-source Python RAG (Retrieval-Augmented Generation) fram…

springboot趵突泉景区的智慧导游小程序

摘 要 当今社会已经步入了科学技术进步和经济社会快速发展的新时期&#xff0c;国际信息和学术交流也不断加强&#xff0c;计算机技术对经济社会发展和人民生活改善的影响也日益突出&#xff0c;人类的生存和思考方式也产生了变化。传统趵突泉景区的智慧导游采取了人工的管理方…

linux源配置:ubuntu、centos

1、ubuntu源配置 1&#xff09;先查电脑版本型号: lsb_release -c2&#xff09;再编辑源更新&#xff0c;源要与上面型号对应 参考&#xff1a;https://midoq.github.io/2022/05/30/Ubuntu20-04%E6%9B%B4%E6%8D%A2%E5%9B%BD%E5%86%85%E9%95%9C%E5%83%8F%E6%BA%90/ /etc/apt/…

Django 解决新建表删除后无法重新创建等问题

Django 解决新建表删除后无法重新创建等问题 问题发生描述处理办法首先删除了app对应目录migrations下除 __init__.py以外的所有文件:然后&#xff0c;删除migrations中关于你的app的同步数据数据库记录最后&#xff0c;重新执行迁移插入 问题发生描述 Django创建的表&#xf…

C语言—打印如图矩阵

输出矩阵 在一个二维数组中形成并输出如下矩阵: #include <stdio.h> main() { int i,j,a[5][5];for(i0;i<4;i)for(j0;j<4;j)if(i<j) a[i][j]1;else a[i][j]i-j1;for(i0;i<4;i){ for(j0;j<4;j)printf("%d ",a[i][j]);printf("…

Java获取视频封面图,利用FFmpegFrameGrabber获取视频封面图

依赖 <dependency><groupId>org.bytedeco</groupId><artifactId>javacv-platform</artifactId><version>1.5.9</version></dependency>传入视频流获取图片byte /*** 获取视频截图** param frameNumber 视频的指定帧数* param …

VUE3生命周期钩子

概念 每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤&#xff0c;比如设置好数据侦听&#xff0c;编译模板&#xff0c;挂载实例到 DOM&#xff0c;以及在数据改变时更新 DOM。在此过程中&#xff0c;它也会运行被称为生命周期钩子的函数&#xff0c;让开发者有机会在…

建筑能耗管理系统项目案例

一、项目背景 近年来&#xff0c;某市级银行认真贯彻新发展理念&#xff0c;以《中国人民银行节能减排工作管理办法》为准绳&#xff0c;统筹推进能源资源节约管理&#xff0c;聚焦绿色低碳发展&#xff0c;努力开创辖区公共机构节约能源资源绿色低碳发展的新局面。但当前支行…