c语言入门-函数栈帧

目录

函数栈帧概念

 分析函数栈帧


函数栈帧概念

函数栈帧:函数在每一次调用时,都会在栈空间开辟一段空间以供函数使用,这个空间被称为栈帧,栈帧中保持着函数所需要的各种信息。

寄存器:是cpu(中央处理器简称cpu,是计算机的运算核心和控制核心,是信息处理,程序运行的最终执行单元)内组成部分,用于存储的部件,可以用来暂时存指令,数据和地址。

win32系统提供了两个寄存器来维护函数栈帧。

⭕ESP:栈指针寄存器,它内部存放着一个指针,永远指向栈最上面一个栈帧的栈顶,即栈顶寄存器。

⭕EBP:基地指针寄存器,即栈底寄存器。

我们知道栈是由高地址向低地址生长的,即先使用高地址,后使用低地址。c语言入门-函数栈帧_第1张图片

 分析函数栈帧

#include
int Add(int x, int y)
 {
	int z = x + y;
		return z;
}
int main(){
	int a = 10;
	int b = 20;
	int ret = Add(a, b);
	printf("%d", ret);
	return 0;
}

通过这个代码我们来分析函数栈帧。在调试程序时查看调用堆栈:可以看出main函数其实是在mainCRTStartup函数中调用的。(在VS编译器中可以看出其实main函数是在_tmainCRTStartup函数中调用的,而_tmainCRTStartup函数是在mainCRTStartup中调用的。) 所以说main函数执行之前,先要为_tmainCRTStartup函数安排栈帧,后为mainCRTStartup函数分配栈帧。

c语言入门-函数栈帧_第2张图片

 调试窗口打开反汇编。

●main()函数被调用之前:_tmainCRTStartup函数栈帧

c语言入门-函数栈帧_第3张图片

●main()函数被调用之时:

//008B1930  push        ebp   将edp存入栈中,esp自动更新到栈顶,即edp空间顶部
//008B1931  mov         ebp,esp   将esp的值赋给edp

push:压栈,在栈中存入数字 mov:将后面的值赋给前面  sub:减法操作 lea:load effecyive address,加载有效地址  pop:出栈

  //008B1933  sub         esp,0E4h   esp减去16进制的数字,esp更新

c语言入门-函数栈帧_第4张图片

 //008B1939  push        ebx ebx压栈
 //008B193A  push        esi  esi压栈
 //008B193B  push        edi  edi压栈

c语言入门-函数栈帧_第5张图片

 //008B193C  lea         edi,[ebp-24h]      给edi加载有效地址
//008B193F  mov         ecx,9           //ecx空间大小
//008B1944  mov         eax,0CCCCCCCCh  //eax的内容更改
//008B1949  rep stos    dword ptr es:[edi] c语言入门-函数栈帧_第6张图片

  //00141950  call        00141316  
//    int a = 10;
//00141955  mov         dword ptr [ebp-8],0Ah  ,
在ebp-8 的位置上存入a
 //   int b = 20;
//0014195C  mov         dword ptr [ebp-14h],14h
在ebp-14 的位置上存入b

c语言入门-函数栈帧_第7张图片

 //00141963  mov         eax,dword ptr [ebp-14h]  
//00141966  push        eax 
压栈压入b
//00141967  mov         ecx,dword ptr [ebp-8]  
//0014196A  push        ecx 
 压栈压入a

c语言入门-函数栈帧_第8张图片

 调用Add函数

0014196B  call        001413B6  
00141970  add         esp,8  

调用call指令时,里面保存了call指令下一条指令(add)的地址。

到达call指令,按F11进入add函数的反汇编代码

//00141890  push        ebp
//00141891  mov         ebp, esp
//00141893  sub         esp, 0CCh
//00141899  push        ebx
//0014189A  push        esi
//0014189B  push        edi
//0014189C  lea         edi, [ebp - 0Ch]
//0014189F  mov         ecx, 3
//001418A4  mov         eax, 0CCCCCCCCh
//001418A9  rep stos    dword ptr es : [edi]

为add函数开辟空间并初始化为0cccccccc。

c语言入门-函数栈帧_第9张图片

 //int z = x + y;
//001418B5  mov         eax, dword ptr[ebp + 8]
//001418B8  add         eax, dword ptr[ebp + 0Ch]
//001418BB  mov         dword ptr[ebp - 8], eax
//return z;
//001418BE  mov         eax, dword ptr[ebp - 8]

c语言入门-函数栈帧_第10张图片

  把结果放到寄存器中,不会因为函数结束了导致值被销毁。

c语言入门-函数栈帧_第11张图片

add函数销毁之后,main函数打印结果c语言入门-函数栈帧_第12张图片

c语言入门-函数栈帧_第13张图片

你可能感兴趣的:(c语言)