C语言——函数栈帧的创建和销毁(一)

简介: C语言——函数栈帧的创建和销毁

Hello,好久没有写博客了,前两份都是之前写的,看来最近有点懈怠,最近也得快点找回学习的状态,那今天开始我们新的讲解

在我们刚开始学习C语言的时候,不知道大家有没有困惑,比如我们在使用局部变量的时候,他是怎么创建的呢

  • 为什么局部变量的值是随机值?
  • 函数是怎么传参的?传参的顺是怎样的?
  • 形参和实参是什么关系?
  • 函数调用是怎么做的?
  • 函数在调用结束后是怎么返回的?

带着这些疑问,我们开始来介绍函数栈帧的创建和销毁

先给大家普及一个知识,就是我们的寄存器

要了解我们的函数栈帧,最主要的是ebp和esp,这两个寄存器存放的是我们的地址,是来维护函数栈帧的。在我们函数调用的时候,每一次都会创建函数栈帧来维护这个函数。

#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;
}

我们先使用的是main函数,ebp,和esp就是来维护这个函数栈帧的,ebp我们可以认为栈低指针,esp我们可以认为栈顶指针,而我们下一次函数调用的时候是在上面开辟函数栈帧,每一次调用都会开函数调用

其实我们的main函数也是被调用的

下面我们看函数的一个反汇编

因为我们的main函数也是被调用的,所以在调用之前也会开辟一个栈帧,我么来看一下这个图

我们在看下一条指令

因为我们在调用main函数的时候进行压栈,压入一个ebp,ebp中存放的是下面那个ebp的地址,而指令中的mov,就是将esp的值给了ebp,所以其实现在esp和ebp应该指向同一个地址

图是这样的

我们在看下一步

所以我们的esp指向上面的一个位置

那就意味着现在我们给main函数开辟了一个空间,这个空间其实很大的

继续看下面指令

我们不用关心这个值是有什么用,其实也是代表寄存器的,我们先不用关心,只要知道我们push三个值进去。

压栈进去,esp也变了

下一条指令更像是初始化,其实应该是下面的三条指令,首先看我们的lea,其实它的意思就是load effective address,是加载有效地址的意思,就是将后面的【ebp-0E4h】加载到edi里面去,edi是什么,它就是我们刚刚压栈进去的值

啥意思,就是相当于在栈帧中初始化


相关文章
|
6月前
|
存储 安全 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-2
|
6月前
|
存储 编译器 C语言
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
深度剖析c语言程序 -- 函数栈帧的创建和销毁(纯肝货)-1
|
6月前
|
存储 编译器 程序员
C语言之反汇编查看函数栈帧的创建与销毁(一)
C语言之反汇编查看函数栈帧的创建与销毁(一)
C语言之反汇编查看函数栈帧的创建与销毁(一)
|
3月前
|
存储 C语言
【C语言】——函数栈帧的创建与销毁
【C语言】——函数栈帧的创建与销毁
|
6月前
|
存储 编译器 C语言
C语言:底层剖析——函数栈帧的创建和销毁
C语言:底层剖析——函数栈帧的创建和销毁
|
6月前
|
存储 编译器 程序员
C语言之反汇编查看函数栈帧的创建与销毁(二)
C语言之反汇编查看函数栈帧的创建与销毁(二)
|
11月前
|
编译器 C语言
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)(下)
函数栈帧的创建和销毁(以C语言代码为例,汇编代码的角度分析)
|
1月前
|
C语言 C++
C语言 之 内存函数
C语言 之 内存函数
34 3
|
8天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
25 6
|
28天前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
35 10