栈帧结构 (c语言)

一,前言

目前正在学习栈帧方面的知识但由于怕忘记,故在此进行整理,方便复习,记忆,也同时还借鉴了其他博主的一些文章和看法。鄙人只是一个小菜鸡,希望以下的内容可以为您提供一些帮助。

二,相关知识:

1,寄存器:

具有储存功能的离cpu最近的储存单元,速度最快

(1),ebp:栈底寄存器

(2),esp:栈顶寄存器

(3),pc指针:指向当前正在执行指令的下一条指令

(4),eax,ebx:通用寄存器

还有其他更多类型寄存器,在此不再赘述,望读者自行搜索了解。

下图:尤其是esp,ebp这两个寄存器中存放的地址(这两个地址用来维护函数栈帧)

原图链接:(18条消息) 栈帧详解——C语言进阶_乔乔家的龙龙的博客-CSDN博客_c语言栈帧

2,任何一个函数都有属于自己的ebp(栈底),esp(栈顶),但是内存中的ebp,esp只有一份;为了保证一个函数不会覆盖另一个函数的ebp,esp,调用时必须对原来的函数的ebp,esp进行保存,(因为ebp,esp永远指向当前函数最新的栈顶与栈底);栈是从地址减小的方向生长

3,函数调用时,相关的寄存器内容必须保存(目的是调用完之后恢复)

4,call指令的任务:

#call命令:在批处理脚本中,call命令用来从一个批处理脚本中调用另一个批处理脚本

1),跳转到被调用函数的入口处(通过调整pc指针完成)

2),保存当前正在进行执行指令的下一条指令的地址到栈中去

5,push:将数据到栈顶;pop:把栈顶数据拉出来放在指定寄存器中

6,形参实例化时从右往左的顺序进行

7,将数据压入栈顶时,先移动指针再放数据,保证栈顶指针永远指向一个有效的数据

#当进行插入操作时,既然想要插入,那就是找空位置,如果指针指向的是当前元素的位置,那这个位置就非空,就需要先对指针操作,让指针指向空位置,才能进行插入;如果指针指向的是栈顶或队尾下一个位置,那指针指向的位置是不是就是空的,是空的就插入,插入之后在移动指向空位置。同理,进行删除操作时,就是看指针指向的位置有没有元素,有元素就可以直接删除再移动,没元素就要先移动找到元素然后再进行删除操作。

8.调用函数时,先形成实参的临时变量,再执行call指令

9.

#include <stdio.h>
#include <windows.h>
int fun(int x,int y)
{
int c=0xcccccccc;
}
int main()
{
int a=0xaaaaaaaa;
int b=0xbbbbbbbb;
int ret=fun(a, b);
printf("you should running here\n");
system("pause");
return 0;
}

开始,寄存器ebp、esp分别指向main函数的栈底、栈顶(main函数是入口),pc指针指向main函数的代码区;

(1)定义变量a,b;反汇编:dword ptr [a],0AAAAAAAAh ,dword ptr [b],0BBBBBBBBh

(2)开始调用:但是调用之前要形参实例化形成临时变量:(注意形参从右往左进行实例化)

mov eax,dword ptr [b] :把变量b存到通用寄存器eax中

push eax :把eax中(b)压入堆栈中

mov ecx,dword ptr [a] :把变量b存到通用寄存器ecx中

push ecx :把ecx中(b)压入堆栈中

使用call指令开始调用函数:call @ILT+295(_fun) (0F9112Ch) ;注意call指令完成两个任务:(1)跳转到被调用函数的入口处(通过调整pc指针完成)

(3)保存当前正在执行指令的下一条指令的地址到栈中

add esp,8 :保存当前正在执行指令的下一条指令的地址到栈中

mov dword ptr [ret],eax :跳转到被调用函数的入口处

(4)这时已经来到fun函数:但是现在系统的ebp、esp还指向原来main函数的栈底和栈顶,显然我们应该马上修改二者的值:

push ebp :把ebp(main函数的栈底内容)中的内容压入栈顶

mov ebp,esp :把esp内容放到ebp中,所以上面先保存ebp内容;此时显示的栈底指向栈顶

sub esp,0CCh :栈顶向下移动

现在的栈底、栈顶所组成的部分为被调用函数的栈帧结构

(4)恢复栈帧结构:

mov esp,ebp :把ebp里内容复原给esp,恢复栈底

pop ebp :然后把栈顶内容返回给ebp,恢复栈顶

ret :恢复pc指针的指向(指向main函数的函数返回地址)

add esp,8 :栈顶向上移动,释放实参实例化的临时变量

10.内存分区

按照内存地址从高(0xffffffff)到低(0x00000000)的顺序排列,可分为5大分区:栈区 -> 堆区 -> 全局静态区 -> 常量区 -> 代码区

三,参考

链接: 栈帧详解_NeilZhy的博客-CSDN博客_栈帧

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值