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 | 856 (724) | Brane2 |
» | asm - vnos stevilk s tipkovniceOddelek: Programiranje | 1295 (1151) | scarymovie |
» | [Assembler] scanf How-ToOddelek: Programiranje | 1660 (1587) | c0dehunter |
» | [nasm] scanfOddelek: Programiranje | 2911 (2638) | Brane2 |
» | [NALOGA][NASM] problem pri povezovanju s C-jevskimi funkcijamiOddelek: Programiranje | 1391 (1249) | c00L3r |