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

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

前言:

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

                                                                     ——By 作者:新晓·故知

那些代码背后的故事:

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

image.gif编辑

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

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

image.gif编辑

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

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;
}
image.gif

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

image.gif编辑

                                                               

image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

 image.gif编辑

                                                                   

反汇编查看:image.gif编辑

image.gif编辑

为a、b、c开辟空间并存值:image.gif编辑

image.gif编辑image.gif编辑

                                                          image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

                                                                    image.gif编辑

image.gif编辑

image.gif编辑

                                                                     ——By 作者:新晓·故知  整理+创作image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

  image.gif编辑

                                                                   image.gif编辑

image.gif编辑

完成a的开辟、存值:

image.gif编辑

image.gif编辑

完成b的开辟、存值:image.gif编辑image.gif编辑

完成c的开辟、存值:image.gif编辑

image.gif编辑

                                                                    image.gif编辑

image.gif编辑

push 压栈:

image.gif编辑

image.gif编辑

 image.gif编辑

                                                                    image.gif编辑

传参:image.gif编辑

image.gif编辑

call指令将下一条指令的地址拿出压栈!image.gif编辑

image.gif编辑

                                                                  image.gif编辑

为Add函数准备栈帧!image.gif编辑

image.gif编辑

                                                                     ——By 作者:新晓·故知  整理+创作image.gif编辑

33h次:16进制的33h次image.gif编辑

image.gif编辑

image.gif编辑

image.gif编辑

                                             

image.gif编辑

形参对应的函数(子函数)计算:image.gif编辑

image.gif编辑

image.gif编辑

注:

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

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

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

image.gif编辑

image.gif编辑

返回:

image.gif编辑

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

image.gif编辑

                                                           image.gif编辑

image.gif编辑

image.gif编辑

                                                           image.gif编辑

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

image.gif编辑

                                                            image.gif编辑

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

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

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

image.gif编辑

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

image.gif编辑

image.gif编辑

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

解答:

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

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

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

传参是从右向左传!

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

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

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

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

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

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

image.gif编辑

                                                             

注:

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

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

image.gif编辑

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

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

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

相关文章
|
7天前
|
C语言
C语言学习笔记之初识字符串
C语言学习笔记之初识字符串
19 5
|
8天前
|
存储 机器学习/深度学习 编译器
C语言代码学习笔记
<编程精粹:编写高质量C语言代码> 读书笔记
|
8天前
|
文件存储 C语言
|
19天前
|
IDE 开发工具 C语言
C primer plus 学习笔记 第2章 C语言概述
C primer plus 学习笔记 第2章 C语言概述
|
19天前
|
存储 Unix 编译器
C primer plus 学习笔记 第1章 初识C语言
C primer plus 学习笔记 第1章 初识C语言
|
2月前
|
存储 安全 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
|
2月前
|
存储 编译器 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
|
2月前
|
存储 编译器 C语言
C语言:底层剖析——函数栈帧的创建和销毁
C语言:底层剖析——函数栈帧的创建和销毁
|
2月前
|
存储 编译器 C语言
C 语言函数栈帧的概念讲解
C 语言函数栈帧的概念讲解
|
1天前
|
Java C语言 C++
定义C语言的int main()函数
定义C语言的int main()函数