底层原理——函数栈帧创建于销毁(图文详解)

目录

前言

一、寄存器

二、演示代码(c语言)

二、汇编逐一分析函数的创建

1.main函数空间的开辟

2.局部变量的创建​编辑

3.Add函数的创建

3.1形参的创建​编辑

3.2Add函数空间开辟

3.3实现函数内功能

三、函数栈帧的销毁


前言

相信大家在初学c语言时都有很多的点不是很清楚,比如为什么函数传参时形参改变不了实参,为什么代码会出现烫烫烫,局部变量是怎么创建的?等等问题,带着这些问题,我们今天来研究研究函数的栈帧创建于销毁。

一、寄存器

寄存器是集成于cpu上的独立存储空间。

我们想要了解函数的栈帧创建于销毁,得先了解一下部分寄存器的名称于功能。

eax,ebx,ecx,edx等是用于存储数据的寄存器

ebp,esp这两个寄存器是用来存放地址的,这2个地址是用于维护函数栈帧的。

当某个函数被调用时,esp和ebp就会来维护这个函数。

二、演示代码(c语言)

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

我将对如上代码分析,带你理解函数栈帧

二、汇编逐一分析函数的创建

1.main函数空间的开辟

esp和ebp先维护调用main函数的函数

 

接下来开始调用main函数:

逐一分析这些汇编代码

1.将ebp的值压入栈顶

2.将esp赋给ebp的位置

3.将esp中的值减去0E4h,esp是指针,减去0E4h后得到一个新的地址(栈区中数据是由高地址到低地址开辟空间,所以esp往栈顶移动)

4.将ebx的值压入栈顶

5.将esi的值压入栈顶

6.将edi的值压入栈顶

7.lea(load effective address) 将(ebp-0E4h)的有效地址加载到edi去

8.将9赋给ecx

9.将0CCCCCCCCh赋给eax

10.从(ebp-0E4h)地址处开始的39h的dword(4字节)的所有的值改为0CCCCCCCCh

如下图:

2.局部变量的创建

1.将0Ah赋给(ebp-8)的4个字节处

2.将14h赋给(ebp-14h)的4个字节处

3.将0赋给(ebp-20h)的4个字节处

3.Add函数的创建

3.1形参的创建

1.将(ebp-14h)地址处的值赋给eax

2.栈顶压入eax

3.将(ebp-8)地址处的值赋给ecx

4.栈顶压入ecx

3.2Add函数空间开辟

这条指令是调用Add函数的

在栈顶压入00c2144B的下一条指令00c21450,以便调用完Add函数以后能够继续下一步操作

这接下来的操作和开辟main函数一样,类比即可。

3.3实现函数内功能

1.将(ebp-8)的值改为0

2.将x值 赋给eax

3.将y值与eax相加并赋给eax

4.将eax的值赋给(ebp-8)

5.将(ebp-8)的值赋给eax寄存器(因为ebp-8这块空间随着Add函数栈帧的销毁也会随之还给操作系统,所以需要用eax寄存器来保存z的值,使得返回main函数后能够使用z的值)

三、函数栈帧的销毁

1.弹出edi

2.弹出esi

3.弹出ebx

4.将ebp的值赋给esp

5.弹出ebp

最终回到了最初调用Add的状态。

  • 9
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

墨染萧然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值