When you perform a call
, the address of the next operation is pushed to the stack as a return value. When creating a function, it is often customary to create a "stack frame". This frame can be used to print the call stack, as well as an offset for local variables and arguments. The frame is created through two operations at the beginning of the function:
push ebp
mov ebp, esp
At the end of the function, the call stack is removed using leave
, which is equivalent to the reverse of those 2 operations. When using a stack frame, value of esp
is stored into ebp
, making it point to a location on the stack called the frame's base. Since, above this address, there are the old value of ebp
and the return address, you would normally get the first argument using [ebp+8]
. However, you did not set up a stack frame. This means that the old value of ebp
was not pushed to the stack, and the current value of ebp
cannot be used to get arguments because you don't know where it is. Therefore, you should get your argument using [esp+4]
.
Also, it is customary that return values are placed in eax
and ebx
be preserved for the caller. Your code does not follow either of these conventions. Also, technically functions aren't required to preserved ecx
or edx
, so normally you should push them to the stack before calling another function if you want them preserved. With this code, edx
and ebx
would be overwritten if called with a value greater than 2, causing an invalid result.
Here is a full listing which includes all of the fixes I have mentioned. I did not create a stack frame as it is not necessary and your code didn't.
.386
.model Flat
public Fibonacci
include iosmacros.inc ;includes macros for outputting to the screen
.code
Fibonacci proc
MOV EAX, [ESP+4]
CMP EAX, 1
JA Recurse
MOV EAX, 1 ; return value in eax
JMP exit
Recurse:
PUSH EBX ; preserve value of ebx
DEC EAX
PUSH EAX
CALL Fibonacci
MOV EBX, EAX ; ebx is preserved by callee, so it is safe to use
DEC [ESP] ; decrement the value already on the stack
CALL Fibonacci
ADD EAX, EBX ; return value in eax
ADD ESP, 4 ; remove value from stack
POP EBX ; restore old value of ebx
exit:
ret
Fibonacci endp