Structura de comandă a limbajului de asamblare conține: Structura de comandă în programarea la nivel de limbaj de asamblare. Formatul datelor și structura de comandă a limbajului de asamblare

Comenzi în limbaj de asamblare (Prelegere)

PLANUL DE PRELEGERE

1. Principalele grupe de operațiuni.

Pentium.

1. Principalele grupe de operațiuni

Microprocesoarele execută un set de comenzi care implementează următoarele grupuri principale de operații:

Operațiuni de expediere

Operatii aritmetice,

Operații logice

Operații în schimburi

Operatii de comparare si testare

Operații cu biți

Operațiuni de gestionare a programelor;

Operațiuni de control al procesorului.

2. Codurile mnemonice ale comenzilor procesorului Pentium

La descrierea comenzilor se folosesc de obicei denumirile lor mnemonice (coduri mnemonice), care sunt folosite pentru a specifica comanda la programare în limbaj Asamblare. Pentru diferite versiuni de Assembler, codurile mnemonice ale unor comenzi pot diferi. De exemplu, pentru comanda de apelare a unei subrutine, se folosește codul mnemonicAPEL sau JSR ("Sari la Subrutină"). Cu toate acestea, codurile mnemonice pentru majoritatea comenzilor pentru principalele tipuri de microprocesoare sunt aceleași sau diferă ușor, deoarece sunt abrevieri ale cuvintelor engleze corespunzătoare care definesc operația care se efectuează. Să ne uităm la codurile mnemonice ale comenzilor adoptate pentru procesoare Pentium.

Redirecționarea comenzilor. Echipa principală a acestui grup este echipaMOV , care asigură transferul de date între două registre sau între un registru și o celulă de memorie. Unele microprocesoare implementează transferuri între două celule de memorie, precum și transferuri în bloc ale conținutului mai multor registre din memorie. De exemplu, microprocesoarele din familia 68 Motorola xxx executa comandaMIȘCARE , oferind transfer de la o celulă de memorie la alta și comandaMOVEM , care scrie în memorie sau încarcă din memorie conținutul unui set specificat de registre (până la 16 registre). EchipăXCHG schimbă reciproc conținutul a două registre de procesor sau a unui registru și a unei celule de memorie.

Comenzi de intrare ÎN și ieșire OUT implementează trimiterea de date de la un registru al procesorului către un dispozitiv extern sau primirea datelor de la un dispozitiv extern către un registru. Aceste comenzi specifică numărul dispozitivului de interfață (port de intrare/ieșire) prin care sunt transferate datele. Rețineți că multe microprocesoare nu au comenzi speciale pentru accesarea dispozitivelor externe. În acest caz, intrarea și ieșirea datelor în sistem se realizează cu ajutorul comenziiMOV , care specifică adresa dispozitivului de interfață necesar. Astfel, dispozitivul extern este adresat ca o celulă de memorie, iar o anumită secțiune este alocată în spațiul de adrese în care se află adresele dispozitivelor de interfață (porturilor) conectate la sistem.

Comenzi pentru operații aritmetice. Principalele comenzi din acest grup sunt adunarea, scăderea, înmulțirea și împărțirea, care au o serie de opțiuni. Comenzi de adăugare ADĂUGA și scăderea SUB efectua operatiile corespunzatoare cucposedat de două registre, un registru și o locație de memorie, sau folosind un operand imediat. Echipe ANUNȚ C , S.B. B efectuați adunarea și scăderea ținând cont de valoarea atributuluiC, setat la formarea unui transfer în timpul executării operațiunii anterioare. Folosind aceste comenzi, este implementată adăugarea secvențială a operanzilor, al căror număr de biți depășește capacitatea procesorului. Echipă N.E.G. schimbă semnul operandului, transformându-l în complement a doi.

