» Utilizator
Salut, vizitatorule!

SkullBox este o comunitate formata din programatori si administratori de sisteme sau retele care iti sta la dispozitie cand ai o problema legata de calculatoare. Daca esti un utilizator existent, autentifica-te.

Daca nu te-ai inregistrat inca pe forum, alatura-te noua astfel marind comunitatea si ajutandu-i pe cei care au nevoie de informatii.

Daca te-ai inregistrat dar inca nu ai primit codul de activare, il poti cere aici.




Autentifica-te cu numele de utilizator si parola pentru a putea posta pe forum sau pentru a accesa ariile disponibile doar utilizatorilor inregistrati.
» Promovam
» Parteneri » Statistici
  • 59752 de mesaje.
  • 7151 de topicuri.
  • 1016 de utilizatori.
  •  
  • Miller0297 e ultimul utilizator inregistrat.
[Detalii]

 
Pagini: 1 [2]
Print
[ Tutorial ] Notiuni elementare ASM [9118 afisari]
emi
*


Mesaje: 1560
OfflineOffline


Daca nu a amintit nimeni de instructiunile push si pop, incerc sa descriu eu:

Am fost o data la un prieten, nu mai stiu cu ce ocazie.
Vad ca tipul coda ceva in assembler pentru un HC (PC-uri din alea vechi pe 8 biti, cu TV normal ca si monitor)

Ma apuc sa il intreb domnule, dar ce e aia push si pop ?

Raspunde: imagineaza-ti o stiva de farfurii.
Cu PUSH pui o farfurie
Si cu POP iei o farfurie.

nu intru acum in detalii, dar ideea e buna pentru incepatori. Repet cine vrea sa completeze e binevenit.
Logged
10-01-2009, 15:17 Twitt ::
acidcromaticle
*


Mesaje: 164
OfflineOffline

WWW

Da la facultate ne-a invatat la fel cu farfurii Big grin (asa intelege omul mai bine). Cu push salvezi in stiva valoarea unui registru de exemplu daca ai in AX ceva date pe care le vrei mai incolo in program, si trebuie sa alterezi sau sa schimbi valoarea din AX pentru ceva instructiune folosesti
Code:
push AX

dupa ce termini treaba cu AX si doresti sa aduci inapoi datele salvate in stiva folosesti comanda
Code:
pop AX

Mai pe scurt stiva se foloseste la salvarea datelor si la refacerea acestora .

Logged
10-01-2009, 17:58 Twitt ::
emi
*


Mesaje: 1560
OfflineOffline


Am vazut ca multi nu stiu ce e aia functie, procedura, subprogram, etc.

atunci cind faci un

CALL functia_mea

"functia_mea" e o adresa pe care o va lua IP.

Mai exista si parametrii care se transmit functiei. Acestia se transmit ori prin registrii direct ori prin stiva.

In majoritatea limbajelor de programare parametrii sunt pusi in stiva cu PUSH, inainte de CALL.
Logged
17-01-2009, 01:16 Twitt ::
TNick
*


Mesaje: 57
OfflineOffline

WWW

O sa ma refer si eu un pic la PUSH si POP. Big grin

Nu ca n-as fi de acord cu treaba cu farfuriile, da', dupa ce m-am jucat o leaca, a ajuns sa ma incurce. Pentru ca nu stiam esentialul.

Fiecarui fir de executie (thread) i se aloca la creare o zona de memorie numita stiva (stack) ce nu e in nici un fel diferita de alte zone de memorie. Un registru din procesor (sp, esp sau rsp, dupa cum lucram in 16, 32 sau 64 de biti) este setat sa contina capatul acestei adrese.
Exemplu:
sistemul de operare hotaraste sa aloce zona de la 0x400 la 0x500 pentru stiva. esp va contine valoarea 0x00000500.

Acum, exista cateva instructiuni care interactioneaza cu stiva.
1) PUSH - salveaza o valoare in stiva
Exemplu:
Code:
push eax ; salveaza valoarea registrului eax la esp-4, apoi scade din esp 4 => esp = 0x4FC
push 0 ; pune valoarea 0 la esp-4, apoi scade din esp 4 => esp = 0x4F8
push [0x123] ; salveaza valoarea de la adresa 0x123 la esp-4, apoi scade din esp 4 => esp = 0x4F4

2) POP - extrage o valoare din stiva in operator
Exemplu:
Code:
pop eax ; extrage valoarea care se gaseste la 0x123 si o plaseaza in eax; esp = esp +4 = 0x4F8
pop ecx ; extrage 0 si il plaseaza in ecx; esp = esp +4 = 0x4FC
pop [0x123] ; extrage valoarea anterioara a lui eax  si pune in ecx; esp = esp+4 = 0x500
3) PUSHAD - salveaza toti registrii de uz general in stiva, in ordinea asta: EAX, ECX, EDX, EBX,  ESP-ul original, EBP, ESI, si EDI

