X86 32位汇编利用堆栈传递函数参数的过程 |
您所在的位置:网站首页 › 程序变成32位 › X86 32位汇编利用堆栈传递函数参数的过程 |
名词、概念介绍
当传递的参数较少时,还是可以用寄存器来传参的,但是一旦传递的参数多了,就没办法了。 主程序将入口参数压入堆栈,子程序从堆栈中取出参数;出口参数通常不使用堆栈传递。 高级语言进行函数调用时提供的参数实质上也是用堆栈传递的,高级语言还利用堆栈创建局部变量。 保存参数和局部变量的堆栈区域称为堆栈帧,在函数调用时建立、返回后消失。 esp通常用来储存栈顶,ebp通常用来储存栈底 引入例子没有例子肯定学不来,所以我用书本上的一个简单的例子来演示一下,实际上书本上的解释已经挺清楚了,不过还是可以更加细致的了解这个过程 用C语言先把大概的代码写一下 void print(int *arr,int len){ printf("%d%d",*arr,len); } int main(){ int arr[5] = {5,4,3,2,1}; print(arr,5); }就是简单的调用两个参数 先给出汇编代码 main proc push offset arr ;把指针入栈 push lengthof arr ;把长度入栈这边要知道,call也涉及到栈 使用call指令的时候,会把下一句指令的eip存入栈中 相当于 push eip 然后跳转到函数那边去 下一步就是比较难理解的地方了 print proc push ebp mov ebp,esp这边寄存器EBP已经指向当前这个函数栈的栈底了,栈里面的ebp就是存的主函数main的栈底,容我介绍网上看来的几个概念: 栈平衡:为了防止缓冲区攻击,程序在结束时需要判断栈平衡,也就是要使ESP==EBP临时变量:像我们在写c语言的时候,总是在函数中用到临时变量,这些临时变量在函数开始时产生,在函数结束时销毁,那他们具体是存在哪里的呢?答案就是存在ebp和esp之间的空间中,这也是为什么临时变量开的数组不能很大,一旦很大就会报错栈溢出(stackOverflow)。 我的这个例子里面没有运用到临时变量,但是平时我们看到的 add esp,10H这样的操作其实就是在开辟临时变量区,开了16个字节的空间。 栈帧:在一个函数调用的过程中,ebp和esp之间的空间就叫做一个栈帧,在函数调用时建立、返回后消失。接下来是做保护寄存器的操作,我们担心寄存器中有存有不能丢失的变量,但是我们有希望能用到那个寄存器,这时候就要把寄存器push到栈里,最后再把原来的值pop出来 push edx push ecx mov edx,[edp+8] ; edx |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |