函数栈帧相关知识的理解

本文详细解析了C语言中局部变量的创建、函数参数传递机制(包括传参顺序和形实参关系)、以及在VS2013中的函数栈帧维护过程,以main函数和Add函数为例,展示了寄存器的角色和栈操作,如push和pop。
摘要由CSDN通过智能技术生成

本部分内容旨在帮助学习C语言函数部分理解更加深刻

一.困惑内容:

1.局部变量是怎样创建的

2.为什么局部变量是随机值

3.函数是怎么传参的,传参的顺序是怎样的

4.形参和实参是什么关系

5.函数调用是怎么做的

6.函数调用是结束后怎么返回的

不同编译器下会有差异,本案例以vs2013为例

1.什么是函数栈帧

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

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

如该代码中,main函数就是一次函数调用,在调用main函数时会在栈区开辟一块空间,该空间称为main函数的函数栈帧。

2.寄存器

(压栈push:给栈顶放一个元素      出栈pop:从栈顶删除一个元素)

计算机中存在寄存器:eax,ebx,ecx,edx,ebp,esp。而ebp,esp这两个寄存器中存放的是地址,这两个地址是用来维护函数栈帧的。

2.1 怎样来维护函数栈帧

ebp栈底指针,esp栈顶指针,调用哪个函数,寄存器就在维护哪个函数。他俩之间的空间就是这次调用的函数栈帧。

1.在vs2013中,main函数也是被其他函数调用的(__tmainCRTStartup),该函数被mainCRTStarup调用,在调用main函数时,要先进行压栈指令(push),将ebp压到esp。

2.之后执行mov指令,将ebp的指向esp的地址。

3.再执行sub指令,改变esp指向的地址,两个寄存器中间的空间,就是给main函数开辟的空间。

4.然后在顶上zz的执行三次压栈push,将ebx,esi,edi三个值压进去。

5.再执z行加载指令(lea),将一个有效地址加载到edi中,然后将下边的四字节数字全部初始化(为main函数开辟的空间)成cc cc cc cc。

6.将a的值放在ebp-8处,如果未初始化,随机值的产生来自于函数函数栈帧中的cc cc cc cc。

7.执行call指令,将函数下面的指令保存。

8.在将两个值从右向左压栈到顶上(传参)。

9.再执行创建Add函数的函数栈帧。

10.在还没有传参时,就将两个参数压栈到栈顶(形参是实参的一份临时拷贝),使用时直接调用。

因为临时拷贝到栈顶,所以形参的改变不影响实参。

11.经过计算后,将z的值放在eax当中,因为出了函数之后,函数会销毁。

12.然后执行出栈(pop),将函数调用销毁。移动ebp,esp。

13.最后执行ret指令,回到call的下一条指令继续执行。.

  • 8
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值