4) POPAD - restaureaza toti registrii de uz general

5) CALL - asa cum s-a mai spus, instructiunea asta transfera neconditionat executia la o alta procedura. In mod normal, dupa ce procedura e gata, executia se reia cu instructiunea urmatoare lui CALL Smile Inainte de a transfera executia, instructiunea salveaza valoarea registrului eip in stiva, iar esp = esp - 4

Exemplu:
Code:
; <- suntem aici
call O_Procedura ; <- executia va fi transferata la o alta procedura
; <- vom reveni aici

6) RET - este folosita - de obicei - in finalul unei proceduri, pentru a reveni la locul apelarii procedurii. Functioneaza astfel: valoarea din stiva indicata de esp este copiata in registrul EIP (cel care indica locul instructiunii curente), apoi la esp se adauga 4. RET are si un operand care ii spune procesorului cati BYTES trebuie sa scada din esp dupa ce a extras eip-ul. Operandul este folosit frecvent in conventia de apelare STDCALL (vezi mai jos), pentru a balansa stiva. Daca nu avem nici un parametru la procedura, operandul poate fi ignorat

Exemplu:
Code:
O_Procedura: ; Eticheta - in cazul nostru punctul de intrare in procedura
mov eax, ebx ; cateva instructiuni de umplutura
mov ecx, edx
; structura stivei:
; esp - adresa la care ne vom intoarce dupa executia procedurii si folosirea lui RET
; esp + 4 - parametrul furnizat procedurii
ret 4 ; in 32 de biti parametrul procedurii va fi de 4 bytes
; daca am avea 2 parametrii ar trebui sa scriem ret 8
.
.
.
push 1 ; furnizam parametrul procedurii in stiva
call O_Procedura ; apelam procedura
; <- dupa instructiunea ret executia revine aici


Conventii de apelare

Conventiile de apelare reglementeaza modul de transfer al parametrilor catre proceduri. Exista doua grupe mari si late: fie cel ce apeleaza e responsabil de balansarea stivei, fie cel ce e apelat.

1) STDCALL
Este modelul prezent in exemplul meu de mai sus. Cel ce apeleaza pune argumentele in stiva si apeleaza procedura care, la final, va aduna la esp numarul argumentelor * 2 (in 16 biti) sau *4 (in 32 de biti).

Code:
; doua apeluri catre aceeasi procedura cu exact aceeasi parametrii
push eax
push ecx
call O_Alta_Procedura

sub esp, 8
mov [esp], ecx
mov [esp+4],eax
call O_Alta_Procedura

O_Alta_Procedura:

mov ecx, [esp + 4] ; la esp e plasat eip-ul, la esp+4 primul argument, la esp + 8 al doilea
mov eax, [esp + 8]

ret 8

2) CDECL
Tipul asta de apelare permite apelul catre o procedura care accepta numar variabil de parametrii (e, si la STDCALL putem sa facem asta daca ne gandim otzara). Apelantul plaseaza argumentele procedurii in stiva, apeleaza procedura, apoi balanseaza stiva.

Code:
push eax ; plasam argumentele
push ecx
call O_Procedura ; apelam procedura
call O_Procedura ; argumentele sunt inca in stiva, la esp si esp+4
add esp, 8 ; balansam stiva

O_Alta_Procedura:

mov ecx, [esp + 4] ; la esp e plasat eip-ul, la esp+4 primul argument, la esp + 8 al doilea
mov eax, [esp + 8]

ret ; nu ne jucam cu argumentele aici

3) Alte conventii
Exista, desigur, o gramada de alte conventii.

4) Concluzii
E important sa stii ce soi de conventie foloseste o functie pe care nu ai scris-o tu (de exemplu, functiile API din Windows) si sa folosesti conventia respectiva cand apelezi functia. Pentru functiile pe care le scrii tu, poti folosi exact ce-ti trece prin cap.




