函数栈帧(上)

一 函数栈帧的创建及销毁

1 什么是函数栈帧?

1 什么是函数?
函数就是对于一个独立功能的抽象。
2 什么是函数栈帧?
函数栈帧是函数调用时在栈区中临时开辟的一块内存空间
3 这些空间的作用是什么?
存放函数参数和函数返回值
存放临时变量
保存上下文信息(寄存器)

2 理解函数栈帧能够解决什么问题呢?

1 局部变量是如何创建的?
2 为什么局部变量不初始化内容是随机的?
3 函数调用时参数时如何传递的?传参的顺序是怎样的?
4 函数的形参和实参分别是怎样实例化的?
5 函数的返回值是如何带会的?
这五个问题都会在文章的最后意义解答

3 函数栈帧的创建和销毁解析

1 什么是栈区?
就是那些由编译器在需要的时候分配,在不需要的时候自动清除变量的存储区
2 什么是压栈?什么是出栈?
压栈:向栈区中添加一个元素
出栈:从栈区中删除一个元素
3 栈区原则 先进后出

二 认识相关寄存器和汇编指令

1 预备知识

1 寄存器的概念:寄存器是CPU内部用来存放数据的一些小型存储区域,用来暂时存放参与运算的数据和运算结果
重点是 1 在cpu中
2 暂时存放参与运算的数据和运算结果

2 相关寄存器

eax:通用寄存器,保留临时数据,常用于返回值
ebx:通用寄存器,保留临时数据
ebp:栈底寄存器
esp:栈顶寄存器
eip:指令寄存器,保存当前指令的下一条指令的地址

这里我们暂时只需要记住ebp栈底寄存器 和esp栈顶寄存器就好

3 相关汇编命令

mov:数据转移指令
push:数据入栈,同时esp栈顶寄存器也要发生改变
pop:数据弹出至指定位置,同时esp栈顶寄存器也要发生改变
sub:减法命令
add:加法命令
call:函数调用,1. 压入返回地址 2. 转入目标函数
jump:通过修改eip,转入目标函数,进行调用
ret:恢复返回地址,压入eip,类似pop eip命令

4 预备知识

  1. 每一次函数调用,都要为本次函数调用开辟空间,就是函数栈帧的空间。
  2. 这块空间的维护是使用了2个寄存器: esp和 ebp ebp记录的是栈底的地址esp记录的是栈顶的地址。

函数调用堆栈演示代码:

#include <stdio.h>

int Add(int x, int y)
{
    int z = 0;
    z = x + y;
    return z;
}

int main()
{
    int a = 3;
    int b = 5;
    int ret = 0;
    ret = Add(a, b);
    printf("%d\n", ret);
    return 0;
}

 2 准备环境

这段代码,如果我们在VS2019编译器上调试,调试进入Add函数后,我们就可以观察到函数的调用堆栈 (右击勾选【显示外部代码】),如下图:

函数调用堆栈是反馈函数调用逻辑的,那我们可以清晰的观察到, main 函数调用之前,是由 invoke_main 函数来调用main函数。
在 invoke_main 函数之前的函数调用我们就暂时不考虑了。

那我们可以确定, invoke_main 函数应该会有自己的栈帧, main 函数和 Add 函数也会维护自己的栈 帧,每个函数栈帧都有自己的 ebp和 esp来维护栈帧空间。
那接下来我们从main函数的栈帧创建开始讲解

为了让我们研究函数栈帧的过程足够清晰,不要太多干扰,我们可以关闭下面的选项,让汇编代码中排 除一些编译器附加的代码:

 转到反汇编

int main()
{
//函数栈帧的创建

00BE1820	push	ebp
00BE1821	mov	ebp,esp
00BE1823	sub	esp,0E4h
00BE1829	push	ebx
00BE182A	push	esi
00BE182B	push	edi
00BE182C	lea	edi,[ebp-24h]
00BE182F	mov	ecx,9
00BE1834	mov	eax,0CCCCCCCCh
00BE1839	rep stos	dword ptr es:[edi]
//main函数中的核心代码
int a = 3;
00BE183B  mov         dword ptr [ebp-8],3
int b = 5;
00BE1842  mov         dword ptr [ebp-14h],5
int ret = 0;
00BE1849  mov         dword ptr [ebp-20h],0
ret = Add(a, b);
00BE1850  mov         eax,dword ptr [ebp-14h]
00BE1853  push        eax
00BE1854  mov         ecx,dword ptr [ebp-8]
00BE1857  push        ecx
00BE1858  call        00BE10B4
00BE185D  add         esp,8
00BE1860  mov         dword ptr [ebp-20h],eax
printf("%d\n", ret);
00BE1863  mov         eax,dword ptr [ebp-20h]
00BE1866  push        eax
00BE1867  push        0BE7B30h
00BE186C  call        00BE10D2
00BE1871  add         esp,8
return 0;
00BE1874  xor         eax,eax
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值