本文主要是介绍递归函数的汇编表示,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
写入程序test.c:
# include <stdio.h>
int fun(int n)
{
if (n==0)
return 0;
if(n==1)
return 1;
else
return n+fun(n-1);
}
int main()
{
fun(4);
return 0;
}
使用gcc –g test.c产生调试信息,使用gdb调试程序,反汇编后得到汇编代码(fun函数):
(gdb) disas fun
Dump of assembler code for function fun:0x004016b0 <+0>: push %ebp0x004016b1 <+1>: mov %esp,%ebp0x004016b3 <+3>: sub $0x18,%esp0x004016b6 <+6>: cmpl $0x0,0x8(%ebp)0x004016ba <+10>: jne 0x4016c3 <fun+19>0x004016bc <+12>: mov $0x0,%eax0x004016c1 <+17>: jmp 0x4016e3 <fun+51>0x004016c3 <+19>: cmpl $0x1,0x8(%ebp)0x004016c7 <+23>: jne 0x4016d0 <fun+32>0x004016c9 <+25>: mov $0x1,%eax0x004016ce <+30>: jmp 0x4016e3 <fun+51>0x004016d0 <+32>: mov 0x8(%ebp),%eax0x004016d3 <+35>: sub $0x1,%eax0x004016d6 <+38>: mov %eax,(%esp)0x004016d9 <+41>: call 0x4016b0 <fun> //递归调用函数fun()0x004016de <+46>: mov 0x8(%ebp),%edx0x004016e1 <+49>: add %edx,%eax0x004016e3 <+51>: leave //函数调用结束0x004016e4 <+52>: ret
End 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
此时递归函数的调用已经结束
这篇关于递归函数的汇编表示的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!