资讯专栏INFORMATION COLUMN

C语言学习笔记—P17(函数栈帧的创建与销毁<超详解版>+图解+题例)

gnehc / 1423人阅读

摘要:目录前言由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教前言由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教作者新晓故知作者新晓故知那些代码背后的故事那些代码背后的故事通过

目录

前言:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                      ——By 作者:新晓·故知

那些代码背后的故事:

通过反汇编讲解函数栈帧的创建与销毁!

 注:本次编译环境为:Visual Stdio 2013 !

 越高级的编译器越难以抽离函数栈帧分装的过程!

main函数也会被其他函数调用哦!

                                                                 

                                                                    

反汇编查看:​

 为a、b、c开辟空间并存值:​

                                                           ​

                                                                     ​

                                                                      ——By 作者:新晓·故知  整理+创作​

                                                                    ​

完成a的开辟、存值:

 完成b的开辟、存值:​​

 完成c的开辟、存值:​

                                                                     ​

 push 压栈:

                                                                     ​

 传参:​

 call指令将下一条指令的地址拿出压栈!​

                                                                   ​

 为Add函数准备栈帧!​

                                                                      ——By 作者:新晓·故知  整理+创作​

                                              

形参对应的函数(子函数)计算:​

 注:

函数调用时没有创建形参,最初在调用函数时,通过call指令和其他指令,就将参数传过去了,将实参a、b通过push压栈在a"、b"。因为是在栈中进行,所以先传的是b(右面的参数),压入栈中,再传a(左面的参数),故参数从右向左传参!

当进入函数计算时,形参回头去找压栈时的空间的a、b对应的值!

因此说:形参是对实参的临时拷贝!改变形参的值不影响实参!

 返回:

 先在eax保存z的值,安全!

                                                            ​

                                                            ​

此时所有指令回到main函数!main函数的栈帧交给esp,ebp进行维护!Add函数的栈帧销毁!别担心!z的值在寄存器eax中存放,安全着呢!

                                                             ​

 这时显现出最初在栈顶存储call指令的下一条指令地址的作用:

在进行函数调用结束后回到主函数,并从call指令的下一条指令开始执行!

逻辑严谨!不仅要走的出去,也要回的来!

 esp执行至此,形参的空间均已释放归还给操作系统!

 而eax的值暂存的z=30!主函数进行打印输出!

解答:

1.局部变量的创建是首先为函数分配栈帧空间,栈帧空间初始化一部分空间后,再为局部变量分配一些空间!

2.局部变量不初始化的是随机值,因为创建的时候是随机放置的值!初始化后随机值被覆盖!

3.函数的传参是在未调用形参对应的函数(子函数)时通过push 操作将实参的值压栈,当真正进入形参函数时,在形参对应的函数(子函数)栈帧里通过指针的偏移量,找回形参,进行使用!

传参是从右向左传!

4.形参是在压栈时开辟的空间 ,它和实参只是在数值上相同的,空间上是独立的!

形参是实参的一份临时拷贝!改变形参的值不影响实参!

5.函数的调用见以上讲解!

6.函数调用的结果的返回:

调用之前将call指令的下一条指令的地址压入栈,记录存储,将ebp的调用的函数的上一个函数(此例为主函数ebp-main)的栈帧的ebp地址存储记录,当形参对应的函数(子函数)调用完返回时,弹出ebp就找到原始函数(上一个函数,此例为main函数)的ebp,而esp的指针移动返回时就能找到原始函数(此例为main函数)的栈帧的顶,回到原始函数(main函数)的栈帧空间,就可以跳转到已记录的call指令的下一条指令的地址,进行返回。

返回值是通过寄存器eax带回!

                                                              

注:

函数内部创建的静态变量是在全局变量空间开辟的!而以上介绍的是在栈区空间开辟的!

编译器会根据函数的不同,开辟合适的空间!

 1.a和b是不连续的,相隔的空间大小取决于不同的编译器!

2.函数的形参可以理解为:不在形参对应的函数(子函数)的栈帧里,而在主函数main拓展的栈帧里!

                                                                         ——Since 作者:新晓·故知  整理+创作



前言:
●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!

                                                                      ——By 作者:新晓·故知

那些代码背后的故事:

通过反汇编讲解函数栈帧的创建与销毁!

 注:本次编译环境为:Visual Stdio 2013 !

VS2013运行结果会一闪而过解决办法1:设置项目属性解决办法2:system("pause");

 

 越高级的编译器越难以抽离函数栈帧分装的过程!

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);	return 0;}

main函数也会被其他函数调用哦!

                                                                 

 

 

 

 

  

                                                                    

反汇编查看:

 

 为a、b、c开辟空间并存值:

 

                                                           

 

 

 

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/124090.html

相关文章

  • C语言知识精讲②】函数帧的创建销毁(全程图解

    摘要:这里分块讲解六函数栈帧的销毁过程一解析的作用是将栈顶的数据弹出,弹出数据储存到相应寄存器中。 ?前言? 读完这篇博客,你可以明白什么? ①局部变量到底是怎么在栈上创建的? ②为什么局部变量不初始化为随机值? ③函数是怎么传参的?传参的先后顺序是什么? ④形参和实参是什么关系? ⑤函数调用是怎...

    davidac 评论0 收藏0
  • C语言深层理解:函数帧的创建销毁

    摘要:语言深层理解函数中栈帧的创建与销毁引言引言问题一引言问题二引言问题三一栈的简单认识内存的简单了解栈的简单了解栈的定义栈的结构二寄存器与简单的汇编指令寄存器的定义寄存器的分类简单的汇编指令三栈帧的创建于销毁调试调用堆栈调 ...

    archieyang 评论0 收藏0
  • C语言学习笔记—P12(扫雷游戏<初级>+图解+题例

    目录  前言:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!                                                                       ——By 作者:新晓·故知                                                                       ...

    lykops 评论0 收藏0
  • 函数栈帧解析

    摘要:函数栈帧的销毁汇编语言了解函数传参函数返回值如何返回函数中变量如何初始化和赋值函数执行结束后系统进行了什么操作 文章目录 一、什么是函数栈帧 1.寄存器2.函数栈帧3.栈帧的作用和维护4.栈帧结构二、函数栈帧的创建  1.汇编2.main函数3.Add函数的创建三、函数...

    MonoLog 评论0 收藏0
  • C语言学习笔记—P15(指针<初阶>+图解+题例

    摘要:变量占用个字节的空间,这里是将的个字节的第一个字节的地址存放在变量中,就是一个之指针变量。是指针变量作者新晓故知总结指针变量,用来存放地址的变量。 目录 前言:●由于作者水平有限,文章难免存在谬误之处,敬请读者斧正,俚语成篇,恳望指教!                           ...

    weknow619 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<