当前位置:网站首页>函数栈帧的创建和销毁
函数栈帧的创建和销毁
2022-07-03 15:16:00 【小蜗牛向冲】
前言
对于编程这件事来说,函数的调用在代码中是必不可少的,那函数在内存中到底是如何创建和销毁的,下面我将写一个简单的函数为大家演示。
为了更加清楚的理解函数栈帧的创建和销毁,将使用VS2013为大家演示(不同版本的vs演示的效果可能不同),
一 认识寄存器
根据百度百科介绍,寄存器是中央处理器内的组成部分。 寄存器是有限存贮容量的高速存贮部件,它们可用来暂存指令、数据和地址。 简单来说, 寄存器就是存放东西的 。 从名字来看,跟火车站寄存行李的地方好像是有相似。
在本次函数栈帧的创建和销毁要到寄存器有:
eax
ebx
ecx
edx
esp:栈顶指针
ebp:栈底指针
对于这四个寄存器知道有这些寄存器即可,对于esp和ebp是用来维护函数的。
二 Add函数栈帧的创建和销毁
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
int Add(int x, int y)
{
int c = 0;
c = x + y;
return c;
}
int main()
{
int a = 10;
int b = 20;
int ret = Add(a, b);
printf("ret = %d\n", ret);
return 0;
}
在调试之前,我们要想一个问题,main函数是程序的入口,但mian函数也是一个函数,那么它又是被什么函数调用的呢?
我们可以调用堆栈进行观察:
这时我们发现main函数是被__tmainCRTStartup函数调用,而__tmainCRTStartup函数又是被mainCRTStartup函数调用。
main函数的调用
int main()
{
00881410 push ebp
00881411 mov ebp,esp
00881413 sub esp,0E4h
00881419 push ebx
0088141A push esi
0088141B push edi
0088141C lea edi,[ebp+FFFFFF1Ch]
00881422 mov ecx,39h
00881427 mov eax,0CCCCCCCCh
0088142C rep stos dword ptr es:[edi]
int a = 10;
0088142E mov dword ptr [ebp-8],0Ah
int b = 20;
00881435 mov dword ptr [ebp-14h],14h
int ret = Add(a, b);
0088143C mov eax,dword ptr [ebp-14h]
0088143F push eax
00881440 mov ecx,dword ptr [ebp-8]
00881443 push ecx
00881444 call 008810E1
00881449 add esp,8
0088144C mov dword ptr [ebp-20h],eax
printf("ret = %d\n", ret);
0088144F mov esi,esp
00881451 mov eax,dword ptr [ebp-20h]
00881454 push eax
printf("ret = %d\n", ret);
00881455 push 885858h
0088145A call dword ptr ds:[00889114h]
00881460 add esp,8
00881463 cmp esi,esp
00881465 call 0088113B
return 0;
0088146A xor eax,eax
}
0088146C pop edi
0088146D pop esi
0088146E pop ebx
0088146F add esp,0E4h
00881475 cmp ebp,esp
00881477 call 0088113B
0088147C mov esp,ebp
0088147E pop ebp
0088147F ret
这些都是调用main函数的准备工作
其中的push ebp指的是压栈,就是把ebp中的指向的值给ebp。
mov ebp,esp.这里是指把esp中的值给ebp
sub esp,0E4h 是指把esp中的值减去0E4h。
push ebx
push esi
push edi压栈三个值
lea edi,[ebp-0E4h]
mov ecx,39h
mov eax,0CCCCCCCCh
rep stos dword ptr es:[edi]这些反汇编就是将mian函数的值,从edi开始下面初始化39次,都初始化为CCCCCCCC
所以,为什么有时候会打印出 烫烫烫烫烫烫,因为变量在初始化时内存里面放的CCCCCC的值。
int a = 10;
mov dword ptr [ebp-8],0Ah这里代码的意思是将a的值放到ptr地址处
mov dword ptr [ebp-8],0Ah
int b = 20;同理是将b的值放到[ebp-8]的地址处
下面就进行函数的传参,那函数传参又是在内存中进行的呢?
mov eax,dword ptr [ebp-14h]
这里就是将[ebp-14h](b的值)中的值放到eax中
push eax
将eax进行压栈
mov ecx,dword ptr [ebp-8]
这里就是将[ebp-14h](a的值)中的值放到ecx中
push ecx
将ecx进行压栈
下面就进行函数调用
00881444 call 008810E1
为了调用的函数参数能够返回,call指令下一条指令的地址。
下面进入到Add函数中的反汇编。
下面这些又是在干什么呢?其实是在维护Add函数的栈帧。
同main函数的维护一样,都是要函数栈帧的准备工作,分配内存,初始化内存。CCCCCCCCCCCCC
int Add(int x, int y)
{
008813C0 push ebp
008813C1 mov ebp,esp
008813C3 sub esp,0CCh
008813C9 push ebx
008813CA push esi
008813CB push edi
008813CC lea edi,[ebp+FFFFFF34h]
008813D2 mov ecx,33h
008813D7 mov eax,0CCCCCCCCh
008813DC rep stos dword ptr es:[edi]
int c = 0;
008813DE mov dword ptr [ebp-8],0
c = x + y;
008813E5 mov eax,dword ptr [ebp+8]
008813E8 add eax,dword ptr [ebp+0Ch]
008813EB mov dword ptr [ebp-8],eax
return c;
008813EE mov eax,dword ptr [ebp-8]
那函数的值又是怎么返回的呢?形参不是会销毁吗?
mov eax,dword ptr [ebp-8]
这里是将[ebp-8](30)的值保持在eax中。
008813F1 pop edi
008813F2 pop esi
008813F3 pop ebx
008813F4 mov esp,ebp
008813F6 pop ebp
008813F7 ret那这些又是指的是什么?
pop指的是出栈的意思,使得esp不断加加。
其中的mov esp,ebp是将ebp的值给esp,在 pop ebp 这样esp和ebp维护的空间重新指向main函数。ret是回到函数调用,call指令的下一个地址。
这样我们就是完成了main函数的创建和Add函数创建和销毁。而main函数的销毁和Add函数的销毁是类似的。
下面我们来回答几个问题,来运用我们今天学习的。
1 局部变量是如何创建的?
首先为函数分配好空间,在为函数初始化,最后在为局部变量在分配好的空间中,分配好地址。
2 为什么局部变量不初始化内容是随机的?
因为我们在为函数初始化的时,就是初始化的随机值。
3 函数调用时参数时如何传递的?传参的顺序是怎样的?
将参数存入eax寄存器中,传参的顺序是从右到左。
4函数调用的结果是如何返回的?
通过call指令记住下一条指令的地址,从而找到main函数,在通过寄存器将返回值带到,main函数中。
总结
通过对Add函数创建和销毁的理解,我们相信大家对于函数在内存中的分配会有更加深刻的理解。在下面的博客中,博主会给大家带来更多知识,希望大家不要错过噢!
边栏推荐
- Relationship between truncated random distribution and original distribution
- Using multipleoutputs to output multiple files in MapReduce
- Functional modules and application scenarios covered by the productization of user portraits
- Summary of concurrent full knowledge points
- Introduction to redis master-slave, sentinel and cluster mode
- Chapter 04_ Logical architecture
- What is label encoding? How to distinguish and use one hot encoding and label encoding?
- 解决pushgateway数据多次推送会覆盖的问题
- Global and Chinese markets for infrared solutions (for industrial, civil, national defense and security applications) 2022-2028: Research Report on technology, participants, trends, market size and sh
- Yolov5 series (I) -- network visualization tool netron
猜你喜欢
第04章_逻辑架构
Jvm-02-class loading subsystem
视觉上位系统设计开发(halcon-winform)-5.相机
Yolov5 series (I) -- network visualization tool netron
Kubernetes advanced training camp pod Foundation
视觉上位系统设计开发(halcon-winform)-3.图像控件
Dataframe returns the whole row according to the value
Influxdb2 sources add data sources
5.2-5.3
Introduction to redis master-slave, sentinel and cluster mode
随机推荐
Puppet automatic operation and maintenance troubleshooting cases
MySQL reports an error: [error] mysqld: file '/ mysql-bin. 010228‘ not found (Errcode: 2 “No such file or directory“)
Kubernetes will show you from beginning to end
使用JMeter对WebService进行压力测试
Global and Chinese markets for infrared solutions (for industrial, civil, national defense and security applications) 2022-2028: Research Report on technology, participants, trends, market size and sh
App global exception capture
【pytorch学习笔记】Datasets and Dataloaders
Tencent internship interview sorting
Besides lying flat, what else can a 27 year old do in life?
Kubernetes - yaml file interpretation
[transform] [practice] use pytoch's torch nn. Multiheadattention to realize self attention
Kubernetes帶你從頭到尾捋一遍
High quality workplace human beings must use software to recommend, and you certainly don't know the last one
Search in the two-dimensional array of leetcode sword offer (10)
视觉上位系统设计开发(halcon-winform)-1.流程节点设计
高并发下之redis锁优化实战
[pytorch learning notes] transforms
Mysql报错:[ERROR] mysqld: File ‘./mysql-bin.010228‘ not found (Errcode: 2 “No such file or directory“)
redis缓存穿透,缓存击穿,缓存雪崩解决方案
Global and Chinese markets for sterile packaging 2022-2028: Research Report on technology, participants, trends, market size and share