递归函数的汇编表示

来源:互联网 发布:装修软件定哪种好 编辑:程序博客网 时间:2024/06/10 04:22

写入程序test.c:

# include <stdio.h>int fun(int n){if (n==0)return 0;if(n==1)return 1;elsereturn n+fun(n-1);}int main(){fun(4);return 0;}

使用gcc –g test.c产生调试信息,使用gdb调试程序,反汇编后得到汇编代码(fun函数):

(gdb) disas funDump of assembler code for function fun:   0x004016b0 <+0>:     push   %ebp   0x004016b1 <+1>:     mov    %esp,%ebp   0x004016b3 <+3>:     sub    $0x18,%esp   0x004016b6 <+6>:     cmpl   $0x0,0x8(%ebp)   0x004016ba <+10>:    jne    0x4016c3 <fun+19>   0x004016bc <+12>:    mov    $0x0,%eax   0x004016c1 <+17>:    jmp    0x4016e3 <fun+51>   0x004016c3 <+19>:    cmpl   $0x1,0x8(%ebp)   0x004016c7 <+23>:    jne    0x4016d0 <fun+32>   0x004016c9 <+25>:    mov    $0x1,%eax   0x004016ce <+30>:    jmp    0x4016e3 <fun+51>   0x004016d0 <+32>:    mov    0x8(%ebp),%eax   0x004016d3 <+35>:    sub    $0x1,%eax   0x004016d6 <+38>:    mov    %eax,(%esp)   0x004016d9 <+41>:    call   0x4016b0 <fun>    //递归调用函数fun()   0x004016de <+46>:    mov    0x8(%ebp),%edx   0x004016e1 <+49>:    add    %edx,%eax   0x004016e3 <+51>:    leave                    //函数调用结束   0x004016e4 <+52>:    retEnd of assembler dump.

上面的汇编语句中,<+35>和<+38>行分别使得n减一和使得n-1入栈,然后继续递归调用函数fun(),直到遇到递归的终止条件,使用leave和ret语句返回。

递归调用的过程是:


设置断点,单步执行后,查看栈帧后可得

(gdb) bt

#0 fun (n=1) at test.c:6

#1 0x004016de in fun (n=2) at test.c:9

#2 0x004016de in fun (n=3) at test.c:9

#3 0x004016de in fun (n=4) at test.c:9

#4 0x004016ff in main () at test.c:13

 可见,fun函数每次递归调用,都会申请新的堆栈,如果递归调用的次数变多,执行的效率会降低很多。

继续单步执行,查看堆栈信息

#0  infun (n=2) at test.c:10

#1 0x004016de in fun (n=3) at test.c:9

#2 0x004016de in fun (n=4) at test.c:9

#3 0x004016ff in main () at test.c:13

f(1)的堆栈已经被释放

再次单步执行,堆栈信息为

#0  infun (n=3) at test.c:10

#2 0x004016de in fun (n=4) at test.c:9

#3 0x004016ff in main () at test.c:13

此时f(2)的堆栈已经被释放

再次单步执行,查看堆栈信息

#0  infun (n=4) at test.c:10

#3 0x004016ff in main () at test.c:13

f(3)的堆栈被释放

单步执行,堆栈信息为:

#0  mainat test.c:14

此时递归函数的调用已经结束


0 0
原创粉丝点击