Operațiile de înmulțire și împărțire pot fi efectuate pe numere semnate (comenzieu MUL, eu DIV ) sau nesemnate (comenzi MUL, DIV Unul dintre operanzi este întotdeauna localizat într-un registru, al doilea poate fi într-un registru, o celulă de memorie sau poate fi un operand imediat. Rezultatul operațiunii se află în registru. La înmulțire (comenziMUL , IMUL ) rezultatul este biți dublu, pentru care se folosesc două registre. La împărțire (comenziDIV , IDIV ) ca dividend se folosește un operand dublu biți, plasat în două registre, iar ca rezultat, câtul și restul sunt scrise în două registre.

Comenzi de operare logică . Aproape toate microprocesoarele efectuează operații logice ȘI, SAU, SAU exclusiv, care sunt efectuate pe aceiași biți de operanzi folosind comenzi ȘI, SAU, X SAU . Operațiile sunt efectuate pe conținutul a două registre, un registru și o locație de memorie, sau folosind un operand imediat. Echipă NU inversează valoarea fiecărui bit al operandului.

Comenzi Shift. Microprocesoarele efectuează deplasări aritmetice, logice și ciclice ale operanzilor adresați cu unul sau mai mulți biți. Operandul de mutat poate fi într-un registru sau într-o locație de memorie, iar numărul de biți de deplasare este specificat de operandul imediat conținut în instrucțiune sau determinat de conținutul registrului specificat. Semnul de transfer este de obicei implicat în implementarea schimbuluiCîn registrul de stare (S.R. sau steaguri), care conține ultimul bit al operandului eliminat din registru sau celula de memorie.

Comenzi de comparare și testare . Compararea operanzilor se face de obicei folosind comandaCMP , care scade operanzi și setează valorile caracteristicilor N, Z, V, Cîn registrul de stare conform rezultatului obţinut. În acest caz, rezultatul scăderii nu este salvat, iar valorile operanzilor nu se modifică. Analiza ulterioară a valorilor caracteristicilor obținute ne permite să determinăm valoarea relativă (>,<, =) операндов со знаком или без знака. Использование различных способов адресации позволяет производит сравнение содержимого двух регистров, регистра и ячейки памяти, непосредственно заданного операнда с содержимым регистра или ячейки памяти.

Unele microprocesoare execută comanda de testare TST , care este o versiune cu un singur operand a instrucțiunii de comparare. Când această comandă este executată, semnele sunt setate N, Z conform semnului și valorii (egale sau non-nule) operandului adresat.

Instrucțiuni de operare a biților . Aceste comenzi stabilesc valoarea atributuluiCîn registrul de stare în conformitate cu valoarea bitului testatbn în operandul adresat. În unele microprocesoare, pe baza rezultatului testării biților, atributul este setatZ. Numărul de biți de testareneste specificat fie de conținutul registrului specificat în comandă, fie de operandul imediat.

Comenzile acestui grup implementează diferite opțiuni pentru modificarea bitului testat BT păstrează neschimbată valoarea acestui bit.Comandă B T S post-testul stabilește valoarea bn=1 și comanda B T C - sens bn=0.Echipă B T C inversează valoarea bitului bn după ce îl testează.

Operațiuni de gestionare a programelor. Pentru a controla programul, se utilizează un număr mare de comenzi, printre care se numără:

- comenzi de transfer de control necondiționat;

- comenzi de sărituri condiționate;

- echipe pentru organizarea ciclurilor de programe;

- comenzi de întrerupere;

- comenzi pentru schimbarea atributelor.

Transferul necondiționat al controlului se realizează prin comandăJMP , care se încarcă în contorul de programePCconținut nou care este adresa următoarei comenzi care urmează să fie executată. Această adresă este fie direct specificată în comandăJMP (adresare directă) sau calculată ca sumă a conținutului curentPCși offset-ul specificat în comandă, care este un număr semnat (adresare relativă). DeoarecePCconține adresa următoarei comenzi de program, cea din urmă metodă specifică adresa de salt, decalată față de următoarea adresă cu un număr specificat de octeți. Cu un offset pozitiv, trecerea la comenzile ulterioare ale programului, cu un offset negativ - la cele anterioare.

O subrutină este de asemenea apelată prin transferul necondiționat al controlului folosind comandaAPEL (sau JSR ). Cu toate acestea, în acest caz, înainte de încărcare înPC continut nou care specifica adresa primei comenzi a subrutinei, este necesara salvarea valorii sale curente (adresa comenzii urmatoare) pentru a asigura revenirea la programul principal dupa executarea subrutinei (sau la precedenta). subrutine la imbricarea subrutinelor). Comenzile de salt condiționate (ramuri de program) se încarcă înPCconținut nou dacă sunt îndeplinite anumite condiții, care sunt de obicei stabilite în funcție de valoarea curentă a diferitelor atribute din registrul de stare. Dacă condiția nu este îndeplinită, atunci următoarea comandă de program este executată.

Comenzile de control al caracteristicilor oferă scriere - citirea conținutului registrului de stare în care sunt stocate caracteristicile, precum și modificarea valorilor caracteristicilor individuale. De exemplu, procesoarele Pentium implementează comenzile LAHF Și SAHF , care încarcă octetul mic, care conține semnele, din registrul de stare EFLAG la octetul mic al registrului EAXși umplerea octetului scăzut steaguri din registru E AX.. Echipe CLC, STC efectuați setarea valorilor semnului de transfer CF=0, CF=1 și a comenzii CMC determină inversarea valorii acestui atribut. Deoarece atributele determină fluxul de execuție a programului în timpul tranzițiilor condiționate, comenzile de modificare a atributelor sunt de obicei folosite pentru a controla programul.

Comenzi de control al procesorului . Acest grup include comenzi de oprire, comenzi fără operare și un număr de comenzi care determină modul de funcționare al procesorului sau blocurile sale individuale. EchipăHLT oprește execuția programului și pune procesorul într-o stare de oprire, care este ieșită atunci când este primit un semnal de întrerupere sau de repornire ( Resetare). Echipă NOP Comanda („goală”), care nu determină efectuarea de operațiuni, este utilizată pentru a implementa întârzierile programului sau pentru a umple golurile formate în program.

Echipe speciale CLI, STI interzice și permite deservirea cererilor de întrerupere. În procesoare Pentium pentru aceasta este folosit un bit de control (steagul).DACĂîn registru steaguri.

Multe microprocesoare moderne emit o comandă de identificare care permite utilizatorului sau altor dispozitive să obțină informații despre tipul de procesor utilizat într-un sistem dat. În procesoare Pentuim comanda pentru aceasta este CPUID , timp în care datele necesare despre procesor intră în registre EAXEBXECXEDXși apoi poate fi citit de utilizator sau de sistemul de operare.

În funcție de modurile de operare implementate de procesor și de tipurile specificate de date care sunt prelucrate, setul de comenzi executate poate fi extins semnificativ.

Unele procesoare efectuează operații aritmetice cu numere binare-zecimale sau execută instrucțiuni speciale pentru a corecta rezultatul la procesarea unor astfel de numere. Multe procesoare de înaltă performanță includ FPU - unitate de procesare a numerelor c "punctul de plutire".

O serie de procesoare moderne implementează procesarea în grup a mai multor numere întregi sau numere c „virgula flotantă” folosind o singură comandă conform principiului SIMD („Instrucțiune unică – Date multiple” ”) - „O comandă – O mulțime de date.” Execuția simultană a operațiunilor pe operanzi multipli îmbunătățește semnificativ performanța procesorului atunci când lucrați cu date video și audio. Astfel de operațiuni sunt utilizate pe scară largă pentru procesarea imaginilor, semnalelor audio și alte aplicații. Pentru a efectua aceste operațiuni, în procesoare au fost introduse blocuri speciale care implementează seturile corespunzătoare de instrucțiuni, care în diferite tipuri de procesoare ( Pentium, Athlon) a primit numeleMMX (“ Milti- Extensie media ”) – Extensie multimedia,SSE(“Streaming SIMD Extension”) – Streaming SIMD - extensie, “3 DExtensie– Expansiune tridimensională.

