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.
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
New to assembly.
I'm trying to write an assembly code, that will do the following operation:
x/8 + 32 - y IF (x+y)/2>0
OR
2Y - 60 IF (x+y)/2<=0
While I was able to get the first operation to work ( even though, only when putting even numbers as X and Y, because otherwise I get results like ~+8000 ), I can't manage to make the second operation to work. When inserting in console something like : x= - 6, y=2, it should prind me out -56, but it prints me +30.
What did I do wrong there and how could I correct it?
INCLUDE Irvine32.inc
.data
mes1 byte "X:",0
mes2 byte "Y:",0
mes3 byte "Result:",0
vrx dword 0
vry dword 0
rez dword 0
doi dword 2
vxr dword 0
vyr dword 0
.code
main PROC
mov edx,OFFSET mes1
call WriteString ;
call ReadDec ;
mov vrx,eax ;
mov edx,OFFSET mes2
call WriteString ;
call ReadDec ;
mov vry,eax ;
;
xor eax,eax
mov edx,0
mov eax, vrx ;x
add eax, vry ;x+y
div doi ;(x+y)/2
cmp eax, 0 ; comparing
jb con1 ;
mov eax,vrx ; X/8+32-Y
mov ebx,8
div ebx
add eax,32
sub eax,vry
mov rez,eax
jmp ex ; jump to ex
con1: mov eax,vry ; 2Y-60
mov ebx,2
mul ebx
sub eax,60
mov rez,eax
ex: mov edx,OFFSET mes3
call WriteString ;
call WriteInt ;
call Crlf ;
exit
main ENDP
END main
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 am working on an MASM project and I think I have everything down / ready to go, expect I am having a pointer issue I believe and I just am not seeing it. When I debug it, it results in a buffer overflow.
EDIT:
Some more info. The error seems to be around the line: I believe it has to do with one of my compare statements / values that I am passing so that its not catching on the return when b / a and then testing it a is equal to 0.
mov eax, DWORD PTR[EBP + nBOffset]
CODE:
.model flat
.686
.STACK 4096
pDepthOffset EQU 8
nAOffset EQU 12
nBOffset EQU 16
.data
nTempSwap dd ?
.code
_GCD_ASM#12 PROC PUBLIC
push ebp
mov ebp, esp
push ebx
;ndepth += 1 section.
mov eax, DWORD PTR[EBP + pDepthOffset]
add eax, 1
mov DWORD PTR[EBP + pDepthOffset], EAX
mov eax, DWORD PTR[EBP + nAOffset]
;if b < a
cmp eax, DWORD PTR[EBP + nBOffset]
jae returnsection
;SWAP section
mov ecx, DWORD PTR[EBP + nAOffset] ; saving off A value.
mov eax, DWORD PTR[EBP + nBOffset] ; saving off B value
mov DWORD PTR[EBP + nAOffset], eax ; storinng my B into A
mov DWORD PTR[EBP + nBOffset], ecx ; storinng my A into B
;checking if equal to 0
returnsection:
cmp DWORD PTR[EBP + nAOffset], 0
jne callingSection
mov eax, DWORD PTR[EBP + nBOffset]
jmp finish
callingSection:
mov eax, DWORD PTR[EBP + nAOffset]
push eax
mov ecx, DWORD PTR[EBP + nBOffset]
sub ecx, DWORD PTR[EBP + nAOffset]
push ecx
mov edx, DWORD PTR[EBP + pDepthOffset]
push edx
call _GCD_ASM#12
finish:
pop ebx
pop ebp
ret 12
_GCD_ASM#12 ENDP
END
You are using ret 12 to remove 12 bytes from the stack, but only adding 12 bytes to the stack if you branch to callingSection (immediately before the line that seems to corrupt the stack, which is partially true).
You can either remove the parameter from your ret instruction and instead add add esp, 12 following call _GCD_ASM#12, or you can use separate cleanup routines rather than jump to a common finish:
I am trying to swap 2 pointers in that are passed by reference to a sub-routine. Here is what I have:
.data
firstInputPrompt BYTE 'Enter First String: ',0
secondInputPrompt BYTE 'Enter Second String: ',0
firstString BYTE 16 DUP(0) ;string buffers
secondString BYTE 16 DUP(0)
firstPointer DWORD OFFSET firstString ;pointers
secondPointer DWORD OFFSET secondString
.code
compare PROC
push ebp ;readying stack for use
mov ebp, esp
push eax ;used for comparing chars
push ebx
push ecx
mov ebx, [ebp+12] ;ebx now a pointer to firstString
mov ecx, [ebp+8] ;ecx now a pointer to secondString
mov ebx, [ebx]
mov ecx, [ecx]
;iterate over strings
iterate:
mov al, [ebx] ;compare characters
cmp al, [ecx]
ja swap_pointers
jb end_method
mov al, [ebx]
cmp al, 0
je end_method
mov al, [ecx]
cmp al, 0
je end_method
inc ebx
inc ecx
jmp iterate
swap_pointers:
;mov ecx, [ebp+12] ;get pointers again
;mov ebx, [ebp+8]
lea ebx, dword ptr [ebp+12]
lea ecx, dword ptr [ebp+8]
end_method:
;pop used registers
pop ecx
pop ebx
pop eax
pop ebp
ret
compare ENDP
The point where I get confused is right after the swap_pointers: label. I can't figure out how to swap the 2 pointers. Any ideas on what I'm doing wrong?
...
;load registers with pointers
mov ebx, firstPointer
mov ecx, secondPointer
;save pointers from register, swapping content
mov firstPointer, ecx
mov secondPointer, ebx
;finis
xor swaps register values whenever required
load registers with pointers
mov ebx, firstPointer
mov ecx, secondPointer
xor ebx,ecx
xor ecx ebx
xor ebx,ecx
gl