ARMSim Recursion - recursion

New to ARMsim, trying to figure out recursion in the Fibonacci number sequence. If I input n I want to find the value of the fibonacci sequence at this index through the recursive case:
int fib(int N) {
# if (N == 0) return 0;
# if (N == 1) return 1;
# return fib(N-1) + fib(N-2);
# }
My current code:
.text
.global _start
_start:
mov r1 , #8
fib:
SUB sp,sp,#8
STR lr,[sp,#0]
STR r1,[sp,#4]
CMP r1, #1
BGT Else
MOV r1, #1
ADD sp,sp,#8
MOV pc,lr
Else:
SUB r1,r1,#1
BL fib
MOV r2,r1
LDR r1,[sp,#4]
SUB r1,r1,#1
BL fib
MOV r3,r1
LDR r1,[sp,#4]
LDR lr,[sp,#0]
ADD sp,sp,#8
ADD r1,r1,r2
ADD r1,r1,r3
MOV pc,lr
I was wondering where I am going wrong.
Any advice appreciated!

Related

ARM assembly recursive sum of 1..n

So I've had the following task that needs to be written in ARM Assembly
Please test the subroutine by passing the value of n equals 5. The result
should equal 15. If n equals 3, the result is 6.
I was given the corresponding Java code:
int sum (int n)
{
int result;
if (n == 1)
return 1;
result = Sum (n‐1) + n;
return result;
}
And I have written the following code in ARM Assembly
NAME main
PUBLIC main
SECTION .text: CODE (2)
THUMB
main
LDR R4, =0x005 ; Value n
BL SUM
STOP B STOP
SUM
MOV R1, #0x01
PUSH {R1, LR}
ADD R5, R5, R4 ; R5 = result
CMP R5, #1 ; Compare result to 1
BEQ ADD1
ADD0
SUB R4, R4, #1 ; Value n - 1
CMP R4, #0 ; Compare n to 0
BEQ ADD1
BL SUM
ADD1
POP {R4, LR}
BX LR ; Branch and exchange instruction set
END
The code is running fine but I want to know if there could be any slight improvements/shortcuts.
I am also a little unsure about the comments but I believe what I have written is correct.

How to find n-th element of Fibonacci sequence in assembly using stack and recursion

I am trying to write classical fib(n) function in assembly (intel x86) that is returning a n-th element of Fibonacci sequence.
I have written iterative version quite easily, but I'm having trouble trying to manipulate with recursion. This is what I tried:
.intel_syntax noprefix
.text
# unsigned fib(unsigned)
.globl fib
fib_n:
enter 0, 0
mov eax, 0
# n = 0 or n = 1
cmp edi, 1
jbe end
mov eax, 1
# n == 2
cmp edi, 2
je end
# n > 2, entering recursion
# fib(n-1)
push rdi
dec edi
call fib_n
mov r8d, eax
pop rdi
# fib(n-2)
push rdi
sub edi, 2
call fib_n
mov r9d, eax
pop rdi
# fib(n) = fib(n-1) + fib(n-2)
mov eax, r8d
add eax, r9d
end:
leave
ret
I am expecting for calls marked #fib(n-1) and #fib(n-1) to store local eax results in r8d and r9d registers, and then just add them and return through eax, but this is what I get as output:
n = 1 (1st el): 0 (works fine)
n = 2: 1 (works fine)
n = 3: 1 (works fine)
(wrong results)
n = 4: 2
n = 5: 2
n = 6: 3
n = 7: 3
...
I also tried pushing rax to the stack as well as rdi, but I still get wrong results. What am I missing?
What am I missing?
Register r8d is not preserved across recursive calls.
You don't need enter nor leave. No parameters were pushed.
It's easier to preserve the index rdi at the entry of fib_n.
fib_n:
push rdi
xor eax, eax
cmp edi, 2
jb end ; fib(1) = 0
mov eax, 1
je end ; fib(2) = 1
dec edi
call fib_n ; -> EAX
push rax ; (1) Preserve intermediate result!
dec edi
call fib_n ; -> EAX
add eax, [rsp] ; fib(n) = fib(n-2) + fib(n-1)
add rsp, 8 ; (1)
end:
pop rdi
ret
EDIT
The below version of the code incorporates comments made by rcgldr and Peter Cordes.
This code now removes 5 base-cases and is much cleaner.
fib_n:
cmp edi, 5 ; n
jb .LT5 ; Base-cases
push rdi ; (1) Preserve n
dec edi ; n-1
call fib_n ; -> EAX
push rax ; (2) Preserve intermediate result!
dec edi ; n-2
call fib_n ; -> EAX
pop rdi ; (2) Restore intermediate result
add eax, edi ; fib(n) = fib(n-2) + fib(n-1)
pop rdi ; (1) Restore n
ret
.LT5:
mov eax, edi ; n < 5
cmp edi, 2
cmc
sbb eax, 0 ; fib(0) = 0, fib(1) = 1
ret ; fib(2) = 1, fib(3) = 2, fib(4) = 3

Fibonacci with recursion steps shown indented / nested

This is the format that I need:
F(3) = F(2) + F(1) =
F(2) = (F1) + F(0) =
F(1) = 1
F(0) = 1
F(2) = 1
F(1) = 1
F(3) = 2
and this is my code, how am I going to do to get the format I want?
Please give me a hint or something that may help, thank you. I just start learning assembly language.
I only know how to show the first line like f()= the answer, but don't know how to show the process.
.data
fib1 BYTE "f(",0
fib2 BYTE ") + f(",0
fib3 BYTE ") = ",0
intVal DWORD ?
main PROC
mov edx, OFFSET fib1 ;show f(intVal)=
call WriteString
mov edx, intVal
call WriteDec
mov edx, OFFSET fib3
call WriteString
mov ecx, intVal-1
push intVal
call fib
add esp, 4
call WriteDec ;show result
call crlf
mov edx, OFFSET msg5 ;show goodbye msg
call WriteString
mov edx, OFFSET username
call WriteString
exit
main ENDP
fib PROC c
add ecx, 1
push ebp
mov ebp, esp
sub esp,4
mov eax, [ebp+8] ;get value
cmp eax,2 ;if ((n=1)or(n=2))
je S4
cmp eax,1
je S4
dec eax ;do fib(n-1)+fib(n-2)
push eax ;fib(n-1)
call fib
mov [ebp-4], eax ;store first result
dec dword ptr [esp] ;(n-1) -> (n-2)
call fib
add esp,4 ;clear
add eax,[ebp-4] ;add result and stored first result
jmp Quit
S4:
mov eax,1 ;start from 1,1
Quit:
mov esp,ebp ;restore esp
pop ebp ;restore ebp
ret
fib ENDP
END main
The code needs to output a "newline" at the end of each line of output, which could be a carriage return (00dh) followed by a linefeed (00ah) or just a linefeed (00ah) depending on the system (I don't know the irvine setup).
The indented lines should be printed from within the fib function, which means you have to save (push/pop stack) any registers that the print functions use.
The fib function needs to print out a variable number of spaces depending on the level of recursion, based on the text, 2 spaces per level of recursion.
The fib function needs to handle an input of 0 and return 0.
Note that the number of recursive calls to the fib function will be 2 * fib(n) - 1, assuming fib checks for fib(0), fib(1), fib(2) (more if it doesn't check for fib(2) ), which would be 5.94 billion calls for fib(47) = 2971215073, the max value for 32 bit unsigned integers. You may want to limit inputs to something like fib(10) = 55 or fib(11) = 89 or fib(12) = 144.

Attempting to implement this recursive Fibonacci sequence gives wrong outputs

I am trying to implement Fibonacci sequence in assembly by using recursion. This is my first time of trying to implement recursion in x86 Assembly.
The code compiles fine but it gives wrong outputs. The output for 1 is 1, output for 2 is 0, output for 3 is 1, output for 4 is 2, output for 5 is 3.
Only output it gives correct when you plug 5 in.
Is there something wrong with the algorithm?
.DATA
n1 DWORD ?
prompt1 BYTE "Please enter the first value", 0
prompt3 BYTE "No negative numbers!",0
string BYTE 40 DUP (?)
resultLbl BYTE "The Fib is: ", 0
fib BYTE 40 DUP (?), 0
.CODE
_MainProc PROC
input prompt1, string, 40
atod string
test eax, eax
js signed
mov n1, eax
jmp procName
signed:
output prompt3, string
jmp end1
procName:
mov eax, n1
push n1
call fib1
add esp,4
dtoa fib, eax
output resultLbl, fib
end1:
mov eax, 0
ret
_MainProc ENDP
Fib1 proc
PUSH EBP ; save previous frame pointer
MOV EBP, ESP ; set current frame pointer
MOV EAX, [EBP+8] ; get argument N
CMP EAX, 1 ; N<=1?
JA Recurse ; no, compute it recursively
MOV ECX, 1 ; yes, Fib(1)--> 1
JMP exit
Recurse:
DEC EAX ; = N-1
MOV EDX, EAX ; = N-1
PUSH EDX ; save N-1
PUSH EAX ; set argument = N-1
CALL Fib1 ; compute Fib(N-1) to ECX
POP EAX ; pop N-1
DEC EAX ; = N-2
PUSH ECX ; save Fib(N-1)
PUSH EAX ; set argument = N-2
CALL Fib1 ; compute Fib(N-2) to ECX
POP EAX ; = Fib(N-1)
ADD ECX, EAX ; = Fib(N-1)+FIB(N-2)
exit:
MOV ESP,EBP ; reset stack to value at function entry
POP EBP ; restore caller's frame pointer
RET
Fib1 endp
END

Recersive proc in x8086 Assembly

;==============================================================================================
; recursive procedure:
; supersum(int x)
; returns 1*2 + 2*3 + 3*4 + ... + i*(i+1)
supersum PROC
push ebp ; start of every procedure
mov ebp, esp
push ebx
; Actual subproc calc here
mov eax, [ebp +8] ; returning eax to the original called value
cmp eax,1
je basecase
dec eax ; (n-1) ; its just a lie...
mov recnum, eax ; saving dec val for call
mul double ; 2(n-1)
mov rhs, eax ; the right hand side is finished
push recnum
call sumseries ; a_(n-1)
add esp, 4
definition:
add eax, rhs ; a_(n-1)+ 2(n-1)
jmp skp
basecase: ; a_1 = 0
mov eax, 0
mov rhs, 2
jmp definition
skp:
pop ebx
pop ebp
ret
supersum ENDP
;============================================================================
The explicit definition of the serries I'm trying to get is 1*2 + 2*3 + 3*4 ... + i(i+1).
I've got the math for it down and I found that the recursive definition for the series is a_n = a_(n-1) + 2(n-1) with a_1 = 0 as a base case. I'm trying to figure out why this code keeps giving me the even series: {2,4,6,8,10 ...} instead of the series I'm trying to calculate

Resources