O trăsătură caracteristică a procesoarelor companiei Intel , începând cu modelul 80286, este controlul prioritar la accesarea memoriei, care este furnizat atunci când procesorul funcționează în modul adrese virtuale protejate - „ Mod protejat " (mod protejat). Pentru implementarea acestui mod, se folosesc grupuri speciale de comenzi, care servesc la organizarea protecției memoriei în conformitate cu algoritmul de acces prioritar adoptat.

Structura comenzilor in limbaj de asamblare Programarea la nivelul comenzilor masinii este nivelul minim la care este posibila programarea pe calculator. Sistemul de comandă al mașinii trebuie să fie suficient pentru a implementa acțiunile necesare prin emiterea de instrucțiuni către echipamentul mașinii. Fiecare instrucțiune de mașină constă din două părți: una operațională, care determină „ce trebuie să faci” și un operand, care determină obiectele de procesare, adică „ce să faci”. O instrucțiune de mașină cu microprocesor, scrisă în limbaj de asamblare, este o singură linie care are următoarea formă: etichetă comanda/operanzii directivă; comentarii Eticheta, comanda/directiva și operandul sunt separate de cel puțin un spațiu sau un caracter tabulator. Operanzii comenzii sunt separați prin virgule.

Structura de comandă a limbajului de asamblare O comandă de asamblare îi spune traducătorului ce acțiune ar trebui să efectueze microprocesorul. Directivele de asamblare sunt parametri specificați în textul programului care afectează procesul de asamblare sau proprietățile fișierului de ieșire. Operandul precizează valoarea inițială a datelor (în segmentul de date) sau elementele asupra cărora se execută acțiunea de comandă (în segmentul de cod). O instrucțiune poate avea unul sau doi operanzi sau niciun operanzi. Numărul de operanzi este implicit specificat de codul instrucțiunii. Dacă o comandă sau o directivă trebuie continuată pe linia următoare, se folosește caracterul backslash: "" . În mod implicit, asamblatorul nu face distincție între litere mari și mici atunci când scrie comenzi și directive. Exemple de directive și comenzi Count db 1 ; Nume, directivă, un operand mov eax, 0 ; Comandă, doi operanzi

Identificatorii sunt secvențe de caractere valide folosite pentru a desemna numele variabilelor și numele etichetelor. Identificatorul poate consta din unul sau mai multe dintre următoarele caractere: toate literele alfabetului latin; numere de la 0 la 9; caractere speciale: _, @, $, ? . Un punct poate fi folosit ca prim caracter al etichetei. Numele rezervate de asamblare (directive, operatori, nume de comenzi) nu pot fi folosite ca identificatori. Primul caracter al identificatorului trebuie să fie o literă sau un caracter special. Lungime maxima Identificatorul are 255 de caractere, dar traducătorul le acceptă pe primele 32 și le ignoră pe restul. Toate etichetele care sunt scrise pe o linie care nu conține o directivă de asamblare trebuie să se termine cu două puncte „:”. Eticheta, comanda (directiva) și operandul nu trebuie să înceapă de la o anumită poziție din linie. Se recomandă să le scrieți într-o coloană pentru o mai mare lizibilitate a programului.

Etichete Toate etichetele care sunt scrise pe o linie care nu conține o directivă de asamblare trebuie să se termine cu două puncte „:”. Eticheta, comanda (directiva) și operandul nu trebuie să înceapă de la o anumită poziție din linie. Se recomandă să le scrieți într-o coloană pentru o mai mare lizibilitate a programului.

Comentarii Utilizarea comentariilor într-un program îmbunătățește claritatea acestuia, mai ales acolo unde scopul unui set de comenzi este neclar. Comentariile încep pe orice linie din modulul sursă cu punct și virgulă (;). Toate caracterele din dreapta lui "; " până la sfârșitul rândului sunt un comentariu. Un comentariu poate conține orice caracter imprimabil, inclusiv spațiu. Un comentariu se poate întinde pe întreaga linie sau poate urma o comandă pe aceeași linie.

Structura programului în limbaj de asamblare Un program scris în limbaj de asamblare poate consta din mai multe părți numite module, fiecare dintre acestea putând defini unul sau mai multe segmente de date, stivă și cod. Orice program complet în limbaj de asamblare trebuie să includă un modul principal, sau principal, de la care începe execuția lui. Un modul poate conține segmente de program, date și stivă, declarate folosind directive corespunzătoare.

Modele de memorie Înainte de a declara segmente, trebuie să specificați modelul de memorie folosind o directivă. MODEL MODEL memory_model, calling_convention, OS_type, stack_parameter Modele de memorie de bază în limbaj de asamblare: Model de memorie Adresarea codului Adresarea datelor Sistemul de operare Intercalarea codului și a datelor TINY NEAR MS-DOS Acceptabil MIC NEAR MS-DOS, Windows Nu MEDIUM FAR NEAR MS-DOS, Windows Nu COMPACT NEAR FAR MS-DOS, Windows Nu LARGE FAR MS-DOS, Windows Nu HUGE FAR MS-DOS, Windows Nu NEAR Windows 2000, Windows XP, Windows Acceptabil FLAT NEAR NT,

