
...
}


从低地址esp到高地址ebp的区域是当前主要功能的堆栈帧. 在main中调用func时,编译大致为:
推米
推n;将两个参数压入堆栈
呼叫func;调用func,在堆栈上填写返回地址,然后跳转到func


当您跳到func时,请看一下func的编译:
__函数:
推动ebp;这非常重要,因为现在我们有了一个新函数,也就是说我们必须拥有自己的堆栈框架,然后我们必须保存上述函数main的堆栈框架的底部;保存,因为前一个堆栈框架的顶部将是func堆栈框架的底部. (两个堆栈帧相邻)

mov ebp,esp;前一个堆栈框架的顶部是该堆栈框架的底部
;我们先来看一下当前的堆栈

;在这里,新的堆栈框架开始

sub esp,8; int a,b在这里声明了两个int栈帧,因此esp减少了8个字节来为a,b分配空间
mov dword ptr [esp + 4],[ebp + 12]; a = m
mov dword ptr [esp],[ebp + 8]; b = n
通过这种方式,堆栈情况变为:

ret 8;返回,则8代表参数占用的字节数,当返回时栈帧,esp-8,释放参数m的空间n
可以看出,通过ebp可以轻松找到上述参数. 从func函数返回时,首先esp移到堆栈框架的底部(即释放局部变量),然后将上一个函数的堆栈框架的底部指针弹出到ebp,然后将返回地址弹出到cs: ip ,esp继续移动参数,以便esp,esp返回到调用该函数之前的状态,即现在已还原原始主堆栈帧.
本文来自电脑杂谈,转载请注明本文网址:
https://www.pc-fly.com/a/jisuanjixue/article-164568-1.html
是因为你真的真的值得爱
不听话
乱放屁
至少还要几十年时间吧