浅谈C语言的栈帧

本文探讨了C语言中的栈帧概念,特别是在栈区的使用。栈帧从大到小进行分配,通过代码示例解释了栈帧的形成、构造以及如何影响参数传递。文章还提到了汇编语言在平衡栈帧结构中的作用,适合C语言初学者了解栈帧工作原理。
摘要由CSDN通过智能技术生成

    C语言中分为几个区,常用的区按地址从小到大分布是:代码区-静态全局区-堆区-全局共享区-栈区,静态区从小到大是已初始化静态区,未初始化静态区。而我们经常使用的区域是栈区,而栈帧就是在栈区,而且有一点是和其他区有一个明显的分别,就是栈区内部是从大到小使用的。

    基本的栈帧就是下图这样的:

     贴上使用的代码:

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<windows.h>

int fun(int x,int y)
{
	int c = 0xcccccccc;
	int *p = &x;
	p++;
	*p = 0xdddddddd;
	printf("after :b = %x\n", y);
	return c;
}

int main()
{
	int a = 0xaaaaaaaa;
	int b = 0xbbbbbbbb;
	int ret = fun(a, b);
	printf("2333333333\n");
	system("pause");
	return 0;
}

    然后我们来详细讲一下栈帧的形成和构造。


    到这,main函数的栈帧区间就已经创建好,并且把fun函数的形参实体化在main中,且保存了call指令的下一指令的地址,便于fun函数的返回。


    现在的栈帧结构大概就是这样:


        依据此图,我们很容易可以理解通过fun函数的第一个形参(并不是第一个实体化的,而是fun函数括号里面从左到右的第一个参数)可以更改第二个参数的值,而不通过第二个参数来完成。

        最后,就是fun的返回和main的返回以及esp、ebp归回到main的地方

    借用这种方式,我们还可以给fun函数里面用x的地址实现调用函数

#define _CRT_SECURE_NO_WARNINGS

#include<stdio.h>
#include<windows.h>

void *main_ret = NULL;

void bug()
{
	int flag = 0;
	int *p = &flag;
	p += 4;
	printf("you see a little bug,hahahhhhh\n");
	Sleep(2000);
	printf("what can you do?\n");
	Sleep(2000);
	printf("nothing\n");
	Sleep(2000);
	printf("just wait\n");
	Sleep(5000);
	*p = main_ret;
	printf("now,see again\n");
	Sleep(2000);
}

int fun(int x,int y)
{
	int c = 0xcccccccc;
	int *p = &x;
	p--;
	main_ret = *p;
	printf("what do you see?\n");
	*p = (int)bug;
	return c;
}

int main()
{
	int a = 0xaaaaaaaa;
	int b = 0xbbbbbbbb;
	int ret = fun(a, b);
	_asm
	{
		sub esp, 4
	}
	printf("2333333333\n");
	system("pause");
	return 0;
}
    代码就是这个样子,根据第一幅栈帧图的结构,使用fun函数中第一个参数的地址,从而达到调用函数的目的。

    并且,可以看到,main中用 汇编语言将esp+4,是因为:main用call调用fun函数,fun用地址调用bug函数,bug函数返回fun,fun返回main,main自己也 有返回值。所以此时ret指令返回了三次,而call指令只 调用了两次,所以esp多出栈一次,所以要给esp+4,平衡栈帧结构。



本人为初学者,对汇编语言和编译器的运行方式并不是很精通,如果各位读者发现以上内容有错误问题,请在评论区回复,我会在第一时间修正。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值