Modele de memorie Modelul mic funcționează numai în aplicațiile MS-DOS pe 16 biți. În acest model, toate datele și codul sunt situate pe un segment fizic. Dimensiunea fișierului de program în acest caz nu depășește 64 KB. Modelul mic acceptă un segment de cod și un segment de date. Datele și codul sunt adresate cât mai aproape atunci când utilizați acest model. Modelul mediu acceptă mai multe segmente de cod și un segment de date, toate referințele din segmentele de cod considerate în mod implicit departe și referințele dintr-un segment de date considerate aproape. Modelul compact acceptă mai multe segmente de date care utilizează adresarea datelor departe (departe) și un segment de cod care utilizează adresarea aproape (near). Modelul mare acceptă mai multe segmente de cod și mai multe segmente de date. În mod implicit, toate referințele la cod și date sunt considerate departe. Modelul uriaș este aproape echivalent cu modelul cu memorie mare.

Modele de memorie Modelul plat presupune o configurație de program nesegmentată și este utilizat numai în sistemele de operare pe 32 de biți. Acest model este similar cu modelul mic prin faptul că datele și codul sunt situate într-un singur segment, dar este pe 32 de biți. Pentru a dezvolta un program pentru modelul plat înainte de directivă. model flat ar trebui să plaseze una dintre directivele: . 386, . 486, . 586 sau. 686. Alegerea directivei de selecție a procesorului determină setul de instrucțiuni disponibile la scrierea programelor. Litera p după directiva de selecție a procesorului înseamnă modul de funcționare protejat. Adresarea datelor și a codului este aproape, toate adresele și indicatorii fiind pe 32 de biți.

Modele de memorie. MODEL modificator memory_model, calling_convention, OS_type, stack_parameter Parametrul modificator este folosit pentru a defini tipurile de segment și poate lua următoarele valori: use 16 (segmentele modelului selectat sunt folosite ca pe 16 biți) use 32 (segmentele modelului selectat sunt utilizate ca pe 32 de biți). Parametrul calling_convention este folosit pentru a determina metoda de transmitere a parametrilor la apelarea unei proceduri din alte limbi, inclusiv limbaje de nivel înalt (C++, Pascal). Parametrul poate lua următoarele valori: C, BASIC, FORTRAN, PASCAL, SYSCALL, STDCALL.

Modele de memorie. MODEL MODEL memory_model, calling_convention, OS_type, stack_parameter Parametrul OS_type este OS_DOS în mod implicit și este în prezent singura valoare acceptată pentru acest parametru. Parametrul stack_parameter este setat la: NEARSTACK (registrul SS este egal cu DS, zonele de date și stiva sunt situate în același segment fizic) FARSTACK (registrul SS nu este egal cu DS, zonele de date și stiva sunt situate în segmente fizice diferite). Valoarea implicită este NEARSTACK.

Un exemplu de program care nu face nimic. 686 P. MODEL PLAT, STDCALL. DATE. COD START: RET END START RET - comandă microprocesor. Se asigură că programul se încheie corect. Restul programului se referă la funcționarea traducătorului. . 686 P - Comenzile în mod protejat Pentium 6 (Pentium II) sunt permise. Această directivă selectează setul acceptat de instrucțiuni pentru asamblare, indicând modelul procesorului. . MODEL FLAT, stdcall - model cu memorie plată. Acest model de memorie este utilizat în sala de operație sistem Windows. stdcall - convenția de apelare a procedurii utilizată.

Un exemplu de program care nu face nimic. 686 P. MODEL PLAT, STDCALL. DATE. COD START: RET END START. DATE este un segment de program care conține date. Acest program nu folosește stiva, deci segmentul. STACK lipsește. . CODE este un segment de program care conține cod. START - etichetă. END START - sfârșitul programului și un mesaj către compilator că execuția programului ar trebui să înceapă cu eticheta START. Fiecare program trebuie să conțină o directivă END pentru a marca sfârșitul cod sursa programe. Toate liniile care urmează directivei END sunt ignorate.Eticheta specificată după directiva END spune traducătorului numele modulului principal de la care începe execuția programului. Dacă programul conține un singur modul, eticheta de după directiva END poate fi omisă.

Traducători în limbaj de asamblare Un traducător este un program sau un instrument tehnic care convertește un program prezentat într-unul dintre limbajele de programare într-un program în limba țintă, numit cod obiect. Pe lângă suportul mnemonicii de instrucțiuni ale mașinii, fiecare traducător are propriul său set de directive și instrumente macro, adesea incompatibile cu orice altceva. Principalele tipuri de traducători de limbaj de asamblare: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - un asamblator multi-pass distribuit gratuit, scris de Tomasz Gryshtar (polonez), NASM (Netwide Assembler) - un asamblator gratuit. asamblator pentru arhitectura Intel x 86, a fost creat de Simon Tatham împreună cu Julian Hall și este în prezent dezvoltat de o echipă mică de dezvoltatori de la Source. Forja. net.

Src="https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt="Traducerea unui program în Microsoft Visual Studio 2005 1) Creați un proiect selectând Fișier->Nou- >Meniul proiect Și"> Трансляция программы в Microsoft Visual Studio 2005 1) Создать проект, выбрав меню File->New->Project и указав имя проекта (hello. prj) и тип проекта: Win 32 Project. В дополнительных опциях мастера проекта указать “Empty Project”.!}

Src="https://present5.com/presentation/-29367016_63610977/image-16.jpg" alt="Traducerea programului în Microsoft Visual Studio 2005 2) În arborele proiectului (View->Solution Explorer) adăuga"> Трансляция программы в Microsoft Visual Studio 2005 2) В дереве проекта (View->Solution Explorer) добавить файл, в котором будет содержаться текст программы: Source. Files->Add->New. Item.!}

Traducerea programului în Microsoft Visual Studio 2005 3) Selectați tipul de fișier Cod C++, dar specificați numele cu extensia. asm:

Traducerea programului în Microsoft Visual Studio 2005 5) Setați parametrii compilatorului. Faceți clic dreapta pe meniul Custom Build Rules din fișierul de proiect...

Traduceți programul în Microsoft Visual Studio 2005 și selectați Microsoft Macro Assembler în fereastra care apare.

