栈帧相关知识总结

    在学习栈帧相关知识前,我们需要明确一些知识点,那就是在电脑中我们的地址空间是以什么样的方式存在的,在这里我们可以用一张图片表示:

栈和堆的存储方式:

栈(stack)的存储方式是自上而下的,先入后出的方式。生长方式往下生长

堆(heap)的存储方式是自下而上的,先入先出的方式,生长方式往上生长

在观察完如图所示的图片之后,我们在开始栈帧的研究操作之前,我们先来明确一些基本的概念:

我们知道每一次函数的调用都是一个过程,这个过程我们通常称之为:函数的调用过程,这个过程要为函数开辟栈空间,用于本次函数的调用中临时变量的保存,现场保护,这块栈空间我们称之为:函数栈帧。

栈帧的维护我们必须了解ebp和esp两个寄存器。在函数的调用过程中这两个寄存器存放了维护这个栈的栈底和栈顶指针。

ebp存放了指向函数栈帧栈底的地址

esp存放了指向函数栈帧栈顶的地址

eip(程序计数器):当前正在执行的指令的下一条指令的地址

从栈顶入栈称为push,从栈底出栈叫做pull。

接下来我们编写一段代码,并通过对应他的汇编过程来研究栈帧。


在输入完代码之后,我们通过观察我们的内存,寄存器,和call(调用堆栈)来观察栈帧的整个过程


我们通过watch来观察变量的地址,内容

int a的地址为00402078   

我们指针经过pull操作入栈,存入ebp-4,int b的地址为0040107f,存入ebp-8,他们的地址之差是4,说明了栈的生长方向是向下的,从高地址向低地址生长。,然后进行ret=Add(a,b)操作,在这里,我们要知道在第十六行eip指向的地址是00401086,而Add的地址就是00401086,这就说明了经过eip操作,接下来跳转到了Add函数,在Add函数内进行相加操作,接下来我们用一张示意图表示栈帧操作过程:

通过示意图我们可以得出一个结论:在函数调用参数的过程(形参实例化)中,是从右往左调用的,因为是先调用了b再调用a,与变量的创建刚刚是相反的。而且栈帧的形成过程就是一个通过指针修改地址,返回值地址的过程,从而由main函数到Add函数再到main函数的过程。在这个过程中eip起到了巨大的作用,因为eip记录了当前执行的指令的下一条指令的地址,所以才能够通过指针进行地址的跳转。我们可以理解为栈帧就是一个不断地通过改变地址进行函数操作的过程。

猜你喜欢

转载自blog.csdn.net/sd116460/article/details/80259192
今日推荐