1

在 32 位 Ubuntu 上学习 NASM 汇编。我现在正在尝试学习递归函数,从阶乘开始(注意:这里我假设参数总是非负的)。

假设我有

push 3
call factorial

我想以6in结束EAX

这是我的尝试:

SECTION .text
global main
main:
; -----------------------------------------------------------
; Main
; -----------------------------------------------------------
push    3
call    factorial

; -----------------------------------------------------------
; Exit
; -----------------------------------------------------------
mov EAX,1
int 0x80

; -----------------------------------------------------------
; Recursive Factorial: n! = n * (n - 1)!
; -----------------------------------------------------------
factorial:

push    EBP         ; Retrieve parameter and put it
mov     EBP,ESP     ; into EBX register
add     EBP,8       ;
mov     EBX,[EBP]   ; EBX = Param

cmp     EBX,0       ; Check for base case
je      base        ; It is base if (n == 0)

dec     EBX         ; Decrement EBX to put it in the stack
push    EBX         ; Put (EBX - 1) in stack
inc     EBX         ; Restore EBX
call    factorial   ; Calculate factorial for (EBX - 1)
mul     EBX         ; EAX = (EAX * EBX) = (EBX - 1)! * EBX
pop     EBX         ; Retrieve EBX from the stack

jmp end
base:               ; Base case
mov     EAX,1       ; The result would be 1

end:

pop     EBP         ; Release EBP
ret

至少它适用于基本情况,哈......但对于我推动的任何其他值,它总是返回0. 我怀疑也许因为EAX0MUL总是会导致0,解释这一点。为了测试,我决定给出EAX一个 的值2,期望一些非零值,但它一直导致0.

你能告诉我如何做一个从堆栈中获取参数的递归阶乘函数吗?我相信已经看过一些示例,但是它们不是递归的,或者它们从其他地方获取参数,或者它们使用了一堆变量(当我认为可以仅使用寄存器来完成时)。

4

1 回答 1

2

请注意,factorial(n-1)它将覆盖它所做的第一件事的factorial(n)'sEBX,从而使inc EBX之后的事情变得push毫无意义。达到基本情况后,您将EBX遇到执行 0 时为 0的情况mul,当然还有任何 * 0 == 0。

最简单的解决方法是将序言更改为:

push    EBP         ; Retrieve parameter and put it
push    EBX         ; save previous param
mov     EBP,ESP     ; into EBX register
add     EBP,12       ;
mov     EBX,[EBP]   ; EBX = Param

和结语:

pop     EBX         ; restore previous param
pop     EBP         ; Release EBP
ret
于 2013-10-07T06:12:28.273 回答