Traducerea programului în Microsoft Visual Studio 2005 Verificați cu butonul din dreapta în fișierul salut. arborele de proiect asm din meniul Proprietăți și instalați General->Tool: Microsoft Macro Assembler.

Src="https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt="Traducerea programului în Microsoft Visual Studio 2005 6) Compilați fișierul selectând Build->Build hello. prj."> Трансляция программы в Microsoft Visual Studio 2005 6) Откомпилировать файл, выбрав Build->Build hello. prj. 7) Запустить программу, нажав F 5 или выбрав меню Debug->Start Debugging.!}

Programarea în sistemul de operare Windows Programarea în sistemul de operare Windows se bazează pe utilizarea funcțiilor API (Interfața programului de aplicație, adică interfața aplicației software). Numărul lor ajunge la 2000. Programul Windows constă în mare parte din astfel de apeluri. Toate interacțiunile cu dispozitive externe iar resursele sistemului de operare apare, de regulă, prin astfel de funcții. Sistemul de operare Windows utilizează un model de memorie plată. Adresa oricărei celule de memorie va fi determinată de conținutul unui registru de 32 de biți. Există 3 tipuri de structuri de program pentru Windows: dialog (fereastra principală este dialog), structură consolă sau fără ferestre, structură clasică (fereastră, cadru).

Apel Funcții Windows API În fișierul de ajutor, orice funcție API este prezentată ca tip nume_funcție (FA 1, FA 2, FA 3) Tip – tip valoare returnată; FAx – o listă de argumente formale în ordinea în care apar. De exemplu, int Mesaj. Casetă(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Legendă, UINT u. Tip); Această funcție afișează o fereastră cu un mesaj și un buton de ieșire (sau butoane). Sensul parametrilor: h. Wnd este un descriptor al ferestrei în care va apărea fereastra de mesaj, lp. Text - text care va apărea în fereastră, lp. Legendă - text în titlul ferestrei, u. Tip - tip de fereastră; în special, puteți determina numărul de butoane de ieșire.

Apelarea funcțiilor Windows API int Message. Casetă(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Legendă, UINT u. Tip); Aproape toți parametrii funcției API sunt de fapt numere întregi de 32 de biți: HWND este un număr întreg de 32 de biți, LPCTSTR este un pointer de 32 de biți către un șir, UINT este un număr întreg de 32 de biți. Sufixul „A” este adesea adăugat la numele funcției pentru a trece la versiuni mai noi ale funcției.

Apelarea funcțiilor Windows API int Message. Casetă (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Legendă, UINT u. Tip); Când utilizați MASM, trebuie să adăugați @N N la sfârșitul numelui - numărul de octeți pe care argumentele transmise îi ocupă pe stivă. Pentru funcțiile API Win 32, acest număr poate fi definit ca numărul de argumente n înmulțit cu 4 (octeți în fiecare argument): N=4*n. Pentru a apela o funcție, utilizați instrucțiunea CALL asamblatorului. În acest caz, toate argumentele funcției îi sunt transmise prin intermediul stivei (comanda PUSH). Direcția de transmitere a argumentelor: STÂNGA LA DREAPTA - DE JOS SUS. Argumentul u va fi împins mai întâi în stivă. Tip. Apelul către funcția specificată va arăta astfel: CALL Message. Cutie. A@16

Apelarea funcțiilor Windows API int Message. Casetă(HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Legendă, UINT u. Tip); Rezultatul executării oricărei funcții API este de obicei un număr întreg care este returnat în registrul EAX. Directiva OFFSET reprezintă un „decalaj într-un segment” sau, tradus în termeni de limbaj de nivel înalt, un „indicator” la începutul unei linii. Directiva EQU, ca #define în SI, definește o constantă. Directiva EXTERN îi spune traducătorului că funcția sau identificatorul este extern acestui modul.

Exemplu de program „Salut tuturor!” . 686 P. MODEL PLAT, STDCALL. STACK 4096. DATE MB_OK EQU 0 STR 1 DB „Primul meu program”, 0 STR 2 DB „Salut tuturor!”, 0 HW DD ? Mesaj EXTERN. Cutie. A@16: APROAPE. COD START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Mesaj. Cutie. A@16 RET END START

Directiva INVOKE Translatorul limbajului MASM vă permite, de asemenea, să simplificați apelurile de funcții folosind un instrument macro - directiva INVOKE: funcția INVOKE, parametrul1, parametrul2, ... Nu este nevoie să adăugați @16 la apelul de funcție; parametrii se scriu exact în ordinea în care sunt dați în descrierea funcției. Prin mijloace macro ale translatorului, parametrii sunt plasați pe stivă. Pentru a utiliza directiva INVOKE, trebuie să aveți o descriere a prototipului funcției folosind directiva PROTO sub forma: Mesaj. Cutie. A PROTO: DWORD, : DWORD Dacă un program folosește multe funcții API Win 32, este recomandabil să folosiți directiva include C: masm 32includeuser 32. inc

Structuri în limbaj de asamblare

Matricele pe care le-am considerat mai sus sunt o colecție de elemente de același tip. Dar adesea în aplicații este nevoie să se ia în considerare un anumit set de date tipuri diferite ca un singur tip.

Acest lucru este foarte important, de exemplu, pentru programele de baze de date, unde este necesar să se asocieze o colecție de date de diferite tipuri cu un singur obiect.

De exemplu, ne-am uitat anterior la Lista 4, în care am lucrat cu o serie de elemente de trei octeți. Fiecare element, la rândul său, a constat din două elemente de tipuri diferite: un câmp de contor de un octet și un câmp de doi octeți, care ar putea transporta și alte informații necesare stocării și procesării. Dacă cititorul este familiarizat cu una dintre limbile de nivel înalt, atunci el știe că un astfel de obiect este de obicei descris folosind un tip de date special - structurilor.