Elemente de limbaj inalt
(asta e o traducere ca dracu' a "High level elements").

Majoritatea asambloarelor moderne (vezi FASM, MASM, NASM, SolASM, ...) iti ofera o modalitate comoda de a scrie proceduri si de a le apela.

PROC si ENDP
Folosite in diferite moduri, te ajuta sa-ti organizezi procedurile. "In spatele scenei" proc va face - de fapt - ceea ce ai face si tu (sau nu). In primul rand, va defini o eticheta, care va deveni punctul de intrare in procedura.

Code:
O_Procedura PROC STDCALL uses edi esi Arg1:DWORD, Arg2:DWORD

xor eax, ecx
ret
O_Procedura ENDP

Sa le luam pe rand:
- asa cum ziceam, (macro)instructiunea va defini o eticheta cu numele O_Procedura (ca si cand ai scrie O_Procedura:);
- apoi poti sa setezi conventia de apelare (in cazul de fata STDCALL - vezi mai sus); sigur ca poti sa omiti in majoritatea cazurilor conventia, una fiind&nbsp; atribuita implicit.
- uses te scapa de la a mai scrie tu push edi si push esi, precum si secventa inversa (pop esi pop edi)
- Arg1 - numele dat de tine si vizibil doar in interiorul procedurii (aaahhh, namespaces) pentru primul argument (cel mai aproape de call, cand apelezi procedura)
- Arg2 - ... Smile

De cele mai multe ori, se va mai introduce o secventa de code, si anume:
Code:
push ebp
mov ebp, esp
Si asa apare in scena Extended Base register. Asta e un registru ca oricare altul (general purpose), dar e des folosit pentru a simplifica lucrul cu stiva. Se poate si fara el (pe cuvant).
Ce se intampla aici? EBP este salvat in stiva, apoi el ia valoarea lui esp. Astfel, pe toata durata executiei procedurii (hopefully ... ) vom avea o copie a pointerului in stiva de la inceputul executiei procedurii. Si cum stim ca,la momentul respectiv, la esp e adresa de intoarcere, la esp + 4 e primul argument, la esp + 8 al doilea, ... putem sa accesam exact la fel argumetele si cu ebp (+4, +8). Mai important, atunci cand executi o instructiune care modifica esp-ul (un push, un call, ...), nu vei mai accesa argumentul 1 la esp + 4, ci la esp + 8 (na, un exemplu). Dar il vei accesa intotdeauna la ebp + 4. In codul tau, vei folosi numele simbolic, desigur.
mov eax, Arg1
sau
mov eax, [Arg1], dupa ce asamblor folosesti.
dar ambele instante vor fi inlocuite cu
Code:
mov eax, [ebp+4]
Totusi, mi se pare important sa stii ce se intampla "in spatele scenei".

O alta intrebuintare a lui ebp e la folosirea variabilelor locale in proceduri. In masm definesti o variabila locala folosind LOCAL:
Code:
LOCAL LocVar1:DWORD
LOCAL Rect1:RECT

ce se va intampla? dupa secventa push ebp - mov ..., va mai fi introdusa si instructiunea:
sub esp, 20 ;(4 pt dword, 4 * 4 pentru RECT)
creind in stiva un spatiu de 20 de bytes. Si da, ai ghicit, atunci cand folosesti numele simbolice in cod:
Code:
mov eax, LocVar1
mov Rect1.right, 12
ele vor fi inlocuite cu:
Code:
mov eax, [ebp-4]
mov [ebp-16],12 ; sper c-am calculat-o bine pe asta ;)

Recapituland, linia ta:
Code:
O_Procedura PROC STDCALL uses edi esi Arg1:DWORD, Arg2:DWORD

va fi inlocuita de secventa:
Code:
O_Procedura:
push edi ; de la uses
push esi
push ebp ; ii zice stack frame
mov ebp, esp
; iar daca inseram si variabilele locale de mai sus
sub esp, 20

Nu spun ca - de fiecare data - se va proceda exact in felul asta dar, functional, schema va fi similara.

Acu', trebuie sa existe si o balansare a stivei undeva. In MASM instructiunea ret nu e tocmai instructiunea ret ...&nbsp; Big grin De fiecare data cand o folosesti, ea va fi inlocuita de (folosind in continuare exemplul anterior):

Code:
mov esp, ebp ; chiar daca ai debalansat stiva, asta te salveaza
pop ebp
pop esi
pop edi
ret 8 ; (2 argumente * 4 bytes)

... Continuarea maine... Smile

Nicu
Logged
02-02-2009, 18:06 Twitt ::
emi
*


Mesaje: 1560
OfflineOffline


Incearca totusi sa fii mai clar, si sa explici din cit mai putine cuvinte.
Retine ca aici sunt notiuni fundamentale, discutam de la inceputuri, cind nu era vorba de programe multifir, sau pe 32 de biti, ce sa mai vorbim de 64 de biti.
Pentru notiuni avansate de ASM, deschide topic separat.

Ce este stiva ?
E o notiune teoretica, in pactica e facuta din citiva registrii care memoreaza baza stivei si virful stivei BP (base pointer) si SP (stack pointer).

Metoda ultimul venit primul servit, sau (echivalent) primul venit ultimul servit, e ce se ar fi vrut exemplul cu stiva de farfurii.
Logged
02-02-2009, 18:50 Twitt ::
TNick
*


