了解NASM程序集中的递归因子函数

时间:2013-10-07 05:58:20

标签: linux assembly recursion nasm 32-bit

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

假设我有

push 3
call factorial

我想在6中结束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。我怀疑可能EAX 0 MUL0总会产生EAX,这解释了这一点。为了测试,我决定给2一个0的值,期望一些非零值,但它会导致{{1}}。

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

1 个答案:

答案 0 :(得分:3)

请注意factorial(n-1)将覆盖factorial(n)'s EBX的第一件事,从而在inc EBX无效后呈现push。在您到达基本案例后,当您执行EBX时,您将遇到mul为0的情况,当然还有* 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