我无法理解下面的代码如何工作。这是一段简单的代码,它使用递归函数来查找数字的阶乘。在这种情况下,4*3*2*1 = 24
。为什么此组件产量为24而不是4?
.section .data
.section .text
.globl _start
._start:
pushl $4
call factorial
addl $4, %esp
movl %eax, %ebx
movl $1, %eax
int $0x80
.type factorial, @function
factorial:
pushl %ebp
movl %esp, %ebp
movl 8(%ebp), %eax
cmpl $1, %eax
je end_factorial
decl %eax
pushl %eax
call factorial
movl 8(%ebp), %ebx
imull %ebx, %eax
end_factorial:
movl %ebp, %esp
popl %ebp
ret
我明白关于代码的一切,除非我不明白为什么执行此部分(25/26行)。
movl 8(%ebp), %ebx
imull %ebx, %eax
我的理解(这显然是错误的),是该函数将保持自称直到%eax
值为1。在这一点上它将乘以%eax
这是一个“4”。这将给出4的值,这对于4的阶乘是完全错误的。然而,当我运行这个时,它确实提供了24的正确输出。我认为每次函数都应该执行乘法指令执行,而不是在函数完成调用之后。
有人可以通过代码并向我解释为什么代码实际上给出了24的正确答案,而不是我认为它应该给(4)。
而且每次在函数内部调用该函数时,ebp都会被压入堆栈,并且会被更改为esp。 (pushl%ebp Movl%esb,%ebp)。如果是的话,我们如何才能将esp,ebp值恢复到函数末尾的初始值。 (据我所知,pop在end_function中是做的,我们已经多次调用了这个函数,这已经推动了ebp,return,eax等几次堆栈)。这真是令人困惑,我的组装逻辑崩溃了。请有人解释一下它是什么意思,并说明什么是堆栈,并在每个点上注册。
你应该学会使用调试器。这些将允许您逐步浏览代码并观察发生的情况,并通过指令进行指导。从大多数代码中剔除它。 –