Mesaje: 57
OfflineOffline

WWW

Incearca totusi sa fii mai clar, si sa explici din cit mai putine cuvinte.
Dimpotriva consider ca repetitia e mama invataturii, ca explicatia detaliata va avea ca si consecinta sigura retinerea conceptului de baza.

Retine ca aici sunt notiuni fundamentale, discutam de la inceputuri, cind nu era vorba de programe multifir, sau pe 32 de biti, ce sa mai vorbim de 64 de biti.
Dupa ceva ani petrecuti programand in limbaj de asamblare (exclusiv), cred ca stiu care e notiune fundamentala si care e avansata. Cum am mai zis, stiu si cum e la inceput, cand ti se prezinta o caruta de concepte abstracte - potrivite limbajelor de nivel inalt -pe cand Assembly inseamna lucruri cat se poate de concrete.

Zici ca discutam de la inceputuri??? E, asta e subiect avansat! Dupa umila mea parere, cea mai potrivita metoda de a incepe sa programezi in asm e sub Windows/Linux, in 32 de biti, scriind un "Hello World" care nu foloseste consola.

Ce este stiva ?
E o notiune teoretica, in pactica e facuta din citiva registrii care memoreaza baza stivei si virful stivei BP (base pointer) si SP (stack pointer).

Metoda ultimul venit primul servit, sau (echivalent) primul venit ultimul servit, e ce se ar fi vrut exemplul cu stiva de farfurii.
Incearca sa intelegi ca nu am atacat definitia scrisa de tine. E corecta si NECESARA. Dar, pe langa notiunea abstracta, am considerat necesara si definitia "la firul bit-ului" Smile Sa stie omul ce se intampla acolo...

Nicu
Logged
03-02-2009, 07:21 Twitt ::
emi
*


Mesaje: 1560
OfflineOffline


Adresarea memoriei (in vremea 8086)

Stiti ca registrul IP (instruction pointer) este cel responsabil cu instructiunea curenta din program, executa instructiunea curenta, vede ce lungime are, si o adauga.

Dar acest registru e pe 16 biti, adica 2^16-1, adica 64KB, cam putin nu ?
Ce s-au gindit cei de la Intel ?
Mai punem un registru, de segment  CS (code segment) si adresa fizica se va calcula astfel:

0x10*CS+IP

Tot ce am vorbit mai sus are si aceasta "complicatie".
Adica exista registrii segment. Va continua.
Logged
03-02-2009, 08:22 Twitt ::
emi
*


Mesaje: 1560
OfflineOffline


Instructiuni pentru siruri:

movsb, movsw, cmpsb, cmpsw

Pentru aceste instructiuni exista registrii:

DS:SI = Data segment si Source Index, ambii pe 16 biti
ES:DI = Extended segment si Destination Index.
Se folosesc de obicei pentru operatii cu siruri de caractere.

STD si CLD sunt instructiuni pentru DF= direction flag 0 sau 1, adica incrementeaza sau decrementeaza pentru operatiile de mai sus.
Logged
21-05-2009, 17:55 Twitt ::
emi
*


Mesaje: 1560
OfflineOffline


Instructiunile de tip Jump conditionat:

0x70: JO Im8
Adica Jump if overflow la o adresa relativa pe 8 biti

0x71: JNO Im8

Sa enumar celelalte: JB, JNB, JZ, JNZ, JA, JNA, JS, JNS, JP, JNP
astea sunt Jump conditionat pentru numere fara semn.
Cind e declarat un numar cu semn, instructiunea jump e:
JL, JNL, JG, JNG.

am avut o problema la un concurs, in asm, gresisem o instructiune jump cu semn, si de fapt trebuia una fara semn.

Sa detaliez fiecare instructiune:

JB = jump if is below, adica sare daca e mai mic
JNB = jump if is not below, adica sare daca nu e mai mic
JZ = jump if is zero, adica sare daca e zero
JNZ = jump if is not zero, adica sare daca nu e zero
JA = jump if is above, adica sare daca e mai mare
JNA = jump if is not above, adica sare daca nu e mai mare

si asa mai departe.
Logged
07-11-2009, 19:35 Twitt ::
Reclama
VIP

Hosting

Mesaje: 25.90
OnlineOnline

WWW
 

   Pe ABCDomenii: 250MB spatiu + 20GB trafic + 5 subdomenii = 0.95 €
 
 

The problem with troubleshooting is that trouble shoots back.
Azi 
Pages: 1 [2]
Print
SkullBox Forum  |  Development  |  ASM (Moderators: astan, TNick)  |  Topic: [ Tutorial ] Notiuni elementare ASM
Jump to: