Today I wrote a recursive fibonacci in assembly and it doesn't work. I compiled it to object file with NASM and than made it elf with gcc.
When I enter 1 or 2 the function works perfectly, but when I enter 3, 4, 5, 6, or more the function doesn't work.
I think there is problem where the function calls itself.
This the code:
SECTION .data ;init data
str: db "This equal: %d",10,0
SECTION .text ;asm code
extern printf
global main
main:
push ebp
mov ebp,esp
;--------------------
push 03 ; the index
call _fibonacci
add esp,4
push DWORD eax
push str
call printf
;---------------------
mov esp,ebp
pop ebp
ret
This is the function:
_fibonacci:
push ebp
mov ebp,esp
mov ebx, [ebp+8] ;; param n
cmp ebx,0
jne CHECK2
mov eax,0
jmp _endFIbofunc
CHECK2:
cmp ebx,0x1
jne ELSE3
mov eax,1
jmp _endFIbofunc
ELSE3:
mov ebx,[ebp+8]
dec ebx ;; n-1
;; FIRST call
push ebx
call _fibonacci
add esp,4
mov edx,eax
;; SEC CALL
dec ebx
push ebx
call _fibonacci
add esp,4
add eax,edx
mov eax,[ebp-4]
_endFIbofunc:
mov esp,ebp
pop ebp
ret
After I ran it on Ubuntu 16.04 it send error:
Segmentation fault (core dumped)
What might be the problem?
You must store (push) the registers you are going to change in the recursive call. And then restore their original values (pop). That should fix the problem.
Something like this:
You are using the memory at
[ebp-4]
without having put something useful in it! You need to reserve this space in your function prolog:Returning from the 1st recursive call you put the result from
EAX
in this memory dword.Returning from the 2nd recursive call you add to
EAX
the contents of this memory dword.Doing so, the
EDX
register will no longer be clobbered.Why do you use the
EBX
register at all? If you use it you have to preserve it as was explained in the answer by Al Kepp.If you start by putting the argument in
EAX
, you know that for both values below 2 (so 0 and 1), the result is just equal to the argument. Simple.If you don't balance the stack directly after the 1st recursive call, you can just decrement the dword that is already there and make your second recursive call.
The whole proc:
In addition to the other answers provided, here's an alternate solution:
Trivia - fib(47) is the largest < 2^32. The number of recursive calls = 2*fib(n+1)-1.