你必须非常努力,才能看起来毫不费力!
分类:
2008-10-06 12:25:26
int FactFun (int n)
{
if (n = =1){ return n;}
else { return n * FactFun(n -1);}
}
前面,我们曾提到过,函数的调用是基于栈的调用,那么,它是怎样被具体实现的呢?下面,我们将这段程序翻译为汇编语言,你就明白是怎么回事了:
;----------------------------------------------
; **** The body is factorial function **
;----------------------------------------------
FactFun PROC NEAR32
;procedure integer Factfun(integer)
;prarameters are passed in double words on the stack
push ebp
mov ebp,esp
push edx
cmp Dword Ptr[ebp+8],1
jne elseMore
jmp endIfOne
elseMore:
mov eax,Dword Ptr[ebp+8]
dec eax
push eax
call FactFun
mul Dword Ptr[ebp+8]
add esp,4
endIfOne:
pop edx
pop ebp
ret
FactFun ENDP
;-------------------------------------------------
注意,这个函数有一个传入参数和一个返回值,通常情况下,我们将返回值放入Eax 寄存器,在调用函数之前,通常要将参数压栈,代码片段如下:
。。。。。。
push eax
call FactFun
add esp,4
。。。。。。
首先,将传入的参数n压入栈,然后再将下一条指令的地址作为函数调用返回地址压入栈,然后进 入函数体
这两个语句的意思是,当传入的参数大于1时,我们要跳转到elseMore,这时,我们又开始第二次递归调用,这时,栈的数据图如图2 所示。递归程序一直压栈,直到我们传入的参数parameter 等于1 ,这个时候,调用就开始退栈,每一次退栈就会执行函数体中Call FactFun 之后的语句即:
。。。。。。
call FactFun
mul Dword Ptr[ebp +8]
add esp,4
endIfOne:
pop edx
pop ebp
ret
执行上述语句进行计算,每一次ret 之后,计算结果都存在eax 中,这样,只要将传入的参数(在Dword Ptr[ebp+8] 中) m,和返回值相乘就得到 m* FactFun(m -1) 的结果,这样层层退栈,直到参数为我们最先传入的参数值 n ,就可以得到计算结果,放入eax 中,返回值可以直接中这个寄存器中取得。我们也可以借助下图来描述我们来帮助我们建立一个递归函数过程