Pentru a îmbunătăți gradul de utilizare a limbajului de asamblare, a fost introdus și acest tip de date în el.

A-prioriu structura este un tip de date format dintr-un număr fix de elemente de diferite tipuri.

Pentru a utiliza structuri într-un program, trebuie să efectuați trei pași:

    A stabilit șablon de structură .

    În esență, aceasta înseamnă definirea unui nou tip de date, care ulterior poate fi folosit pentru a defini variabile de acest tip.

    Defini instanță de structură .

    Această etapă implică inițializarea unei variabile specifice cu o structură predefinită (folosind șablon).

    Organiza accesarea elementelor de structură .

Este foarte important să înțelegeți de la bun început care este diferența între Descriere structurile din program și ale acestuia definiție.

Descrie structura într-un program înseamnă pur și simplu indicarea conturului sau modelului acestuia; memoria nu este alocată.

Acest șablon poate fi considerat doar ca informații pentru traducător despre locația câmpurilor și valoarea lor implicită.

Defini structura înseamnă instruirea traducătorului să aloce memorie și să atribuie un nume simbolic acestei zone de memorie.

O structură poate fi descrisă într-un program o singură dată, dar definită de orice număr de ori.

Descrierea șablonului de structură

Descrierea șablonului de structură are următoarea sintaxă:

nume_structură STRUC

Structura_nume ENDS

Aici este o secvență de directive de descriere a datelor db, dw, dd, dqȘi dt.

Operanzii lor determină dimensiunea câmpurilor și, dacă este necesar, valorile inițiale. Aceste valori vor inițializa probabil câmpurile corespunzătoare la definirea structurii.

După cum am observat deja când descriem șablonul, memoria nu este alocată, deoarece aceasta este doar informații pentru traducător.

LocațieȘablonul din program poate fi arbitrar, dar, urmând logica traductorului cu o singură trecere, trebuie să fie situat înainte de locul în care este definită variabila cu tipul structurii date. Adică, atunci când se descrie o variabilă cu tipul unei anumite structuri într-un segment de date, șablonul acesteia trebuie plasat la începutul segmentului de date sau înaintea acestuia.

Să luăm în considerare lucrul cu structuri folosind exemplul de modelare a unei baze de date despre angajații unui anumit departament.

Pentru simplitate, pentru a evita problemele de conversie a informațiilor la introducere, vom fi de acord că toate câmpurile sunt câmpuri de caractere.

Să definim structura de înregistrare a acestei baze de date cu următorul șablon:

Definirea datelor cu tip de structură

Pentru a utiliza o structură descrisă folosind un șablon într-un program, trebuie să definiți o variabilă cu tipul acestei structuri. Pentru aceasta, se folosește următoarea construcție sintactică:

[nume variabilă] nume_structură

    numele variabilei- identificatorul unei variabile de acest tip de structură.

    Specificarea unui nume de variabilă este opțională. Dacă nu o specificați, o zonă de memorie de dimensiune egală cu suma lungimilor tuturor elemente de structură.

    lista de valori- o listă de valori inițiale ale elementelor de structură cuprinse între paranteze unghiulare, separate prin virgule.

    Misiunea lui este, de asemenea, opțională.

    Dacă lista nu este complet specificată, atunci toate câmpurile structurii pentru această variabilă sunt inițializate cu valori din șablon, dacă sunt specificate.

    Este posibilă inițializarea câmpurilor individuale, dar în acest caz câmpurile lipsă trebuie separate prin virgulă. Câmpurile omise vor fi inițializate cu valorile din șablonul de structură. Dacă, atunci când definim o nouă variabilă cu tipul unei structuri date, suntem de acord cu toate valorile câmpului din șablonul acesteia (adică cele specificate implicit), atunci trebuie doar să scriem paranteze unghiulare.

    De exemplu: muncitor Victor.

De exemplu, să definim mai multe variabile cu tipul de structură descris mai sus.

Metode de lucru cu structura

Ideea introducerii unui tip structurat în orice limbaj de programare este de a combina variabile de diferite tipuri într-un singur obiect.

Limbajul trebuie să aibă un mijloc de accesare a acestor variabile într-o anumită instanță a structurii. Pentru a face referire la un câmp al unei structuri într-o comandă, se folosește un operator special - simbolul ". " (punct). Este folosit în următoarea sintaxă:

    expresie_adresă- identificatorul unei variabile de tip structural sau expresie între paranteze în conformitate cu regulile de sintaxă indicate mai jos (Fig. 1);

    nume_câmp_structură- numele câmpului din șablonul de structură.

    Aceasta, de fapt, este și o adresă, sau mai bine zis, decalajul câmpului de la începutul structurii.

Astfel operatorul " . „(punctul) evaluează expresia

Orez. 5. Sintaxa unei expresii de adresă într-un operator de acces la câmpul de structură

Să demonstrăm folosind exemplul structurii pe care am definit-o. muncitor unele tehnici de lucru cu structuri.

De exemplu, extrage la topor valorile câmpului cu vârsta. Deoarece este puțin probabil ca vârsta unei persoane care lucrează să fie mai mare de 99 de ani, după introducerea conținutului acestui câmp de caracter în registru topor Va fi convenabil să îl convertiți în reprezentare binară cu comanda aad.

Atenție deoarece datorită principiului stocării datelor „octet mic la adresa scăzută” va fi plasată cea mai mare cifră a vârstei al, iar cel mai tânăr - în Ah.

Pentru a face ajustări, trebuie doar să utilizați comanda xchg al, ah:

mov ax,word ptr sotr1.age ;in al age sotr1

sau o poti face asa:

Lucrările ulterioare cu o matrice de structuri se desfășoară în același mod ca și cu o matrice unidimensională. Aici apar mai multe întrebări:

