函数的调用过程(栈帧)

拿一段简单的代码为例:

#include <stdio.h>

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

程序调试的时候,查看调用堆栈:


不难发现:main函数在__tmainCRTStartup函数中调用;而__tmainCRTStartup函数是在mainCRTstartup中被调用。

栈是从高地址向低地址延伸的。每个函数的每次调用,都有它自己独立的一个栈帧,这个栈帧中维持着所需要的各种信息。寄存器ebp指向当前的栈帧的底部(高地址),寄存器esp指向当前的栈帧的顶部(低地址)。——“来自搜狗百科”

那么调用main函数,分配栈帧空间,栈帧维护如下:

接下来,有了这些铺垫,我对应汇编代码来说明:

1.先从main函数开始:



2.传参



接着执行call指令按F11:

再按F11:

进入Add函数:



接下来是返回部分:




最后,将30带回给c。

如有误,欢迎朋友们指出!







CTF(Capture The Flag)是一种信息安全竞赛,通常涉及一系列与安全相关的挑战和问题。在这些挑战中,函数调用的深入理解对于解决许多问题至关重要。 在计算机程序中,函数调用涉及到(Stack Frame)的创建和销毁。函数调用过程中用于存储函数参数、局部变量以及返回地址等信息的内存区域。具体来说,的结构通常包含以下几个部分: 1. 参数区域:存放函数调用时传递给函数的参数值。 2. 返回地址:函数执行完毕后,程序需要返回到的地址,通常是调用函数之后的指令地址。 3. 保存的寄存器:保存调用者上下文中的寄存器值,以便函数返回后能够恢复。 4. 局部变量区域:存放函数内部定义的局部变量。 5. 保存的指针(可选):一些系统会使用指针来引用当前的,方便函数调用和变量访问。 6. 顶指针:指向当前顶部的指针。 函数调用过程中,一般步骤如下: - 参数准备:调用者将参数准备好,按照约定的方式压入中。 - 调用指令:执行调用指令(如x86架构的`CALL`指令),该指令将返回地址压,并跳转到被调用函数的入口地址。 - 建立:被调用函数开始执行后,首先建立自己的,可能包括设置指针和局部变量等。 - 执行函数体:函数体内执行需要的操作,使用上的局部变量进行计算。 - 函数返回:当函数执行完毕准备返回时,清理局部变量,恢复之前保存的寄存器状态和顶指针,然后执行返回指令(如`RET`指令)回到调用者。 在CTF竞赛中,理解结构和函数调用机制对于逆向工程、二进制分析和漏洞利用等安全相关挑战尤为关键。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值