[ Zevs85 @ 29.03.2005. 19:53 ] @
Pozdrav... Da li bi bili ljubazni da mi objasnite princip rada rekurzivnih funkcija preko steka.... Konkretno vezano za faktorijel i Fibonacijeve brojeve. Unapred zahvalan |
[ Zevs85 @ 29.03.2005. 19:53 ] @
[ Vojislav Milunovic @ 29.03.2005. 20:53 ] @
Pa kao i u C i u asm je isto.
Pozivas istu funkciju iz te funkcije :) recimo: Code: proba proc ja :DWORD ;sta god oces call proba, eax ;sta vec oces proba endp [ Zevs85 @ 30.03.2005. 12:25 ] @
:-)
Hvala,ali mene zanima struktura steka pri pozivanju rekurzivne funkcije... [ Vojislav Milunovic @ 30.03.2005. 14:56 ] @
Pa ako mislis na redosled podataka na steku onda to izgleda slikovito ovako:
U zavisnosti da li koristis EBP da pristupas podacima na steku ili ides diektno preko esp registra imas razliciti prikaz steka: (cita se sa desna na levo jer me mrzi da pisem u vise linija) 1. poziv sa 1 argumentom (bez frame pointera aka ebp) [arg1][eip] 2. poziv [arg1][eip][arg1][eip] 3.poziv [arg1][eip][arg1][eip][arg1][eip] sa EBP: 1. poziv [arg1][eip][ebp] 2. poziv [arg1][eip][ebp][arg1][eip][ebp] 3. poziv [arg1][eip][ebp][arg1][eip][ebp][arg1][eip][ebp] itd iitd, ako si na ovo mislio :) Ako nisi na ovo mislio, onda moras detaljnije da objasnis sta te konkretno zanima :) [ Zevs85 @ 30.03.2005. 18:47 ] @
Da, to sam pitao, ali i dalje mi neke stvari nisu jasne...
Konkretno problem je: <PODPROGRAM> faktorijel: push %ebp movl %esp, %ebp movl 8(%ebp), %ebx andl %ebx, %ebx #provera da li je n=0 jz fakt_nula push %ebx #čuvanje vrednosti n na steku decl %ebx #n-1 push %ebx #rekurzija call faktorijel add $4, %esp pop %ebx #vraćanje vrednosti n sa steka mull %ebx #n*(n-1)! -> eax jmp fakt_kraj fakt_nula: movl $1, %eax #slučaj n=0 fakt_kraj: movl %ebp, %esp pop %ebp ret ne razumem neke delove koda, nisam siguran ni da li radi... Studiram racunarstvo i automatiku na FTN-u i to se nalazi u njihovom praktikumu iz arhitekture, a oni (asistenti) kazu da tu sve "sljaka" kako treba! Nisam razumeo konkretno deo koda posle prvog poziva labela faktorijel... Kad on izlazi iz petlje, jel prolazi kroz naredn redove koda posle poziva...? Ne znam, ako imas strpljenja da mi iskucas u cemu je fazon.... Unapred u svakom slucaju VELIKO HVALA, i prethodni odgovor mi je znacio.... [ Vojislav Milunovic @ 30.03.2005. 20:52 ] @
Code: push %ebp movl %esp, %ebp movl 8(%ebp), %ebx u ebx ti ide argument koji se predaje funkciji :) Code: andl %ebx, %ebx #provera da li je n=0 jz fakt_nula Kao sto i sam komentar kaze (cesce se koristi or i test nego and), ali kod radi svoj posao i proverava da li je argument predat funkciji = 0. Code: push %ebx #čuvanje vrednosti n na steku decl %ebx #n-1 push %ebx #rekurzija call faktorijel add $4, %esp Dakle cuvas vrednost ebx-a pre ulaska u drugi poziv iste funkcije, zatim umanjujes ebx za 1 i predajes ga kao parametar funkciji faktorijal. Naime add $4, %esp ce ukloniti sa stacka parametar koji si gurnuo na stack. Zbog lepote koda ja koristim ret 4 (pa u tom slucaju add $4, %esp nepotrebno) to je u sustini razlika izmedju __cdecl(ne cisti stack znaci samo retn) i __stdcall(cisti stack znaci ret broj_parametra * 4) Code: pop %ebx #vraćanje vrednosti n sa steka mull %ebx #n*(n-1)! -> eax jmp fakt_kraj Sad posto si poravnao stack odnosno ukloni sa njega parametar koji si predao funkciji vracas u ebx ono sto si ranije pushnuo (ono #cuvanje vrednosti n na stacku) i mnozis sadrzaj eax registra sa ebx (mull %ebx) i izlazis iz te funkcije... Da sumiramo ovako -> Ovaj kod ce se pozivati i vrteti sve dok argument predat funkciji != 0, odnosno dok ebx != 0 Code: faktorijel: push %ebp movl %esp, %ebp movl 8(%ebp), %ebx andl %ebx, %ebx #provera da li je n=0 jz fakt_nula push %ebx #čuvanje vrednosti n na steku (ovo je bitan momenat) decl %ebx #n-1 push %ebx #rekurzija call faktorijel Kad ebx bude = 0 u eax ce se staviti broj 1 i izaci ce se iz poslednje funkcije kad ta funkcija izadje ovaj deo koda ce se vrteti do kraja pri cemu ce se eax uvek mnoziti sa sacuvanim ebx-om sa stacka :) Code: add $4, %esp pop %ebx #vraćanje vrednosti n sa steka mull %ebx #n*(n-1)! -> eax jmp fakt_kraj fakt_nula: movl $1, %eax #slučaj n=0 fakt_kraj: movl %ebp, %esp pop %ebp ret Stek ce ti ovako izgledati (ebx prvo cuvanje ebx pre decl %ebx, arg1 ebx koji se predaje kao argument) [ebx][arg1][eip][ebp][ebx][arg1][eip][ebp][ebx][arg1][eip][ebp] Kad funkcija dodje do mov ebp, esp pop ebp sa steka ce se ocistiti ebp [ebx][arg1][eip][ebp][ebx][arg1][eip][ebp][ebx][arg1][eip] ret ce pokupiti sacuvan EIP i stack ce izgledati ovako: [ebx][arg1][eip][ebp][ebx][arg1][eip][ebp][ebx][arg1] add esp, 4 ce ocistiti [arg1] sa stacka i mozes slobodno da popnes sacuvani ebx dakle: [ebx][arg1][eip][ebp][ebx][arg1][eip][ebp][ebx] pop ebx cisti sacuvani ebx i onda imas sitciju kakvu si i imao malopre : [ebx][arg1][eip][ebp][ebx][arg1][eip][ebp] i na kraju kad poslednji izlaz iz funkcije pokupi EIP u izaci ces i iz ove duge rekurzije :) Nadam se da sam donekle pomogao :) [ Zevs85 @ 30.03.2005. 23:08 ] @
HVALA TI MNOGO...
Nemam reci, najjaci si.... Pozdrav! [ Vojislav Milunovic @ 31.03.2005. 12:40 ] @
Nema frke :)
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|