最近学习汇编!讨论一下栈的调用过程!解决办法

最近学习汇编!讨论一下栈的调用过程!
程序执行时,栈指针ESP和栈顶指针EBP的变化 
进入main函数的时候,
1)保存ebp指针
2)使得ebp->esp
3)保持现场ebx,esi,edi
4)进入一般函数的时候,push参数,例如有n个参数 esp = esp - 4*n
5)push函数返回地址 esp = esp -4
6)调用函数 EIP指向函数地址,jmp 函数地址
7)Push ebp 保存 (故有[ebp+8]就是第一个参数的内容)
8)使得ebp ->esp, esp = esp - 40h - 临时变量需要字节数(有字节对齐问题)
9)保持现场ebx,esi,edi
10)返回值=》eax
11)恢复现场,就是依次pop出edi,esi,ebx,
12)Esp = ebp
13)Pop ebp
14)pop 函数返回地址(即ret),EIP指向下个指令地址 esp = esp +4
15)Esp + n*4 (每个字有4个字节);push是按字操作的,32位机器

------解决方案--------------------
你写的哪个是每次调用函数时候的操作。。。
不是一个函数对应着一个堆栈。

只是每次调用函数时候都使用到堆栈。
------解决方案--------------------
一般来讲
每个程序都有栈空间

一个函数对应一个栈桢而不是一个堆栈
函数入口处的push %ebp,mov %esp %ebp为栈桢建立过程
函数结束有相应的栈桢销毁过程
但是也有栈桢被优化掉的时候,比如 push ebp被优化掉了,那么实际上是把被调用函数优化成了调用函数的一部分.
------解决方案--------------------
一个程序只有一个栈空间,调用函数前,主程序会把变量压栈。函数体进入后,首先保留寄存器数据,然后取得栈指针。通过记录下的栈指针来取得传递进来的参数。

由于栈空间只有一个,所以当你编程使用到递归时,一定要小心。每一次调用递归程序时,栈空间都会减少。
------解决方案--------------------
To zhangyanli:

因为ebp指向的是保存父函数的返回地址,而其下面的4位存放的是父函数的内容(内容是个返回地址),在这个返回地址下面才是我们存放的第一个参数的内容.所以要ebp+8
To 楼主
4)进入一般函数的时候,push参数,例如有n个参数 esp = esp - 4*n //很显然这是很错误的...esp是不可能指向参数区的,我们要调用参数区的 东西,是用[ebp+4*n]来调用的...
5)push函数返回地址 esp = esp -4 //详细错误见下面...

这两句中的esp应该改为ebp,esp只有在函数调用完成的时候才会直接将ebp的值赋给它,从而保证了销毁为保存局部变量而开辟出的栈空间.
------解决方案--------------------
这里为什么啊,为什么是ebp+8 
~~~~~~~~~
一般说来,
push yyy ;传参,esp-4,栈地址是从高到低的,所以此时esp指向yyy的地址
call xxx的时候,自动push 进去返回地址 esp-4
接下来在子函数里面
push ebp ;esp指针再次减4
mov ebp,esp;

ebp指向的是原ebp的地址,+4就指向了返回地址,再+4就指向了调用call xxx之前所压栈的参数了。ebp+8就是这个原因。
vc debug下生成的代码都是如此。
vc release下则就不一定,很多都是直接操作esp,反正只管负责返回父函数的时候,栈不变就行。