Forum » Programiranje » [ASM] Pomoč, ne najdem napake
[ASM] Pomoč, ne najdem napake

c0dehunter ::
Lep pozdrav, ker se že en teden ukvarjam s to nalogo (brez uspeha), sem se odločil zatežit na ST forum, če bo kdo svetoval :)
Naredil sem že okoli 5 verzij pa mi nobena ne dela. Spodnja je še najboljši približek (vendar na koncu zašteka - "Cannot read memory at 0x0000001")
V zbirnem jeziku napišite rekurzivno funkcijo, ki izračuna n-ti člen zaporedja:
f(n) = f(n-3) + f(n-2), n > 2, f(0) = 1, f(1)=1, f(2) = 7
Naredil sem že okoli 5 verzij pa mi nobena ne dela. Spodnja je še najboljši približek (vendar na koncu zašteka - "Cannot read memory at 0x0000001")
bits 32
extern _printf
global _main
section .data
izpis db "Rezultat za f(%d)= %d",10,0 ;za izpis zaporedja
n dd 0
section .text
_rekurz:
mov eax, [esp+4] ;trenutni argument shranimo v eax
cmp eax,0 ;primerjamo, če je argument 0 in v tem primeru v eax shranimo 1
je .vrni1
cmp eax,1
je .vrni1
cmp eax,2 ;primerjamo argument z 2
je .vrni7
sub eax,2 ;n=n-2
mov edx, eax ;eax (n) shranimo v drug register, saj se bo vrednost eax spremenila
push eax ;na sklad potisnemo eax (n-2)
call _rekurz ;klicemo funkcijo za trenutni (n-2) - rezultat bo v eax
add esp,4 ;pobrišemo argument
mov ecx,eax ;dobljeno vrednost shranimo v ecx, začasno
mov eax,edx ;v eax nazaj shrani tisti trenutni n (n-2)
dec eax ;in se zmanjsamo za 1 (n-2 -1 = n-3)
push eax ;in to potisnemo na sklad na naslednji klic
call _rekurz ;klicemo funkcijo za trenutni (n-3) - rezultat bo v eax
add esp,4
add eax,ecx ;rezultata seštejemo
ret
.vrni1:
mov eax,1
ret
.vrni7:
mov eax,7
ret
.konec:
ret
_main:
pushad
; klic funkcije - rad bi izracunal 10. clen
push 10
call _rekurz
add esp,4
; izpis rezultata
push eax
push 10
push dword izpis
call _printf
add esp, 8
popad
ret

mikesr ::
lp
Ta n se bo ob rekurzivnem klicu vedno znova spremeninjal(tudi v registru ker ga vedno znova tja shranjujes).. Torej to je ena napaka
vrednost moras shranit v sklad.. torej najprej ko v register preneses parameter, preveris pogoje(ce je 0 1 ali 2).. potem pa v sklad pushas:
- rezerviran prostor za rezultat
- n-2(od shranjene vrednosti v registru odstejes 2)
- n-3
No in pol rekurzivno klices funkcijo.parameter se vzame n-3. rezultat shranis na rezerviran prostor, pocistis vrh sklada, spet klices rekurzivno funkcijo(parameter n-2) in na koncu vrnjeno vrednost eax pristejes k prvem rezultatu.
mov edx, eax ;eax (n) shranimo v drug register, saj se bo vrednost eax spremenila
Ta n se bo ob rekurzivnem klicu vedno znova spremeninjal(tudi v registru ker ga vedno znova tja shranjujes).. Torej to je ena napaka
vrednost moras shranit v sklad.. torej najprej ko v register preneses parameter, preveris pogoje(ce je 0 1 ali 2).. potem pa v sklad pushas:
- rezerviran prostor za rezultat
- n-2(od shranjene vrednosti v registru odstejes 2)
- n-3
No in pol rekurzivno klices funkcijo.parameter se vzame n-3. rezultat shranis na rezerviran prostor, pocistis vrh sklada, spet klices rekurzivno funkcijo(parameter n-2) in na koncu vrnjeno vrednost eax pristejes k prvem rezultatu.
Zgodovina sprememb…
- spremenil: mikesr ()

c0dehunter ::
mikser, 100x hvala!
Edino tega ne razumem najbolj: "potem pa v sklad pushas: -rezerviran prostor za rezultat". Lahko to malo bolj razložiš?
Sumim, da se to nanaša na
, vendar ne vem kako implementirat.
Sedanja koda (rekurzivne funkcije) - rezultat še vedno ni prav:
Edino tega ne razumem najbolj: "potem pa v sklad pushas: -rezerviran prostor za rezultat". Lahko to malo bolj razložiš?
Sumim, da se to nanaša na
mov ecx,eax ;dobljeno vrednost shranimo v ecx, začasno
, vendar ne vem kako implementirat.
Sedanja koda (rekurzivne funkcije) - rezultat še vedno ni prav:
_rekurz:
mov eax, [esp+4] ;trenutni argument shranimo v eax
cmp eax,0 ;primerjamo, če je argument 0 in v tem primeru v eax shranimo 1
je .vrni1
cmp eax,1
je .vrni1
cmp eax,2 ;primerjamo argument z 2
je .vrni7
sub eax,2 ;n=n-2
push eax ;eax (n) shranimo na sklad, saj se bo vrednost eax spremenila
dec eax
push eax ;n=n-3
call _rekurz ;klicemo funkcijo za trenutni (n-3) - rezultat bo v eax
add esp,4 ;pobrišemo argument
mov esi,eax ;dobljeno vrednost shranimo v esi, začasno
call _rekurz ;klicemo funkcijo za trenutni (n-3) - rezultat bo v eax
add esp,4
add eax,esi ;rezultata seštejemo
ret

