I am getting a stack overflow error at the position 'Call CalcProd' (within the function itself, not in main). Any idea why?
Here are relevant variable declarations:
Num1 DWORD 12
Num2 DWORD 7
Prod DWORD 0
Here is my function linkage and call in Main:
;----------------------CalcProd LINKAGE------------------
PUSH Num1
PUSH Num2
PUSH OFFSET Prod
CALL CalcProd
;--------------------------------------------------------
Here is my function:
;-------------------------CalcProd-------------------------
;calculates the product of the Num1 * Num2
;e.g. CalcProd(5,3) = 5+5+5 = 15
;params: Num1 and Num2 are passed in on the stack
;output: the product is put into the Prod variable
;------------------------------------------------------------
CalcProd proc
N1 EQU 16[ebp]
N2 EQU 12[ebp]
P EQU 8[ebp]
;necessary
PUSH ebp
MOV ebp,esp
MOV ecx,N2
;if (Num2 == 0)
CMP ecx,0
JE baseCase
;else return CalcProd(Num1,Num2-1)
DEC ecx
;PUSH ecx ; Num2-1
MOV N2,ecx
CALL CalcProd
;adds number to itself here
MOV esi,P
MOV eax,N1
ADD [esi],eax
baseCase:
MOV esp,ebp
POP ebp
ret 12
CalcProd endp
;the fix:
;else return CalcProd(Num1,Num2-1)
;DEC ecx
;PUSH Num1
;PUSH ecx
;PUSH OFFSET Prod
;CALL CalcProd
Related
%include "asm_io.inc"
segment .data
segment .bss
segment .text
global asm_main
asm_main:
enter 0,0
pusha
call read_int
push eax
call fak_rekursiv
add esp, 4
call print_int
call print_nl
popa
mov eax, 0
leave
ret
fak_rekursiv:
enter 4, 0
pusha
mov eax, [ebp + 8]
cmp eax, 0
je ergebnis_1
cmp eax, 1
je ergebnis_1
mov ebx, eax
dec ebx
mul ebx
push ebx
call fak_rekursiv
pop ebx
ergebnis:
mov [ebp - 4], eax
ergebnis_1:
mov [ebp - 4], dword 1
popa
mov eax, [ebp - 4]
leave
ret
I am learning to code on NASM and I was trying to understand recursion through using coding factorial but I got confused quickly.
How can I use Recursion in NASM to code factorial algorithm?
actually I have coded up factorial just for fun earlier. And now I have dug through my files to find that code :) here you go, but it is more like a pseudo-code which I only stepped through debugger.
factorial:
push eax
test eax, 07FFFFFFEh
jz .exit
dec eax
call factorial
mul dword [esp]
.exit:
pop edx
ret
put different values in eax and step through it in debugger.
Not too familiar with NASM, but here's a MASM solution which calls the factorial function recursively.
factorial.asm
.386
.model flat, stdcall
option casemap :none
includelib \masm32\lib\msvcrt.lib
printf PROTO C, :VARARG
.data
fmt db "%u! = %u", 13, 10, 0
.code
factorial proc
cmp eax, 0 ; Special-case to account for 0! = 1
je retone
cmp eax, 1
je retnow
push eax
dec eax
call factorial
pop edx
imul eax, edx ; eax = eax * edx
retnow:
ret
retone:
mov eax, 1
ret
factorial endp
main:
; Loop from 0 to 12 (max) factorial for 32-bit code.
mov ebx, 0
num:
mov eax, ebx
call factorial
invoke printf, OFFSET fmt, ebx, eax
inc ebx
cmp ebx,13
jne num
ret
end main
Displays all factorials from 0 to 12
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.
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
I've wrote assembly program which should count the below recursive function :
f(n) = f(n-1) + 2*f(n-2) - f(n-3)
For n = 0 and n = 1 it returns 1, and for n = 2 it should return 0.
But for this values program always returns 0, it looks like the below conditions were never met.
if0:
mov eax,1
jmp end
if1:
mov eax,1
jmp end
if2:
mov eax,0
jmp end
For any other value (greater than 2) I recives an segmentation falut.
Below is the entire code:
.intel_syntax noprefix
.globl main
.text
main:
mov eax, 3
push eax
call f
push eax
push offset msg
call printf
add esp, 8
mov eax, 0
ret
f:
push ebp
mov ebp,esp
add ebp,12
mov ebx,[ebp]
cmp ebx, 0
jz if0
cmp ebx, 1
jz if1
cmp ebx, 2
jz if2
lea ecx, [ebx-1]
push ecx
call f
pop ecx
push eax
lea ecx,[2*ebx-2]
push ecx
call f
pop ecx
pop eax
add eax,ecx
push eax
lea ecx, [ebx-3]
push ecx
call f
pop ecx
pop eax
sub eax,ecx
jmp end
if0:
mov eax,1
jmp end
if1:
mov eax,1
jmp end
if2:
mov eax,0
jmp end
end:
pop ebx
pop ebp
ret
msg: .asciz "Output = %d\n"
I have no idea what I do wrong.
EDIT: So, I've experimented with ebp and I've changed
add ebp,8
to:
add ebp, 16.
And, now it works for base conditions. It seems to me that there is problem with stack overflow, but I don't see it where is it.
Your pop ebx has no corresponding push, messing up your stack. There could well be other errors, but that's the one that jumped out at me.
;==============================================================================================
; 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