先看看遞歸的實現和棧的關系,這里引入著名的尾遞歸-斐波那契數列的實現。既然涉及到底層,自然就該用C語言實現。
int Fib(int n)
{
if(i==1||i==2)
return 1;
return Fib(i-1)+Fib(i-2);
}
我們不妨把函數Fib和return語句中調用的函數看作是不同的函數(只是具有了相同的名稱),那么就涉及到了函數調用的知識,我們知道,在函數調用的過程中(比如A函數中調用了B函數),編譯器就會把A函數的參數,局部變量及返回地址壓入棧中存儲,再進行B函數的調用。這里用匯編的思想解釋會比較生動,如下圖所示,假設傳入參數為5。
為方便理解,繪圖會比較生動,如下圖所示,假設傳入參數為5
此時返回值已有確定值,開始按順序出棧,運行到有返回地址字樣時執行命令call XXXX(跳入該函數體內執行該函數),如下圖
運行到這里跳入Fib(3)函數體內,我們不妨進入函數體內看看,
int Fib(int n) <---n=3
{
if(i==1||i==2) <---跳過
return 1;
return Fib(i-1)+Fib(i-2); //運行到此處,由於Fib(2)已經由上一步得出,即此時語句等同於return 1+Fib(1);
}
操作同第一步
下一步,出棧,由於Fib(3)的值已經明確,繼續出棧
繼續出棧
步入Fib(4)函數體內,同理運行到return 2+Fib(2)語句,調用函數Fib(2),
出棧......
值已明確,繼續出棧
步入函數Fib(5),運行至return 3+Fib(3)語句處,調用函數Fib(3)
同理步入Fib(3)函數,運行至return 1+Fib(1)語句處,調用函數Fib(1),進而出棧,ebx更新為2,繼續出棧
Fib(5)已有確定值,出棧,此時棧空,即Fib(5)等於5.
到這里我們就可以比較直觀看出遞歸及函數調用過程中與棧的關系了,
軟件漏洞與技術一書上也描述的很詳細,在這里貼出來。