学C的第十一天【查看汇编代码一步步了解 函数栈帧(栈区局部变量)的创建和销毁】

这篇具有很好参考价值的文章主要介绍了学C的第十一天【查看汇编代码一步步了解 函数栈帧(栈区局部变量)的创建和销毁】。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

=========================================================================

相关代码gitee自取:C语言学习日记: 加油努力 (gitee.com)

=========================================================================

接上期:
学C的第十天(继续深入学习函数、函数递归、练习)-CSDN博客

=========================================================================

                 

函数栈帧的创建和销毁

  • 越高级编译器越不容易学习和观察该过程

                    

  • 同时在不同的编译器下,函数调用过程中栈帧的创建略有差异的,
    具体细节取决于编译器的实现

               

寄存器:ebp 和 esp(和函数栈帧有关)

esp栈顶指针        ;        ebp栈低指针


  • 寄存器集成在CPU上

               

  •  ebpesp 这两个寄存器中存放的是地址

               

  • 这两个地址是用来维护函数栈帧
                        

1. 每一次函数调用,都要在栈区创建一个空间

               

2. 正在调用哪个函数,esp 和 ebp 就在维护哪个函数的函数栈帧

               

3. esp 和 ebp 之间的空间就是系统为这次函数所调用的空间,叫这次函数的函数栈帧

               

4. 栈区的使用习惯使用地址,使用地址

               

5. 空间消耗时,从高地址向低地址消耗

               

6. 再开辟新空间时,使用的空间是上面的空间往上使用

               

7. 像栈一样,放数据在顶上(栈顶)放数据


               

测试代码:

#include <stdio.h>

int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}

int main()
{
	int a = 10;
	int b = 20;
	int c = 0;

	c = Add(a, b);

	printf("%d\n", c);

	return 0;
}
函数栈帧图示:

汇编局部变量的创建,CCC全是C,c语言

                      


                    

VS2013中,main函数也是被其它函数调用的

               

mainCRTStartup        -->        __tmainCRTStartup        -->        main函数 

            (调用)                                            (调用)

汇编局部变量的创建,CCC全是C,c语言

                    

 实际开辟的空间为:

汇编局部变量的创建,CCC全是C,c语言

              

 (查看汇编代码:)

汇编局部变量的创建,CCC全是C,c语言

                  


                    

函数栈帧实现过程(重点):

(1).push压栈):给栈顶放一个元素

        [ 补充:pop出栈) -->   从栈顶删除一个元素 ]

(压栈前:)

汇编局部变量的创建,CCC全是C,c语言

                  

(压栈后:esp会往上移,移到压的元素上方)

汇编局部变量的创建,CCC全是C,c语言

            文章来源地址https://www.toymoban.com/news/detail-758411.html

            

---------------------------------------------------------------------------------------------

            

            

(2).mov把后面的值赋给前面,把esp的值赋给ebp):

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(3).sub让esp减去一个十六进制数):

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(4).连续push三次:

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(5).leaload effective address -- 加载有效地址,
把一个有效地址加载到edi中
):

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(6).两次mov后,rep stos

汇编局部变量的创建,CCC全是C,c语言

之前出现过的“烫烫烫”乱码的原因:

              

变量未初始化,变量里面的数据是“cc cc cc cc”,
这些“cc cc cc cc”在使用后会产生随机值
"烫烫烫",而初始化就会将这些随机值覆盖

            

---------------------------------------------------------------------------------------------

            

            

(7).产生局部变量:int a = 10; (mov)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(8).产生局部变量:int b = 20; (mov)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(9).产生局部变量:int c = 0; (mov)

汇编局部变量的创建,CCC全是C,c语言

              

             

===================================================================== 

                

(总结上面步骤)局部变量(上面的a、b、c)的创建过程:

                 

  • 为这次函数调用创建函数栈帧   -- (1)~(6)
                     
  • 在函数栈帧中找到空间把局部变量放进去   --(7)~(9)

=====================================================================

                  

