栈帧详情转载

Posted 两片空白

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了栈帧详情转载相关的知识,希望对你有一定的参考价值。

栈帧详解

我们知道,栈帧又称 过程活动记录,主要用于记录函数调用过程中的一些 局部变量和中间数据
下面,我们用一个简单的程序的汇编过程来分析程序在内存中的存储情况。

主函数的汇编过程:


首先,我们都知道每一个栈帧都有其自己的栈底指针ebp和栈顶指针esp。每一个函数的每一次运行都需要在栈区中开辟出一个栈帧,可是一个CPU中的栈帧不可能无限的增加,所以,当有新的栈帧出现时,原先的栈帧的ebp和esp就被新开辟的栈帧的esp和ebp所覆盖,当新栈帧释放后,指针又指向原来的栈底和栈顶。
当此程序在内存中运行时,首先进行main函数的运行。我们要知道,在main函数的汇编之前,栈区中已经存在一个ebp和esp。
我们分步剖析main函数的汇编过程:
Step 1:push ebp//此时的ebp是原先栈帧的栈底地址,将这个地址压栈,即保存原先栈帧的栈底地址。
Step 2:mov ebp,esp//mov,数据传送器,将esp的值传送给ebp,即将ebp指向当前的栈顶地址。
Step 3:sub esp,OD8H//sub,减法运算器,由于在栈帧中,存储地址由高地址向低地址变换,给esp减去一个值,意为esp下移。这个步骤为main函数开辟除了一个指定大小的栈帧区域。这一步进行完毕后,esp和ebp分别指向main函数的栈帧的栈顶和栈底地址。
main函数的栈帧开辟完毕后,程序向下进行
①int a=22;→mov dword ptr[a],16h
②int b=33;→mov dword ptr[b],21h
dword ptr[]:四字节指针,[ ]内存放一个数据的内存地址;通过四字节指针可以找到这个数据的值。
这两步操作是将a,b变量值放在变量的内存地址处。
要注意的是,在这一过程中,只是给a,b变量进行赋值操作,而没有将a,b变量压入fun函数的栈帧中,即没有完成函数的实例化。

下面,程序进行到fun(a,b):

进行fun函数的函数调用:
①mov eax,dword ptr[b]//将四字节指针内所指的b变量的值放在eax数据寄存器中
②push eax//将eax中的数据压栈,即将数据b的值压栈
③mov ecx,dword ptr[a]//将四字节指针内所指的a变量的值放在ecx数据寄存器中
④push ecx//将ecx中的数据压栈,即将数据a的值压栈
至此,两个局部变量a和b已经全部被压入栈中,完成了函数的实例化操作。
由此可以看出,函数的实例化是从右向左进行的。先进行b的实例化,再进行a的实例化。
⑤call fun(OA711DBh)
    call指令的作用:⑴保存当前指令的下一条指令的地址,压栈⑵jmp,跳转到对应函数的入口,执行子程序
    该步作用:⑴将main:retaddr 压栈,即保存当前之灵的下一条指令的地址,方便函数结束后程序的继续运行
                      ⑵jmp 跳转到fun函数的入口,执行fun函数内的指令
⑥add esp,8//加法处理器,将esp指针上移8个字节(两个变量的大小),即释放变量a,b的存储区域。


进行到这一步后,指令跳转到fun函数内部,开始进行fun函数栈帧的建立

①push ebp//将main函数的栈底地址压栈,保存
②mov ebp,esp//此时ebp和esp都指向main函数的栈顶
③sub esp,OCCh//将esp下移一定单位,开辟出fun函数的栈帧,此时ebp和esp分别指向fun函数的栈底和栈顶
至此,fun函数的栈帧创立完毕
④mov eax,dword ptr[c]//函数执行完毕后,将四字节指针内变量c的值寄存在eax数据寄存器中

至此,fun函数的功能已经使用完毕,系统要进行fun函数栈帧的释放

①mov esp,ebp//将当前栈底的值赋给栈顶,即此时esp和edp都指向fun函数的栈底,即main函数的栈顶
②pop ebp//将栈顶内容弹出,赋给ebp。由于此时esp指向的是卖弄函数的栈顶,其内保存着main函数的ebp,所以此时ebp重新指向main函数的栈底。
                   另外值得注意的是,由于栈顶esp内容被弹出,esp无所值,所以esp指针上移一个单位,指向main:retaddr,即当时指令的下一条指令,即main的栈顶。
③ret //ret指令是一个集合指令,能够保证main函数的继续执行:
           ⑴pop pc//将当前栈顶弹出,赋给pc,即将main:retaddr的值赋给pc指针
           ⑵跳转到pc指针存放的指令处,执行该指令。由此,main函数在fun函数结束后能够继续执行。

当main函数中所有指令都执行结束后,进行main函数栈帧的释放


以上是关于栈帧详情转载的主要内容,如果未能解决你的问题,请参考以下文章

gdb调试程序

转载FAT12格式的引导程序

欢迎搭乘「G20路」时光专车 转载?

转载 C#匿名函数 委托和Lambda表达式

细说虚拟机栈

科技部基础软件产品重大专项2009年课题(转载)