我无法理解以下代码的工作原理。这是一段简单的代码,它使用递归函数来查找数字的阶乘。在这种情况下4*3*2*1 = 24
。
.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。此时它将乘以“4”乘以%eax
1。这将给出 4 的值,这对于 4 的阶乘是完全错误的。但是,当我运行它时,它实际上给出了正确的输出 24。我在想每次函数时都应该执行乘法指令执行,而不是在函数完成调用自身之后。
有人可以通过代码向我解释为什么代码实际上给出了 24 的正确答案,而不是我认为它应该给出的答案 (4)。
每次在函数内部调用函数时,ebp 都会推送到堆栈并将更改为 esp。(推 %ebp 移动 %esb,%ebp)。如果是这样,我们如何在函数结束时将 esp,ebp 值恢复为初始值。(据我了解,pop 是在 end_function 中执行的,我们已经多次调用该函数,该函数已将 ebp、return、eax 多次推送到堆栈)。这真的让我的组装逻辑崩溃了。请有人定期解释它,说明堆栈有什么,并在每个点注册。