数据结构之---栈和递归&函数调用

更正:以下所指ebx应改为eax。
EBX指“基地址”寄存器,在内存寻址时存放基地址;、
EAX是累加器(accumulator),一般用来保存函数的返回值。

首先说说递归的实现和栈的关系吧,这里引入一个著名的尾递归-斐波那契数列的实现,我用的是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

数据结构之---栈和递归&函数调用_第1张图片

此时返回值已有确定值,开始按顺序出栈,运行到有返回地址字样时执行命令call XXXX(跳入该函数体内执行该函数),如下图

数据结构之---栈和递归&函数调用_第2张图片

运行到这里跳入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);
}                                

操作同第一步,

数据结构之---栈和递归&函数调用_第3张图片

下一步,出栈,由于Fib(3)的值已经明确,继续出栈

数据结构之---栈和递归&函数调用_第4张图片

由于Fib(3)的值已经明确,继续出栈

数据结构之---栈和递归&函数调用_第5张图片

步入Fib(4)函数体内,同理运行到return 2+Fib(2)语句,调用函数Fib(2),

数据结构之---栈和递归&函数调用_第6张图片

出栈,

数据结构之---栈和递归&函数调用_第7张图片

值已明确,继续出栈

数据结构之---栈和递归&函数调用_第8张图片

步入函数Fib(5),运行至return 3+Fib(3)语句处,调用函数Fib(3)

数据结构之---栈和递归&函数调用_第9张图片
数据结构之---栈和递归&函数调用_第10张图片
数据结构之---栈和递归&函数调用_第11张图片

同理步入Fib(3)函数,运行至return 1+Fib(1)语句处,调用函数Fib(1),进而出栈,ebx更新为2,继续出栈

数据结构之---栈和递归&函数调用_第12张图片

Fib(5)已有确定值,出栈,此时栈空,即Fib(5)等于5.

到这里我们就可以比较直观看出递归及函数调用过程中与栈的关系了,栈的这种先进后出的特性在计算机中被广泛运用。

当然我的所述皆出于自己的理解,如果有错误欢迎指正!


补充:在《0day安全:软件漏洞分析技术》上看到的一张图画得很详细,也一并贴出来。
数据结构之---栈和递归&函数调用_第13张图片

你可能感兴趣的:(数据结构)