void myfunction(int a,int b)
{
int c=a+b;
}
(1)保存ebp。ebp总是被我们用来保存这个函数执行前的esp的值。执行完毕后,我们用ebp恢复esp;同时,调用此函数的上层函数也用ebp做同样的事情。所以先把ebp压入堆栈,返回之前弹出,避免ebp被我们改动。
push ebp
(2)保存esp到ebp中。
;保存ebp并把esp放入ebp中,此时ebp与esp同,都是这次函数调用时的栈顶
mov ebp,esp
(3)在堆栈中腾出区域来保存局部变量。
方法是:把esp减少一个数值,这就等于压入了一堆变量。要恢复时,只要把esp恢复成ebp中保存的数据就可以了。
保存ebx,esi,edi到堆栈中。函数调用后恢复。
sub esp,0cch
push ebx
push esi
push edi
(4)把局部变量初始化成全0cccccccch。0cch实际是int 3指令的机器码,是一个断点中断指令。因为局部变量不可能被执行,如果执行了,必然程序有错
,这时发生中断来提示开发者。这是VC编译Debug版本的特有操作。
lea edi,[ebp-0cch] ;本来是要mov edi,ebp-0cch,但是mov不支持ebp-0cch这样的参数。所以对ebp-0cch取内容,而
;lea把内容的地址也就是ebp-0cch加载到edi中。目的是把保存局部变量的区域(从ebp-0cch开始的区域)初始化成全部0cccccccch
mov ecx,33h
mov eax,0cccccccch
rep stos dword ptr [edi] ;串写入
(5)然后做函数里应该做的事。参数的获取是ebp+12字节为第二个参数,ebp+8为第一个参数(注意倒序压入),依次增加。最后ebp+4字节处是要返回的地址。
(6)恢复ebx,esi,edi,esp,ebp,最后返回。代码如下:
pop edi ;恢复edi,esi,ebx
pop esi
pop ebx
mov esp,ebp ;恢复原来的ebp和esp,让上一个调用的函数正常使用
pop ebp
ret
另外,该函数没有返回值。如果要返回值,函数应该在返回之前,把返回值放入eax中,外部通过eax获得返回值。