Ce să faci cu dimensiunea și cum să organizezi indexarea elementelor matricei?

Similar altor identificatori definiți în program, traducătorul atribuie un atribut tip numelui tipului de structură și numelui variabilei cu tipul structurii. Valoarea acestui atribut este dimensiunea în octeți ocupată de câmpurile acestei structuri. Puteți prelua această valoare folosind operatorul tip.

Odată ce dimensiunea unei instanțe de structură este cunoscută, organizarea indexării într-o serie de structuri nu este deosebit de dificilă.

De exemplu:

Cum se copiază un câmp dintr-o structură în câmpul corespunzător al altei structuri? Sau cum să copiem întreaga structură? Să copiem câmpul nam al treilea angajat în domeniu nam al cincilea angajat:

mas_sotr worker 10 dup()

mov bx,offset mas_sotr

mov si,(tip muncitor)*2 ;si=77*2

mov di,(tip muncitor)*4 ;si=77*4

Mi se pare că a fi programator mai devreme sau mai târziu face ca o persoană să pară o gospodină bună. El, ca și ea, caută constant unde să salveze ceva, să reducă și să facă o cină minunată dintr-un minim de ingrediente. Și dacă acest lucru are succes, atunci satisfacția morală pe care o obțineți nu este mai mică, și poate chiar mai mare, decât dintr-o cină minunată cu o gospodină. Gradul acestei satisfacții, mi se pare, depinde de gradul de iubire față de profesia proprie.

Pe de altă parte, succesele în dezvoltarea de software și hardware relaxează oarecum programatorul și, destul de des, se observă o situație similară cu binecunoscutul proverb despre o muscă și un elefant - pentru a rezolva o problemă minoră, se folosesc instrumente grele, a cărui eficacitate, în cazul general, este semnificativă numai atunci când implementarea unor proiecte relativ mari.

Prezența următoarelor două tipuri de date în limbă se explică, probabil, prin dorința „gospodinei” de a folosi zona de lucru a mesei (RAM) cât mai eficient posibil la pregătirea alimentelor sau pentru plasarea produselor (date de program). ).

Comenzile pot fi distinse după scop (exemple de coduri de operare mnemonice ale comenzilor de asamblare IBM PC sunt date în paranteze):

l efectuarea de operații aritmetice (ADD și ADC - adunare și adunare cu purtare, SUB și SBB - scădere și scădere cu împrumut, MUL și IMUL - înmulțire fără semn și semn, DIV și IDIV - împărțire fără semn și semn, CMP - comparații etc.);

l efectuarea de operații logice (OR, AND, NOT, XOR, TEST etc.);

l transfer de date (MOV - înainte, XCHG - schimb, IN - intra în microprocesor, OUT - ieșire de la microprocesor etc.);

l transfer de control (ramuri de program: JMP - salt neconditionat, CALL - apel procedura, RET - intoarcere din procedura, J* - salt conditionat, LOOP - control bucla etc.);

l procesarea șirurilor de caractere (MOVS - transferuri, CMPS - comparații, LODS - încărcări, SCAS - scanări. Aceste comenzi sunt de obicei folosite cu prefixul (modificatorul de repetiție) REP;

l întreruperi de program (INT - întreruperi software, INTO - întrerupere condiționată la depășire, IRET - întoarcere de la întrerupere);

l control microprocesor (ST* și CL* - setarea și resetarea steagurilor, HLT - oprire, WAIT - așteptare, NOP - inactiv etc.).

CU lista plina Comenzile de asamblare pot fi găsite în lucrări.

Comenzi de transfer de date

l MOV dst, src - transfer de date (mutare - trimite de la src la dst).

Transferuri: un octet (dacă src și dst sunt în format octet) sau un cuvânt (dacă src și dst sunt în format cuvânt) între registre sau între un registru și memorie și scrie o valoare directă într-un registru sau memorie.

Operanzii dst și src trebuie să aibă același format - octet sau cuvânt.

Src poate fi de următorul tip: r (registru) - registru, m (memorie) - memorie, i (impedanță) - valoare imediată. Dst poate fi de tip r, m. Nu puteți folosi următorii operanzi într-o singură comandă: rsegm împreună cu i; doi operanzi de tip m şi doi operanzi de tip rsegm). Operandul i poate fi, de asemenea, o expresie simplă:

mov AX, (152 + 101B) / 15

Evaluarea expresiei se efectuează numai în timpul traducerii. Nu schimbă steaguri.

l PUSH src - împingerea unui cuvânt în stivă (push - impinge; împingeți pe stiva din src). Plasează conținutul src - orice registru de 16 biți (inclusiv registrul de segment) sau două celule de memorie care conțin un cuvânt de 16 biți - în partea de sus a stivei. Steagurile nu se schimbă;

l POP dst - scoateți un cuvânt din stivă (pop - pop; numărați de la stivă la dst). Îndepărtează un cuvânt din partea de sus a stivei și îl plasează în dst - orice registru de 16 biți (inclusiv registrul de segment) sau în două celule de memorie. Steagurile nu se schimbă.

Programarea la nivelul de instruire al mașinii este nivelul minim la care pot fi scrise programe. Sistemul de instrucțiuni al mașinii trebuie să fie suficient pentru a implementa acțiunile solicitate prin emiterea de instrucțiuni către hardware-ul computerului.

Fiecare comandă a mașinii constă din două părți:

  • operațional - stabilirea „ce trebuie făcut”;
  • operand - definirea obiectelor de procesare, „ce să faci cu”.

Comanda mașinii cu microprocesor, scrisă în limbaj de asamblare, este o linie cu următoarea formă sintactică:

etichetă de comandă/directivă operand(i); comentarii

În acest caz, câmpul necesar din linie este o comandă sau o directivă.

Eticheta, comanda/directiva și operanzii (dacă există) sunt separați de cel puțin un spațiu sau un caracter tabulator.