(10).调用函数:传参(mov

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(11).调用函数:传参(push

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(12).调用函数:传参(mov

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(13).调用函数:传参(push

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(14).call:调用函数(进入Add()函数)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(15).进入Add()函数后:

汇编局部变量的创建,CCC全是C,c语言

              

当前开辟的空间情况:)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(16).Add()函数push

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(17).Add()函数mov

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(18).Add()函数sub

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(19).Add()函数连续三次push

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(20).Add()函数lea(加载有效地址) --> mov  --> mov --> rep stos

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(21).Add()函数中产生局部变量:int z = 0; (mov)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(22).Add()函数中进行计算:z = x + y

                

 形参的产生和使用:
  • 形参是对实参的临时拷贝:形参是调用的main函数中对变量的拷贝,
    即下图
     ecxeax所以改变形参,改变的也只是 ecxeax ,
    并不会改变main函数中的实参

                        
  • 压栈时:先压的b’,所以在a‘下面,所以传参是先传的形参y再传的形参x
                    
  • 形参的使用:通过指针的偏移量找到形参
                     

汇编局部变量的创建,CCC全是C,c语言

                

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(23).Add()函数计算后进行返回return z

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(24).Add()函数调用完后销毁空间返回main函数
pop -- 出栈(弹出栈顶元素)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(25).Add()函数调用完后销毁空间返回main函数:ret -- call函数调用完后
返回main函数call的下一条指令(之前留的地址会出栈)

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(26).main函数:销毁形参

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(27).main函数:使用Add函数的返回值

汇编局部变量的创建,CCC全是C,c语言

            

            

---------------------------------------------------------------------------------------------

            

            

(28).最后main函数的销毁和Add()函数的销毁类似

到了这里,关于学C的第十一天【查看汇编代码一步步了解 函数栈帧(栈区局部变量)的创建和销毁】的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 第五十一天打卡

    中等 1.5K company 微软 Microsoft 给定一个整数数组prices,其中第 prices[i] 表示第 i 天的股票价格 。​ 设计一个算法计算出最大利润。在满足以下约束条件下,你可以尽可能地完成更多的交易(多次买卖一支股票): 卖出股票后,你无法在第二天买入股票 (即冷冻期为 1 天)。 注意

    2023年04月09日
    浏览(25)
  • 代码随想录第十一天 | ​​​​​​LeetCode 20. 有效的括号、​​​​​​LeetCode 1047. 删除字符串中的所有相邻重复项、​​​​​​LeetCode 150. 逆波兰表达式求

    目录 ​​​​​​LeetCode 20. 有效的括号 文章讲解:代码随想录(programmercarl.com) 视频讲解:栈的拿手好戏!| LeetCode:20. 有效的括号_哔哩哔哩_bilibili 思路 ​​​​​​LeetCode 1047. 删除字符串中的所有相邻重复项 文章讲解:代码随想录(programmercarl.com) 视频讲解:栈的好戏还

    2024年02月22日
    浏览(34)
  • C语言(第三十一天)

    6. 调试举例1 求1!+2!+3!+4!+...10!的和,请看下面的代码: 调试找一下问题。 7. 调试举例2 在VS2019、X86、Debug 的环境下,编译器不做任何优化的话,下面代码执行的结果是啥? 程序运行,死循环了,调试看看为什么? 调试可以上面程序的内存布局如下:  1. 栈区内存的使用习惯

    2024年02月11日
    浏览(29)
  • 【代码随想录 | Leetcode | 第十一天】字符串 | 反转字符串 | 反转字符串 II | 替换空格 | 反转字符串中的单词 | 左旋转字符串

    欢迎来到小K的Leetcode|代码随想录|专题化专栏,今天将为大家带来字符串~反转字符串 | 反转字符串 II | 替换空格 | 反转字符串中的单词 | 左旋转字符串的分享 ✨ ✨题目链接点这里 编写一个函数,其作用是将输入的字符串反转过来。输入字符串以字符数组 s 的形式给出。不要

    2024年02月15日
    浏览(34)
  • node 第二十一天 webpack 初见

    为什么需要学习(了解)webpack webpack是前端工程化的基石,webpack又是基于node进行文件打包bundle,所以作为前端起手学习node服务端开发,同时学习webpack是很有必要的。 随着vite的出现,vue这一脉可能也许不再需要学习webpack了,但是需要知道的是, 打包一定是前端工程化绕不

    2024年01月16日
    浏览(31)
  • 谷粒商城第十一天-完善商品分组(主要添上关联属性)

    目录 一、总述 二、前端部分 2.1 改良前端获取分组列表接口及其调用 2.2 添加关联的一整套逻辑 三、后端部分 四、总结 前端部分和之前的商品品牌添加分类差不多。 也是修改一下前端的分页获取列表的接口,还有就是加上关联的那一套逻辑,包括基本构件的引入、数据域的

    2024年02月13日
    浏览(28)
  • 15天学习MySQL计划-MySQL工具(进阶篇)-第十一天

    1.mysql 该mysql 不是指MySQL服务,而是指MySQL的客户端工具。 -e选项可以在MySQL客户端执行SQL语句,而不用连接到MySQL数据库再执行,对于一些批处理脚本,这种方式尤其方便。 2.mysqladmin mysqladmin是一个执行管理操作的客户端程序。可以用它来检查服务器的配置和当前状态,创建并

    2024年02月01日
    浏览(45)
  • 从零开始的力扣刷题记录-第五十一天

    题目描述: 给你一棵二叉搜索树的 root ,请你 按中序遍历 将其重新排列为一棵递增顺序搜索树,使树中最左边的节点成为树的根节点,并且每个节点没有左子节点,只有一个右子节点。 题解: 中序遍历存储节点后按顺序连接即可 代码(Go): 题目描述: 小扣在秋日市集发

    2024年02月08日
    浏览(30)
  • 从零开始的力扣刷题记录-第六十一天

    题目描述: 给定由一些正数(代表长度)组成的数组 nums ,返回 由其中三个长度组成的、面积不为零的三角形的最大周长 。如果不能形成任何面积不为零的三角形,返回 0。 题解: 排序后从后往前遍历,取最大的三个边,如果满足两边之和大于第三边则返回,否则整体向前

    2024年02月09日
    浏览(34)
  • 秒懂百科,C++如此简单丨第二十一天:栈和队列

    目录 前言 Everyday English 栈(Stack) 图文解释 实现添加删除元素 实现查看清空栈 完整代码 运行示例 栈的选择题 队列(Queue) 图文解释 队列的基本用法 完整代码  运行结果  队列的好处  结尾  今天我们将学习两个新的数据结构——栈和队列。 A friend in need is a friend indeed

    2024年02月20日
    浏览(25)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包