bigbada ::
;V zbirnem jeziku napišite rekurzivno funkcijo, ki izračuna n-ti člen zaporedja:
;f(n) = f(n-3) + f(n-2), n > 2, f(0) = 1, f(1)=1, f(2) = 7
;V glavnem programu izračunajte člene od 3 do 15 in rezultat izpišite.
;Pomoč: dogovor klica funkcije cdecl, organizacija funkcijskega klicnega okna.
bits 32
extern printf
global main
section .data
izpis db "f(%d)=%d",10,0
stevec dd 0
main:
pushad
mov dword [stevec], 3 ;stevec nastavimo na 3
.zanka: ;loop
push dword [stevec] ;stevec pushnemo na sklad
call funkcija ;klic funkcije
add esp, 4 ;pocistimo za sabo
push eax ;eax in stevec na sklad + izpis
push dword [stevec]
push izpis
call printf
add esp, 12 ;pocistimo, ker smo 3 pushnili na sklad po 4bajte
inc dword [stevec] ;stevec povecujemo za 1
cmp dword [stevec], 15 ;to delamo dokler ne dosezemo 15, potem koncamo
jle .zanka
popad
ret
funkcija: ;funkcija
mov eax, [esp+4] ;trenutni argument shranimo v eax
cmp eax, 0 ;eax primerjamo z 0, ce je 0 jump v nadaljuj1, drugace shrani 1 v eax
jg .nadaljuj1
mov eax, 1
jmp .konec
.nadaljuj1: ;nadaljuj1
cmp eax, 1 ;eax primerjamo z 1.. ce je enak 1 gremo v nadaljuj2, drugace
jg .nadaljuj2
mov eax, 1 ;v eax damo 1
jmp .konec
.nadaljuj2: ;nadaljuj2
cmp eax, 2 ;ce je eax 2 gremo v nadaljuj 3
jg .nadaljuj3
mov eax, 7 ;v eax damo 7
jmp .konec ;skok na konec
.nadaljuj3: ;nadaljuj3
sub eax, 2 ;(eax-2)
push eax ;damo na sklad
sub eax, 1 ;odstejemo se 1... (eax-3)
push eax ;damo na sklad za naslednji klic
call funkcija ;klicemo funkcijo, rezultat se shrani v eax
add esp, 4 ;pocistimo
pop ebx
push eax ;eax in ebx damo na sklad
push ebx
call funkcija ;klic funkcije, rezultata seštejemo
add esp, 4
add eax, dword [esp]
add esp, 4
.konec:
ret
Zanima me, če mi lahko kdo razlozi zadnjih par vrstic kode.. pop ebx pa add eax, dword [esp].. Kaj tu naredimo.. Ni mi čisto jasno? Zakaj kar ebx, od kje?
Zgodovina sprememb…
- spremenilo: bigbada ()

mikesr ::
lp sosolci 
bom kar prilepil kodo, da bo bolj razumljivo:

bom kar prilepil kodo, da bo bolj razumljivo:
push 0 ;rezultat , lahko je tudi sub esp, 4
sub ecx, 2 ;(n-2)
push ecx ;shranimo v sklad
sub ecx, 1 ;(n-3)
push ecx ;shranimo v sklad
call _rekurzija ;klic funkcije z n-3 parametrom
add [esp+8], eax ;rezultat shranimo v sklad(na rezerviran prostor)
add esp, 4 ;izbrisemo vrh sklada(n-3)
call _rekurzija ;klic funkcije z n-2 parametrom
add eax, [esp+4] ;rezultat + prej shranjenen rezultat
add esp, 8 ;pocistimo sklad
Zgodovina sprememb…
- spremenil: mikesr ()
Vredno ogleda ...
Tema | Ogledi | Zadnje sporočilo | |
---|---|---|---|
Tema | Ogledi | Zadnje sporočilo | |
» | Delo za datotekami in zbirkami v zbirniku...Oddelek: Programiranje | 886 (754) | Brane2 |
» | asm - vnos stevilk s tipkovniceOddelek: Programiranje | 1334 (1190) | scarymovie |
» | [Assembler] scanf How-ToOddelek: Programiranje | 1694 (1621) | c0dehunter |
» | [nasm] scanfOddelek: Programiranje | 2973 (2700) | Brane2 |
» | [NALOGA][NASM] problem pri povezovanju s C-jevskimi funkcijamiOddelek: Programiranje | 1413 (1271) | c00L3r |