函数栈帧(下)

简介: 函数栈帧(下)

一 函数栈帧的创建


我们首先来一步步解析上一篇文章的汇编代码


00BE1820  push        ebp    //把ebp寄存器中的值进行压栈,此时的ebp中存放的是
invoke_main函数栈帧的ebp,esp-4
00BE1821  mov         ebp,esp  //move指令会把esp的值存放到ebp中,相当于产生了main函数的
ebp,这个值就是invoke_main函数栈帧的esp
00BE1823  sub         esp,0E4h  //sub会让esp中的地址减去一个16进制数字0xe4,产生新的
esp,此时的esp是main函数栈帧的esp,此时结合上一条指令的ebp和当前的esp,ebp和esp之间维护了一 个块栈空间,这块栈空间就是为main函数开辟的,就是main函数的栈帧空间,这一段空间中将存储main函数 中的局部变量,临时数据已经调试信息等。
00BE1829  push        ebx  //将寄存器ebx的值压栈,esp-4
00BE182A  push        esi  //将寄存器esi的值压栈,esp-4
00BE182B  push        edi  //将寄存器edi的值压栈,esp-4
//上面3条指令保存了3个寄存器的值在栈区,这3个寄存器的在函数随后执行中可能会被修改,所以先保存寄 存器原来的值,以便在退出函数时恢复。


9be406e13da347b7b9a5a462838847b2.png

6b41b86596f34c70b1383dad182305e8.png

b09a34b62c75439e8fe8ba8a7b4567d0.png


7791ede083fe40d0a549ad170a5765af.png


b8f52a603a30427ca1a0e6700a7f4b0c.png


上面的这段代码最后4句,等价于下面的伪代码:

edi = ebp-0x24; ecx = 9; 
eax = 0xCCCCCCCC; 
for(; ecx = 0; --ecx,edi+=4)
 { 
 *(int*)edi = eax;
  }


二 小知识:烫烫烫烫


#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
  char arr[20];
  printf("%s", arr);
  return 0;
}


下面这段代码之所以会发出来烫烫烫烫的原因是因为函数初始化的值为occcccccch

oxcccc的文本就是“烫”

321cffd6ed2a448fb65a9249ca1235a2.png


三 函数中临时变量的创建


6fe5e6158e9d47a6bcb58881acb77593.png


四 Add()函数的调用


77d6d4ab252d4d758ba72c63b634f218.png

1986a1ec084f43cd8ec3a14485c28c7c.png

函数调用过程


1be23655d43f44a98159148bbe23eaf7.png


call 指令是要执行函数调用逻辑的,在执行call指令之前先会把call指令的下一条指令的地址进行压栈

操作,这个操作是为了解决当函数调用结束后要回到call指令的下一条指令的地方,继续往后执行。

ad0376fa28084523aa7ec0b03a5198b2.png


352a317e4a604701a152a47301a12d8f.png


函数栈帧的创建和压栈和main()函数是大差不差的

通过观察x y的值我们可以更加深刻的理解 为什么函数的形参是实参的零食拷贝这句话

当最后计算出z的结果的时候

将z存放到寄存器当中 之后开始销毁add()的栈帧

d124a83fb9a241bfb97b634e194a6ccb.png


五 函数栈帧的销毁


02ba62f10c9443ae9a58c5452fdafb66.png


六 回答文章最初的问题


1 局部变量是如何创建的?

首先函数创建一个栈帧空间 初始化好之后空间之后再为局部变量分配好空间

2 为什么局部变量不初始化内容是随机的?

因为里面的值是我们随机放进去的 初始化后随机值就会被我们覆盖

3 函数调用时参数时如何传递的?传参的顺序是怎样的?

当调用函数之前 从右向左开始压栈

4 函数的形参和实参分别是怎样实例化的?

形参是实参的一份临时拷贝

形参在函数调用之后进行实例化

实参在函数中进行实例化

5 函数的返回值是如何带会的?

通过寄存器带回

相关文章
|
17天前
|
编译器 容器
关于函数栈帧的创建和销毁
关于函数栈帧的创建和销毁
|
1月前
|
容器
函数栈帧的创建和销毁介绍
函数栈帧的创建和销毁介绍
19 0
|
8月前
|
存储
函数栈帧的创建和销毁(下)
函数栈帧的创建和销毁(下)
36 0
|
4月前
|
编译器 程序员 C语言
函数栈帧的创建与销毁(超详解)
函数栈帧的创建与销毁(超详解)
63 0
|
5月前
|
存储 缓存 编译器
函数栈帧的创建与销毁
函数栈帧的创建与销毁
24 0
|
5月前
|
存储 C语言 C++
你知道函数栈帧的创建和销毁吗?
你知道函数栈帧的创建和销毁吗?
54 0
|
8月前
|
存储 编译器
函数栈帧深度剖析(一篇带你牢牢掌握函数栈帧)(二)
函数栈帧深度剖析(一篇带你牢牢掌握函数栈帧)(二)
65 0
|
8月前
|
存储 机器学习/深度学习 编译器
函数栈帧深度剖析(一篇带你牢牢掌握函数栈帧)(一)
函数栈帧深度剖析(一篇带你牢牢掌握函数栈帧)(一)
167 0
|
9月前
|
存储 编译器 C语言
C/函数栈帧
C/函数栈帧
|
8月前
|
存储 编译器
函数栈帧的创建和销毁(上)
函数栈帧的创建和销毁
37 0