Dacă o comandă sau o directivă trebuie continuată pe linia următoare, se folosește caracterul backslash: \.

În mod implicit, limbajul de asamblare nu face distincție între litere mari și mici atunci când scrieți comenzi sau directive.

Exemple de linii de cod:

Numărați db 1 ;Nume, directivă, un operand
muta eax,0 ;Comandă, doi operanzi
cbw ; Echipă

Etichete

Eticheta în limbaj de asamblare poate conține următoarele simboluri:

  • toate literele alfabetului latin;
  • numere de la 0 la 9;
  • caractere speciale: _, @, $, ?.

Un punct poate fi folosit ca prim caracter al unei etichete, dar unii compilatori nu recomandă utilizarea acestui caracter. Numele de asamblare rezervate (directive, operatori, nume de comenzi) nu pot fi folosite ca etichete.

Primul caracter din etichetă trebuie să fie o literă sau un caracter special (dar nu un număr). Lungimea maximă a etichetei este de 31 de caractere. Toate etichetele care sunt scrise pe o linie care nu conține o directivă de asamblare trebuie să se încheie cu două puncte: .

Echipe

Echipă spune traducătorului ce acțiune ar trebui să efectueze microprocesorul. Într-un segment de date, o comandă (sau o directivă) definește un câmp, un spațiu de lucru sau o constantă. Într-un segment de cod, o comandă specifică o acțiune, cum ar fi mutarea (mov) sau adăugarea (adăugarea).

Directive

Asamblatorul are o serie de operatori care vă permit să controlați procesul de asamblare și listare. Acești operatori sunt chemați directive . Ele acționează numai în timpul procesului de asamblare a programului și, spre deosebire de comenzi, nu generează cod de mașină.

Operanzi

Operand – un obiect pe care este executată o comandă de mașină sau o instrucțiune a limbajului de programare.
O instrucțiune poate avea unul sau doi operanzi sau deloc operanzi. Numărul de operanzi este implicit specificat de codul instrucțiunii.
Exemple:

  • Fără operanzi ret ;Return
  • One operand inc ecx ;Mărire ecx
  • Doi operanzi adaugă eax,12 ;Adăugați 12 la eax

Eticheta, comanda (directiva) și operandul nu trebuie să înceapă de la o anumită poziție din linie. Cu toate acestea, este recomandat să le scrieți într-o coloană pentru a face programul mai ușor de citit.

Operanzii pot fi

  • identificatori;
  • șiruri de caractere cuprinse între ghilimele simple sau duble;
  • numere întregi în sisteme de numere binar, octal, zecimal sau hexazecimal.
Identificatori

Identificatori – secvențe de caractere valide utilizate pentru a desemna obiecte de program, cum ar fi coduri de operare, nume de variabile și nume de etichete.

Reguli pentru înregistrarea identificatorilor.

  • Identificatorul poate consta din unul sau mai multe caractere.
  • Ca simboluri puteți folosi litere din alfabetul latin, cifre și câteva caractere speciale: _, ?, $, @.
  • Un identificator nu poate începe cu un caracter cifră.
  • Lungimea identificatorului poate fi de până la 255 de caractere.
  • Traducătorul acceptă primele 32 de caractere ale identificatorului și ignoră restul.
Comentarii

Comentariile sunt separate de linia executabilă printr-un caracter; . În acest caz, tot ce este scris după punct și virgulă și până la sfârșitul rândului este un comentariu. Utilizarea comentariilor într-un program îmbunătățește claritatea acestuia, mai ales acolo unde scopul unui set de comenzi este neclar. Comentariul poate conține orice caracter imprimabil, inclusiv spații. Un comentariu se poate întinde pe întreaga linie sau poate urma o comandă pe aceeași linie.

Structura programului de asamblare

Un program scris în limbaj de asamblare poate consta din mai multe părți numite module . Fiecare modul poate avea unul sau mai multe segmente de date, stivă și cod definite. Orice program complet de asamblare trebuie să includă un modul principal sau principal de la care începe execuția acestuia. Un modul poate conține segmente de cod, segmente de date și segmente de stivă, declarate folosind directive corespunzătoare. Înainte de a declara segmente, trebuie să specificați modelul de memorie folosind directiva .MODEL.

Un exemplu de program „nu face nimic” în limbaj de asamblare:

686P
.MODEL PLAT, STDCALL
.DATE
.COD
START:

RET
sfârșitul început

Acest program conține o singură comandă de microprocesor. Această comandă este RET. Se asigură că programul se încheie corect. În general, această comandă este folosită pentru a ieși dintr-o procedură.
Restul programului se referă la funcționarea traducătorului.
.686P - Comenzile în mod protejat Pentium 6 (Pentium II) sunt permise. Această directivă selectează setul acceptat de instrucțiuni pentru asamblare, indicând modelul procesorului. Litera P indicată la sfârșitul directivei informează traducătorul că procesorul funcționează în mod protejat.
.MODEL FLAT, stdcall - model de memorie plat. Acest model de memorie este utilizat în sistem de operare Windows. stdcall
.DATA este un segment de program care conține date.
.CODE este un bloc de program care conține cod.
START - etichetă. În asamblare, etichetele joacă un rol important, ceea ce nu se poate spune despre limbajele moderne de nivel înalt.
END START - sfârșitul programului și un mesaj către traducător că execuția programului ar trebui să înceapă cu eticheta START.
Fiecare modul trebuie să conțină o directivă END, care marchează sfârșitul codului sursă al programului. Toate liniile care urmează directiva END sunt ignorate. Dacă omiteți directiva END, este generată o eroare.
Eticheta specificată după directiva END îi spune traducătorului numele modulului principal de la care începe execuția programului. Dacă programul conține un singur modul, eticheta de după directiva END poate fi omisă.




Top