class Persoana{ private: char nume[25]; // vector de caractere unde vom salva numele persoanei int size; // variabila ce va memora dimensiunea numelui public: Persoana(); // constructor implicit ~Persoana(); // destructor implicit void setNume(char*); };
După cum am văzut mai sus apar niște etichete ce desemnează drepturi de acces asupra acelor elemente și anume: public, private și protected.
- public: toate elementele de sub această etichetă pot fi accesate în interiorul clase cât și în afara acesteia.
- private: elementele de sub această etichetă nu pot fi accesate decât în interiorul clasei.
- protected: elementele din această categorie pot fi accesate doar în clasele ce derivă din această clasă.
În principiu pentru a avea acces la un element din clasă trebuie ca cunoaștem practic adresa relativă fată de pointerul this la care se află elementul în memorie. Pentru aceasta avem nevoie să știm dimensiunea clasei. Dimensiunea clasei se calculează fiind suma dimensiunii fiecărui element.
În cazul de față clasa noastră ar avea dimensiunea de 29 de octeți. De fapt aceasta nu este dimensiunea reală deoarece se produce alinierea datelor, adica poziționarea lor în funcție de tipul cel mai mare de dată, în cazul nostru, int. Deci adevărata dimensiune a clasei este de 32 de octeți.
Cam așa arată clasa noastră în memorie.
Deoarece dimensiunea elementului nume este de 25, nefiind un multiplu de 4 (int fiind cel mai mare tip de dată din clasa), s-a produs alinierea datelor la tipul int.
Încă un lucru trebuie să mai știm ca să putem accesa un element din clasă, și anume că pointerul this se află în registrul ecx. Deci când lucrăm cu o clasă în limbaj de asamblare trebuie să avem grijă ca acest registru să nu fie modificat pentru a nu pierde adresa obiectului.
Adresa absolută a unui atribut din clasă se construiește din adresa de început a clasei, care se afla în pointerul this sau, în Assembler, în registrul ecx, și poziția de început atributul în memorie. În cazul nostru atributul size se găsește în memorie la adresa ecx+28, deoarece 28 reprezintă poziția de început a atributului size.
Acum ca avem aceste lucruri lămurite, putem trece să implementăm în limbaj de asamblare metoda din această clasă.
Ca idee de bază, verificăm dimensiunea șirului care este primit ca parametru, comparăm cu dimensiunea maximă a șirului din clasă. În cazul în care dimensiunea șirului primit ca parametru depășește dimensiunea șirului din clasă ieșim din funcție. Dacă dimensiunea este în regulă trecem mai departe la copierea celor șirurilor.
Pentru o bună vizualizare asupra codului, comentariile din partea de Assembler vor începe tot cu "//".
void setNume(char*){ _asm{ mov ebx,[ebp+8] // mutăm în ebx valoarea parametrului primit xor edi, edi // folosim registrul edi pentru a salva dimensiunea // șirului primit ca argument dim_param: // calculăm dimensiunea parametrului primit ca argument cmp [ebx+edi],'\0' je verificare_dim // cât timp nu am ajuns la sfârșitul șirului incrementăm registrul edi inc edi jmp dim_param verificare_dim: // verificam dacă depășește dimensiunea vectorului din clasă cmp edi,24 // comparăm cu dimensiunea maximă a șirului din clasă jge final xor esi, esi bucla_1: // copiem în vectorul din clasă șirul primit ca argument // totodată ținând cont și de lungimea acestuia cmp [ebx+esi], '\0' je final_bucla_1 mov dl, [ebx+esi] // copiem fiecare caracter din șirul primit // ca argument în șirul din clasa mov [ecx+esi], dl inc esi jmp bucla_1 final_bucla_1: mov byte ptr [ecx+esi],'\0' mov [ecx+28], esi // punem dimensiunea actuală a șirului în variabila size jmp final final: } }
Mai sunt de explicat câteva lucruri în legătură cu codul de mai sus cum ar fi: folosirea registrului "dl " din instrucțiunea "mov dl, [ebx+esi]" sau de ce se pune "byte ptr" în instrucțiunea "mov byte ptr [ecx+esi],'\0'".
Pentru prima instrucțiune, folosirea registrului "dl" este necesară deoarece elementele din șir sunt de tip "char", dimensiunea lor fiind de 1 octet, avem nevoie de un registru de 1 octet pentru manipularea valorilor.
Cât despre a doua instrucțiune, practic îi spunem să pună "\0" într-un singur byte la adresa specificată.
No comments:
Post a Comment