Program în limbaj de asamblare. Caracteristici generale ale sistemului de comandă al limbajului Assembler pentru IBM-PC (set de comenzi de bază, metode de bază de adresare a operanzilor). Structura programului în limbaj Assembler. Comenzi în limbaj de asamblare

Informații generale despre limbajul de asamblare

Limbajul de asamblare simbolic poate elimina în mare măsură dezavantajele programării în limbaj mașină.

Principalul său avantaj este că în limbajul de asamblare toate elementele programului sunt prezentate în formă simbolică. Conversia numelor de comenzi simbolice în codurile lor binare este responsabilitatea program special- asamblator, care eliberează programatorul de munca intensivă în muncă și elimină erorile inevitabile.

Numele simbolice introduse la programarea în limbaj de asamblare reflectă de obicei semantica programului, iar abrevierea comenzilor reflectă funcția lor principală. De exemplu: PARAM - parametru, TABLE - tabel, MASK - masca, ADD - adunare, SUB - scadere etc. etc. Astfel de nume sunt ușor de reținut pentru un programator.

Pentru programarea în limbaj de asamblare este necesar să aveți instrumente complexe decât pentru programarea în limbaj mașină: aveți nevoie de sisteme informatice bazate pe un microcomputer sau PC cu un set dispozitiv periferic(tastatură alfanumerică, afișare de caractere, unitate cu float și dispozitiv de imprimare), precum și sisteme rezidente sau de programare încrucișată pentru tipurile necesare de microprocesoare. Limbajul de asamblare vă permite să scrieți și să depanați eficient programe mult mai complexe decât limbajul mașină (până la 1 - 4 KB).

Limbajele de asamblare sunt orientate către mașină, adică depind de limbajul mașinii și structura microprocesorului corespunzător, deoarece în ele fiecărei instrucțiuni de microprocesor i se atribuie un nume simbolic specific.

Limbajele de asamblare oferă o creștere semnificativă a productivității programatorului în comparație cu limbajele de mașină și, în același timp, păstrează capacitatea de a utiliza toate resursele hardware disponibile de software ale microprocesorului. Acest lucru face posibil ca programatorii calificați să scrie programe care pot fi executate în mai puțin de un timp scurtși ocupă mai puțină memorie în comparație cu programele create într-un limbaj de nivel înalt.

În acest sens, aproape toate programele pentru controlul dispozitivelor de intrare/ieșire (driver) sunt scrise în limbaj de asamblare, în ciuda prezenței unei game destul de mari de limbaje de nivel înalt.

Folosind limbajul de asamblare, programatorul poate seta următorii parametri:

mnemonice (nume simbolic) ale fiecărei comenzi în limbajul mașinii cu microprocesor;

un format standard pentru liniile unui program scris în limbaj de asamblare;

format pentru indicare în diverse moduri variante de adresare și comandă;

format pentru specificarea constantelor de caractere și a constantelor întregi în diverse sisteme numerice;

pseudo-comenzi care controlează procesul de asamblare (traducere) a unui program.

În limbajul de asamblare, un program este scris linie cu linie, adică este alocată o linie pentru fiecare comandă.

Pentru microcalculatoarele construite pe baza celor mai comune tipuri de microprocesoare, pot exista mai multe variante de limbaj de asamblare, dar de obicei una este utilizată pe scară largă în practică - acesta este așa-numitul limbaj de asamblare standard

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:

· sala de operație - 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ă comanda/operanzii directivă ;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.

Adresare directă: Adresa efectivă este determinată direct de câmpul offset al instrucțiunii de mașină, care poate fi de 8, 16 sau 32 de biți.

mov eax, sum ; eax = suma

Asamblatorul înlocuiește sum cu adresa corespunzătoare stocată în segmentul de date (adresat implicit de registrul ds) și plasează valoarea stocată la sum în registrul eax.

Adresarea indirectă la rândul său are următoarele tipuri:

· adresare indirectă de bază (registru);

· adresare indirectă de bază (registru) cu offset;

· adresare indirectă la index;

· adresarea indirectă a indexului de bază.

Adresare indirectă de bază (registru). Cu această adresare, adresa efectivă a operandului poate fi localizată în oricare dintre registrele de uz general, cu excepția sp/esp și bp/ebp (acestea sunt registre specifice pentru lucrul cu segmentul de stivă). Sintactic într-o comandă, acest mod de adresare este exprimat prin includerea numelui registrului în paranteza patrata.

mov eax, ; eax = *esi; *valoarea esi la adresa esi

Introducere.

Limba în care este scris programul original, numit Intrare limba și limba în care este tradus pentru executare de către procesor este in zilele libere limbă. Procesul de conversie a limbajului de intrare în limbaj de ieșire este numit difuzat. Deoarece procesoarele sunt capabile să execute programe în limbaj mașină binar, care nu este folosit pentru programare, este necesară traducerea tuturor programelor sursă. Cunoscut doua feluri emisiuni: compilare și interpretare.

La compilare programul sursă este mai întâi tradus complet într-un program echivalent în limbajul de ieșire, numit obiect program și apoi executat. Acest proces este implementat cu ajutorul unui program special programe, numit compilator. Un compilator pentru care limbajul de intrare este o formă simbolică de reprezentare a limbajului mașină (de ieșire) al codurilor binare se numește asamblator.

La interpretări Fiecare linie de text din programul sursă este analizată (interpretată) și comanda specificată în acesta este imediat executată. Implementarea acestei metode îi este încredințată program de interpret. Interpretarea durează mult. Pentru a-și crește eficiența, în loc să proceseze fiecare linie, interpretul le convertește mai întâi pe toate echipășiruri în caractere (

). Secvența generată de simboluri este utilizată pentru a îndeplini funcțiile atribuite programului original.

Limbajul de asamblare discutat mai jos este implementat folosind compilare.

Caracteristicile limbii.

Principalele caracteristici ale asamblatorului:

● în loc de coduri binare, limba folosește nume simbolice - mnemonice. De exemplu, pentru comanda de adăugare (

) sunt folosite mnemonice

Scăderi (

inmultire (

Diviziuni (

etc. Numele simbolice sunt, de asemenea, folosite pentru adresa celulelor de memorie. Pentru a programa în limbaj de asamblare, în loc de coduri și adrese binare, trebuie să cunoașteți doar nume simbolice pe care asamblatorul le traduce în coduri binare;

fiecare afirmatie corespunde o comandă de mașină(cod), adică există o corespondență unu-la-unu între comenzile mașinii și operatori într-un program în limbaj de asamblare;

● limba oferă acces la toate obiectele si echipe. Limbile de nivel înalt nu au această abilitate. De exemplu, limbajul de asamblare vă permite să verificați biți din registrul steagului și limbajul de nivel înalt (de exemplu,

) nu are această capacitate. Rețineți că limbajele de programare a sistemelor (de exemplu, C) ocupă adesea o poziție intermediară. În ceea ce privește accesibilitatea, acestea sunt mai apropiate de limbajul de asamblare, dar au sintaxa unui limbaj de nivel înalt;

● limbaj de asamblare nu este un limbaj universal. Fiecare grup specific de microprocesoare are propriul său asamblator. Limbile de nivel înalt nu au acest dezavantaj.

Spre deosebire de limbajele de nivel înalt, scrierea și depanarea unui program în limbaj de asamblare necesită mult timp. În ciuda acestui fapt, limbajul de asamblare a primit utilizare largă datorita urmatoarelor circumstante:

● un program scris în limbaj de asamblare este semnificativ mai mic ca dimensiune și rulează mult mai rapid decât un program scris într-un limbaj de nivel înalt. Pentru unele aplicații, acești indicatori joacă un rol principal, de exemplu, mulți programe de sistem(inclusiv compilatoare), programe pe cărți de credit, celulare, drivere de dispozitiv etc.;

● unele proceduri necesită acces complet la hardware, ceea ce este de obicei imposibil de realizat într-un limbaj de nivel înalt. Acest caz include întreruperi și gestionare de întreruperi în sistemele de operare, precum și controlere de dispozitiv în sistemele încorporate în timp real.

În majoritatea programelor, doar un mic procent din codul total este responsabil pentru un procent mare din timpul de execuție al programului. De obicei, 1% din program este responsabil pentru 50% din timpul de execuție, iar 10% din program este responsabil pentru 90% din timpul de execuție. Prin urmare, pentru a scrie un program specific în condiții reale, se utilizează atât asamblatorul, cât și unul dintre limbajele de nivel înalt.

Format operator în limbaj de asamblare.

Un program în limbaj de asamblare este o listă de comenzi (instrucțiuni, propoziții), fiecare dintre acestea ocupând o linie separată și conține patru câmpuri: un câmp de etichetă, un câmp de operare, un câmp de operand și un câmp de comentariu. Fiecare câmp are o coloană separată.

Câmp de etichetă.

Coloana 1 este alocată pentru câmpul etichetă. Eticheta este un nume simbolic sau un identificator, adrese memorie. Este necesar pentru a putea:

● face o trecere condiționată sau necondiționată la comandă;

● obțineți acces la locația în care sunt stocate datele.

Astfel de declarații sunt prevăzute cu o etichetă. Pentru a indica un nume, sunt folosite litere (majuscule) din alfabetul englez și numere. Numele trebuie să aibă o literă la început și un separator de două puncte la sfârșit. Eticheta două puncte poate fi scrisă pe o linie separată, iar opcode-ul poate fi scris pe următoarea linie din coloana 2, ceea ce simplifică munca compilatorului. Absența două puncte nu permite distingerea unei etichete de un cod de operație dacă acestea sunt situate pe linii separate.

În unele versiuni ale limbajului de asamblare, două puncte sunt plasate numai după etichetele de instrucțiuni, nu după etichetele de date, iar lungimea etichetei poate fi limitată la 6 sau 8 caractere.

Nu ar trebui să existe nume identice în câmpul de etichetă, deoarece eticheta este asociată cu adrese de comandă. Dacă în timpul execuției programului nu este nevoie să apelați o comandă sau date din memorie, atunci câmpul de etichetă rămâne gol.

Câmpul pentru codul operațiunii.

Acest câmp conține codul mnemonic pentru o comandă sau pseudo-comandă (vezi mai jos). Codul mnemonic al comenzii este ales de dezvoltatorii limbajului. În limbaj de asamblare

mnemonic este selectat pentru a încărca un registru din memorie

), și pentru a salva conținutul registrului în memorie - un mnemonic

). În limbaje de asamblare

pentru ambele operațiuni puteți folosi, respectiv, același nume

Dacă alegerea numelor mnemonice poate fi arbitrară, atunci necesitatea de a utiliza două instrucțiuni de mașină este determinată de arhitectura procesorului

Mnemotecnia registrelor depinde și de versiunea de asamblare (Tabelul 5.2.1).

Câmp operand.

Aici se află Informații suplimentare, necesare efectuarii operatiei. În câmpul operand pentru comenzile de săritură este indicată adresa la care trebuie efectuată săritura, precum și adresele și registrele care sunt operanzi pentru comanda mașinii. Ca exemplu, oferim operanzi care pot fi utilizați pentru procesoare pe 8 biți

● date numerice,

prezentate în diferite sisteme numerice. Pentru a indica sistemul de numere utilizat, constanta este urmată de una dintre litere latine: IN,

În consecință, sistemele de numere binar, octal, hexazecimal, zecimal (

Nu trebuie să-l scrieți). Dacă prima cifră a unui număr hexazecimal este A, B, C,

Apoi se adaugă un 0 (zero) nesemnificativ în față;

● coduri ale registrelor interne ale microprocesorului și celulelor de memorie

M (surse sau receptori de informații) sub forma literelor A, B, C,

M sau adresele acestora în orice sistem de numere (de exemplu, 10B - adresa de înregistrare

în sistem binar);

● identificatori,

pentru perechi de aeronave de înregistrare,

Primele litere sunt B,

N; pentru o pereche de acumulator și registru de caracteristici -

; pentru contorul de programe -

;pentru indicatorul stivei -

● etichete care indică adresele operanzilor sau instrucțiunile următoare din condițional

(dacă este îndeplinită condiția) și tranziții necondiționate. De exemplu, operandul M1 din comandă

înseamnă necesitatea unei tranziții necondiționate la comandă, a cărei adresă în câmpul de etichetă este marcată cu identificatorul M1;

● expresii,

care sunt construite prin legarea datelor discutate mai sus folosind operatori aritmetici și logici. Rețineți că metoda de rezervare a spațiului de date depinde de versiunea limbii. Dezvoltatori de limbaj de asamblare pentru

Definiți cuvântul) și introdus ulterior Opțiune alternativă.

care a fost în limbajul pentru procesoare încă de la început

În versiune lingvistică

folosit

Definiți o constantă).

Procesoarele procesează operanzi de diferite lungimi. Pentru a-l defini, dezvoltatorii de asamblare au luat diferite decizii, de exemplu:

Registrele II de lungimi diferite au nume diferite: EAX - pentru plasarea operanzilor pe 32 de biți (tip

); AX - pentru 16 biți (tip

și AN - pentru 8 biți (tip

● pentru procesoare

La fiecare cod de operare se adaugă sufixe: sufix

Pentru tip

; sufixul „.B” pentru tip

diferite opcode sunt utilizate pentru operanzi de diferite lungimi, de exemplu, pentru a încărca un octet, jumătate de cuvânt (

) și cuvinte într-un registru de 64 de biți folosind opcodes

respectiv.

Câmp de comentarii.

Acest câmp oferă explicații despre acțiunile programului. Comentariile nu afectează funcționarea programului și sunt destinate oamenilor. Ele pot fi necesare pentru a modifica un program, care fără astfel de comentarii poate fi complet de neînțeles chiar și pentru programatorii experimentați. Un comentariu începe cu un simbol și este folosit pentru a explica și documenta programe. Caracterul de început al unui comentariu poate fi:

● punct și virgulă (;) în limbile pentru procesoarele companiei

Semn de exclamare(!) în limbi pentru

Fiecare linie de comentariu separată este precedată de un caracter principal.

Pseudo-comenzi (directive).

În limbajul de asamblare există două tipuri principale de comenzi:

de bază instrucțiuni care sunt echivalentul codului mașinii procesorului. Aceste comenzi efectuează toate procesările prevăzute de program;

pseudo-comenzi sau directive, conceput pentru a deservi procesul de traducere a unui program într-un limbaj de combinare de coduri. Ca exemplu în tabel. 5.2.2 prezintă câteva pseudo-comenzi de la asamblator

pentru familie

.

La programare, sunt situații în care, conform algoritmului, același lanț de comenzi trebuie repetat de mai multe ori. Pentru a ieși din această situație puteți:

● scrieți secvența necesară de comenzi ori de câte ori apare. Această abordare duce la o creștere a volumului programului;

● aranjați această secvență într-o procedură (subrutină) și apelați-o dacă este necesar. Această ieșire are dezavantajele sale: de fiecare dată trebuie să executați o comandă de apel de procedură specială și o comandă de returnare, care, dacă secvența este scurtă și utilizată frecvent, poate reduce foarte mult viteza programului.

Cel mai simplu și metoda eficienta repetarea repetată a unui lanț de comenzi constă în folosirea macro, care poate fi reprezentată ca o pseudo-comandă concepută pentru a retraduce un grup de comenzi des întâlnite într-un program.

O macrocomandă sau macrocomandă se caracterizează prin trei aspecte: macrodefiniție, macroinversie și macroextensie.

Definiție macro

Aceasta este o desemnare pentru o secvență repetată în mod repetat de comenzi de program, folosită pentru referințe în textul programului.

Definiția macro are următoarea structură:

Lista de expresii; Definiție macro

În structura dată de macro-definiție, se pot distinge trei părți:

● titlu

macro, inclusiv numele

Pseudo-comandă

și un set de parametri;

● marcate cu puncte corp macro;

● echipa

absolvire

definiții macro.

Setul de parametri de definiție macro conține o listă cu toți parametrii dați în câmpul operand pentru grupul de instrucțiuni selectat. Dacă acești parametri au fost indicați mai devreme în program, atunci nu trebuie să fie indicați în antetul definiției macro.

Pentru a reasambla grupul selectat de comenzi, se folosește un apel constând din nume

comenzi macro și listă de parametri cu alte valori.

Când asamblatorul întâlnește o definiție de macro în timpul procesului de compilare, o stochează în tabelul de definiții de macro. La aparițiile ulterioare în programul numelui (

) a unei macrocomenzi, asamblatorul o înlocuiește cu corpul macro-ului.

Utilizarea unui nume de macrocomandă ca opcode este apelată macro-inversare(apel macro) și înlocuirea acestuia cu corpul macro-ului - extinderea macro.

Dacă un program este reprezentat ca o secvență de caractere (litere, numere, spații, semne de punctuație și întoarceri de cărucior pentru a trece la o nouă linie), atunci extinderea macro constă în înlocuirea unor lanțuri din această secvență cu alte lanțuri.

Extinderea macro-ului are loc în timpul procesului de asamblare, nu în timpul execuției programului. Le sunt atribuite metode de manipulare a șirurilor de caractere macro înseamnă.

Procesul de asamblare este efectuat in doua treceri:

● La prima trecere, toate definițiile macro sunt păstrate, iar apelurile macro sunt extinse. În acest caz, programul original este citit și convertit într-un program în care toate definițiile macro sunt eliminate și fiecare apel de macro este înlocuit cu corpul macro-ului;

● a doua trecere procesează programul rezultat fără macro-uri.

Macro-uri cu parametri.

Pentru a lucra cu secvențe repetate de comenzi, ai căror parametri pot lua valori diferite, sunt furnizate definiții macro:

● cu real parametrii care sunt plasați în câmpul operand al apelului macro;

● cu formal parametrii. În timpul extinderii macro, fiecare parametru formal care apare în corpul macro-ului este înlocuit cu parametrul real corespunzător.

folosind macro-uri cu parametri.

Programul 1 conține două secvențe similare de comenzi, care diferă prin faptul că prima schimbă P și

Iar al doilea

Programul 2 include o macro cu doi parametri formali P1 și P2. În timpul extinderii macro, fiecare caracter P1 din corpul macro este înlocuit cu primul parametru real (P,

), iar simbolul P2 este înlocuit cu al doilea parametru real (

) din programul nr. 1. În apelul macro

programul 2 este marcat: P,

Primul parametru real,

Al doilea parametru real.

Programul 1

Programul 2

MOV EBX,Q MOV EAX,Pl

MOV Q,EAX MOV EBX,P2

MOV P,EBX MOV P2,EAX

Capabilitati extinse.

Să ne uităm la câteva caracteristici avansate ale limbii

Dacă o macrocomandă care conține o comandă de salt condiționat și o etichetă la care trebuie sărită este apelată de două sau de mai multe ori, eticheta va fi duplicată (problema cu eticheta duplicată), ceea ce va cauza o eroare. Prin urmare, fiecare apel atribuie o etichetă separată ca parametru (de către programator). În limbaj

eticheta este declarată locală (

) și datorită capabilităților avansate, asamblatorul generează automat o etichetă diferită de fiecare dată când macro-ul este extins.

vă permite să definiți macrocomenzi în interiorul altor macrocomenzi. Această caracteristică avansată este foarte utilă în combinație cu legarea condiționată a unui program. Sa luam in considerare

IF WORDSIZE GT 16 M2 MACRO

Macro-ul M2 poate fi definit în ambele părți ale declarației

Cu toate acestea, definiția depinde de procesorul pe care este asamblat programul: 16 biți sau 32 de biți. Dacă M1 nu este apelat, atunci macro M2 nu va fi definită deloc.

O altă caracteristică avansată este că macrocomenzile pot apela alte macrocomenzi, inclusiv ele însele - recursiv apel. În acest din urmă caz, pentru a evita o buclă fără sfârșit, macro-ul trebuie să-și transmită un parametru care se modifică cu fiecare extindere și, de asemenea, Verifica acest parametru și încheie recursiunea când parametrul atinge o anumită valoare.

Despre utilizarea mijloacelor macro în asamblare.

Când utilizați macrocomenzi, asamblatorul trebuie să poată îndeplini două funcții: salvați definițiile macroȘi extinde provocările macro.

Salvarea definițiilor macro.

Toate numele macrocomenzilor sunt stocate într-un tabel. Fiecare nume este însoțit de un indicator către macrocomanda corespunzătoare, astfel încât să poată fi apelat dacă este necesar. Unii asamblatori au un tabel separat pentru numele macro-urilor, alții au un tabel general în care, împreună cu numele macro-urilor, se află toate instrucțiunile și directivele mașinii.

Când întâlniți o macrocomandă în timpul asamblarii este creat:

nou element de masă cu numele macro-ului, numărul de parametri și un pointer către un alt tabel de definire a macrocomenzii în care va fi stocat corpul macro-ului;

● listă formal parametrii.

Corpul macrocomenzii, care este pur și simplu un șir de caractere, este apoi citit și stocat în tabelul de definire a macrocomenzii. Parametrii formali care apar în corpul buclei sunt marcați caracter special.

Reprezentarea internă a unei macrocomenzi

din exemplul de mai sus pentru programul 2 (p. 244) este:

MOV EAX, MOV EBX, MOV MOV &

unde punctul și virgulă este folosit ca caracter de returnare a căruciorului, iar ampersand & este folosit ca caracter parametru formal.

Extinderea apelurilor macro.

Ori de câte ori o definiție macro este întâlnită în timpul asamblarii, aceasta este stocată în tabelul macro. Când este apelată o macrocomandă, asamblatorul oprește temporar citirea datelor de intrare de pe dispozitivul de intrare și începe să citească corpul macro-ului stocat. Parametrii formali extrași din corpul macro sunt înlocuiți cu parametri reali și furnizați de apel. Parametrii ampersand & before permit asamblatorului să-i recunoască.

În ciuda faptului că există multe versiuni de asamblare, procesele de asamblare au caracteristici comune și sunt similare în multe privințe. Funcționarea unui asamblator cu două treceri este discutată mai jos.

Asamblator cu două treceri.

Un program constă dintr-un număr de declarații. Prin urmare, s-ar părea că la asamblare, puteți utiliza următoarea secvență de acțiuni:

● traducerea acestuia în limbajul mașinii;

● transferați codul mașinii rezultat într-un fișier, iar partea corespunzătoare a listei într-un alt fișier;

● repetați procedurile enumerate până când întregul program este tradus.

Cu toate acestea, această abordare nu este eficientă. Un exemplu este așa-numita problemă link direct. Dacă prima instrucțiune este un salt la instrucțiunea P, situată la sfârșitul programului, atunci asamblatorul nu o poate traduce. Mai întâi trebuie să determine adresa operatorului P, iar pentru a face acest lucru trebuie să citească întregul program. Fiecare citire completă a programului sursă este apelată trecere. Să arătăm cum puteți rezolva problema link-ului anticipat folosind două treceri:

la prima trecere ar trebui colectareași stocați toate definițiile simbolurilor (inclusiv etichetele) în tabel, iar la a doua trecere, citiți și asamblați fiecare operator. Această metodă este relativ simplă, dar o a doua trecere prin programul original necesită timp suplimentar petrecut cu operațiunile I/O;

● la prima trecere ar trebui convertit programul într-o formă intermediară și salvați-l într-un tabel și efectuați a doua trecere nu conform programului original, ci conform tabelului. Această metodă de asamblare economisește timp, deoarece a doua trecere nu efectuează operațiuni I/O.

Prima trecere.

Gol din prima pasă- construiți un tabel de simboluri. După cum sa menționat mai sus, un alt obiectiv al primei treceri este păstrarea tuturor definițiilor macro și extinderea apelurilor pe măsură ce apar. În consecință, atât definirea simbolului, cât și extinderea macro au loc într-o singură trecere. Simbolul poate fi oricare eticheta, sau sens, căruia i se atribuie un nume specific folosind directiva -you:

;Valoare - dimensiunea tamponului

Atribuind semnificații numelor simbolice în câmpul de etichetă a comenzii, asamblatorul specifică în esență adresele pe care fiecare comandă le va avea în timpul execuției programului. În acest scop, asamblatorul stochează în timpul procesului de asamblare contor de adrese de instrucțiuni(

) ca o variabilă specială. La începutul primei treceri, valoarea variabilei speciale este setată la 0 și crește după fiecare comandă procesată de lungimea acelei comenzi. Ca exemplu în tabel. 5.2.3 prezintă un fragment de program care indică lungimea comenzilor și valorile contorului. La prima trecere, sunt generate tabele nume simbolice, directiveȘi coduri de operare, iar dacă este necesar literal masa. Un literal este o constantă pentru care asamblatorul își rezervă automat memorie. Să remarcăm imediat că procesoarele moderne conțin instrucțiuni cu adrese imediate, astfel încât asamblatorii lor nu acceptă literale.

Tabel cu nume de simbol

conține câte un element pentru fiecare nume (Tabelul 5.2.4). Fiecare element al tabelului de nume simbolice conține numele în sine (sau un indicator către acesta), valoarea sa numerică și, uneori, câteva informații suplimentare, care pot include:

● lungimea câmpului de date asociat simbolului;

● biți de realocare a memoriei (care indică dacă valoarea unui simbol se modifică dacă programul este încărcat la o adresă diferită de cea prevăzută de asamblator);

● informații despre dacă simbolul poate fi accesat din afara procedurii.

Numele simbolice sunt etichete. Ele pot fi specificate folosind operatori (de exemplu,

Tabel directiv.

Acest tabel listează toate directivele, sau pseudo-comenzile, care sunt întâlnite la asamblarea unui program.

Tabelul de coduri de operare.

Pentru fiecare cod de operare, tabelul are coloane separate: denumirea codului de operare, operandul 1, operandul 2, valoarea hexazecimală a codului de operare, lungimea comenzii și tipul comenzii (Tabelul 5.2.5). Codurile de operare sunt împărțite în grupuri în funcție de numărul și tipul operanzilor. Tipul de comandă determină numărul grupului și specifică procedura care este apelată pentru a procesa toate comenzile din acel grup.

A doua trecere.

Golul celei de-a doua pasi- realizarea unui program obiect si tiparirea, daca este cazul, a protocolului de asamblare; informațiile de ieșire necesare pentru linker pentru a lega procedurile care au fost asamblate la momente diferite într-un singur fișier executabil.

În a doua trecere (ca și în prima), rândurile care conțin declarațiile sunt citite și procesate unul câte unul. Operatorul original și operatorul de ieșire derivat din acesta în hexazecimal obiect Codul poate fi tipărit sau plasat într-un buffer pentru imprimare ulterioară. După resetarea contorului de adrese de comandă, comanda este apelată următoarea declarație.

Programul sursă poate conține erori, de exemplu:

simbolul dat nu este definit sau este definit de mai multe ori;

● opcode-ul este reprezentat de un nume nevalid (din cauza unei greșeli de scriere), nu are destui operanzi sau are prea mulți operanzi;

● fără operator

Unii asamblatori pot detecta un simbol nedefinit și îl pot înlocui. Cu toate acestea, în majoritatea cazurilor, când întâlnește o declarație de eroare, asamblatorul afișează un mesaj de eroare pe ecran și încearcă să continue procesul de asamblare.

Articole dedicate limbajului de asamblare.

Subiectul 2.5 Bazele programării procesoarelor

Pe măsură ce durata programului crește, devine din ce în ce mai dificil să vă amintiți codurile diferitelor operațiuni. Mnemonicii oferă o oarecare asistență în acest sens.

Se numește limbajul de codificare a comenzilor simbolice asamblator.

limbaj de asamblare este o limbă în care fiecare enunț corespunde exact unei comenzi de mașină.

Asamblare numită convertirea unui program din limbajul de asamblare, adică pregătirea unui program în limbajul mașinii prin înlocuirea denumirilor simbolice ale operațiilor cu coduri de mașină și adreselor simbolice cu numere absolute sau relative, precum și încorporarea programelor de bibliotecă și generarea de secvențe de instrucțiuni simbolice prin specificarea unor parametri specifici în micro-echipe. Acest program localizat de obicei în ROM sau introdus în RAM de pe unele medii externe.

Limbajul de asamblare are mai multe caracteristici care îl deosebesc de limbajele de nivel înalt:

1. Aceasta este o corespondență unu-la-unu între instrucțiunile limbajului de asamblare și instrucțiunile mașinii.

2. Un programator în limbaj de asamblare are acces la toate obiectele și instrucțiunile prezente pe mașina țintă.

Înțelegerea elementelor de bază ale programării în limbaje orientate pe mașină este utilă pentru:



O mai bună înțelegere a arhitecturii PC-ului și o utilizare mai competentă a computerelor;

Dezvoltarea unor structuri mai raționale de algoritmi pentru programe de rezolvare a problemelor aplicate;

Posibilitatea de a vizualiza și corecta programe executabile cu extensia .exe și .com, compilate din orice limbaj de nivel înalt, în caz de pierdere a programelor sursă (prin apelarea programelor specificate în depanatorul programului DEBUG și decompilarea afișajului lor în asamblare limba);

Compilarea de programe pentru rezolvarea celor mai critice probleme (un program scris într-un limbaj orientat către mașină este de obicei mai eficient - mai scurt și mai rapid cu 30-60 la sută din programele obținute ca urmare a traducerii din limbi de nivel înalt)

Să implementeze procedurile incluse în programul principal sub formă de fragmente separate în cazul în care acestea nu pot fi implementate nici în limbajul de nivel înalt folosit, nici folosind procedurile de service OS.

Un program în limbaj de asamblare poate rula doar pe o singură familie de computere, în timp ce un program scris într-un limbaj de nivel înalt poate rula pe diferite mașini.

Alfabetul limbajului de asamblare este format din caractere ASCII.

Numerele sunt doar numere întregi. Sunt:

Numerele binare se termină cu litera B;

Numerele zecimale care se termină cu litera D;

Numerele hexazecimale se termină cu litera H.

RAM, registre, prezentare date

Pentru o anumită serie de MP, se folosește un limbaj de programare individual - limbajul de asamblare.

Limbajul de asamblare ocupă o poziție intermediară între codurile de mașină și limbajele de nivel înalt. Programarea în acest limbaj este mai ușoară. Un program în limbaj de asamblare folosește mai eficient capacitățile unei anumite mașini (mai precis, un MP) decât un program într-un limbaj de nivel înalt (care este mai simplu pentru un programator decât pentru asamblator). Să ne uităm la principiile de bază ale programării în limbaje orientate spre mașină, folosind exemplul de limbaj de asamblare pentru MP KR580VM80. Se folosește o metodologie generală pentru a programa în limbaj. Tehnicile tehnice specifice pentru înregistrarea programelor sunt asociate cu caracteristicile arhitecturii și sistemului de comandă al MP țintă.

Model software sistem cu microprocesor bazat pe MP KR580VM80

Modelul software al MPS în conformitate cu figura 1

Porturi MP Memorie

S Z A.C. P C

Poza 1

Din punctul de vedere al programatorului, MP KR580VM80 are următoarele registre accesibile programului.

A– Registrul acumulator de 8 biți. Este registrul principal al parlamentarului. Orice operație efectuată într-o ALU implică plasarea unuia dintre operanzii care urmează să fie procesați în acumulator. Rezultatul unei operații în ALU este de obicei stocat în A.

B, C, D, E, H, L– registre de uz general pe 8 biți (GPR). Memoria interioară MP. Conceput pentru a stoca informațiile prelucrate, precum și rezultatele operațiunii. La procesarea cuvintelor de 16 biți, registrele formează perechi BC, DE, HL, iar registrul dublu se numește prima literă - B, D, H. Într-o pereche de registre, cel mai mare este primul registru. Registrele H și L au o proprietate specială, folosită atât pentru stocarea datelor, cât și pentru stocarea adreselor pe 16 biți ale celulelor RAM.

FL– registru de pavilion (registru de semne) registru de 8 biți în care sunt stocate cinci semne ale rezultatului efectuării operațiilor aritmetice și logice în MP. Format FL conform imaginii

Bit C (CY - carry) - carry, setat la 1 dacă a existat o carry din ordinea înaltă a octetului la efectuarea operațiilor aritmetice.

Bit P (paritate) – paritate, setat la 1 dacă numărul de biți ai rezultatului este par.

Cifra AC este un transport suplimentar, conceput pentru a stoca valoarea de transport din tetrada de ordin inferioară a rezultatului.

Bit Z (zero) – setat la 1 dacă rezultatul operației este 0.

Bit S (semn) – este setat la 1 dacă rezultatul este negativ și la 0 dacă rezultatul este pozitiv.

SP– stack pointer, un registru de 16 biți, conceput pentru a stoca adresa celulei de memorie unde a fost scris ultimul octet introdus pe stivă.

RS– contor de programe (contor de programe), un registru de 16 biți, conceput pentru a stoca adresa următoarei instrucțiuni de executat. Conținutul contorului programului este incrementat automat cu 1 imediat după preluarea următorului octet de instrucțiune.

Zona de memorie inițială a adresei 0000Н – 07FF conține programul de control și programele demonstrative. Aceasta este zona ROM.

0800 – 0AFF - zona de adresă pentru înregistrarea programelor aflate în studiu. (RAM).

0В00 – 0ВВ0 - zonă de adresă pentru scrierea datelor. (RAM).

0ВВ0 – adresa de pornire a stivei. (RAM).

O stivă este o zonă special organizată de RAM destinată stocării temporare a datelor sau adreselor. Ultimul număr scris în stivă apare primul. Indicatorul de stivă stochează adresa ultimei celule de stivă în care sunt scrise informații. Când este apelată o subrutină, adresa de retur la programul principal este stocată automat pe stivă. De regulă, la începutul fiecărei subrutine, conținutul tuturor registrelor implicate în execuția acesteia este salvat pe stivă, iar la sfârșitul subrutinei acestea sunt restaurate din stivă.

Formatul datelor și structura de comandă a limbajului de asamblare

Memoria MP KR580VM80 este o matrice de cuvinte de 8 biți numite octeți.Fiecare octet are propria sa adresă de 16 biți, care determină poziția sa în secvența celulelor de memorie. MP-ul poate adresa 65536 de octeți de memorie, care pot fi conținute atât în ​​ROM, cât și în RAM.

Format de date

Datele sunt stocate în memorie ca cuvinte de 8 biți:

D7 D6 D5 D4 D3 D2 D1 D0

Bitul cel mai puțin semnificativ este bitul 0, cel mai semnificativ bit este bitul 7.

O comandă se caracterizează prin formatul său, adică numărul de biți alocați pentru ea, care sunt împărțiți octet cu octet în anumite câmpuri funcționale.

Format de comandă

Comenzile MP KR580VM80 au format de unul, doi sau trei octeți. Comenzile multibyte trebuie plasate în limbi adiacente. Formatul comenzii depinde de specificul operației efectuate.

Primul octet al comenzii conține codul operației, scris sub formă mnemonică.

Determină formatul comenzii și acțiunile care trebuie efectuate de către MP asupra datelor în timpul executării acestora, precum și metoda de adresare și poate conține, de asemenea, informații despre locația datelor.

Al doilea și al treilea octet pot conține date pentru care se efectuează operațiuni sau adrese care indică locația datelor. Datele asupra cărora sunt efectuate acțiunile se numesc operanzi.

Format de comandă pe un singur octet conform Figura 2

Figura 4

În comenzile limbajului de asamblare, codul de operare are o formă scurtă de scriere a cuvintelor în limba engleză - o notație mnemonică. Mnemotecnia (de la grecescul mnemonic - arta memorării) facilitează rememorarea comenzilor prin scopul lor funcțional.

Înainte de execuție, programul sursă este tradus folosind un program de traducere numit assembler în limbajul combinațiilor de cod - limbaj mașină, sub această formă este plasat în memoria MP-ului și apoi este folosit la executarea comenzii.


Metode de adresare

Toate codurile operanzilor (intrare și ieșire) trebuie să fie localizate undeva. Ele pot fi localizate în registrele interne ale MP (cele mai convenabile și varianta rapida). Ele pot fi amplasate în memorie de sistem(cea mai comună opțiune). În cele din urmă, acestea pot fi localizate în dispozitivele I/O (cel mai rar caz). Locația operanzilor este determinată de codul de instrucțiune. Exista metode diferite, cu care codul de instrucțiune poate determina unde să ia operandul de intrare și unde să plaseze operandul de ieșire. Aceste metode se numesc metode de adresare.

Pentru MP KR580VM80, există următoarele metode de adresare:

Direct;

Inregistreaza-te;

Indirect;

Stivuite.

Direct adresarea presupune că operandul (de intrare) este localizat în memorie imediat după codul de instrucțiune. Operandul este de obicei o constantă care trebuie trimisă undeva, adăugată la ceva etc. datele sunt conținute în al doilea sau al doilea și al treilea octet al comenzii, cu octetul mic de date situat în al doilea octet al comenzii, iar octetul înalt în al treilea octet de comandă.

Drept Adresarea (aka absolută) presupune că operandul (de intrare sau de ieșire) este localizat în memorie la adresa, al cărei cod este localizat în interiorul programului imediat după codul de instrucțiune. Folosit în comenzi de trei octeți.

Inregistreaza-te adresarea presupune că operandul (intrare sau ieșire) se află în registrul intern al MP. Folosit în comenzile pe un singur octet

Indirect Adresarea (implicita) presupune că registrul intern al MP conține nu operandul în sine, ci adresa sa în memorie.

Grămadă adresarea presupune că comanda nu conține o adresă. Adresarea celulelor de memorie folosind conținutul registrului SP de 16 biți (pointer de stivă).

Sistem de comandă

Sistemul de comandă MP este o listă completă de acțiuni elementare pe care MP este capabil să le efectueze. MP controlat de aceste comenzi efectuează acțiuni simple, cum ar fi operații aritmetice și logice elementare, transfer de date, compararea a două valori etc. Numărul de comenzi al MP KR580VM80 este de 78 (ținând cont de modificările 244).

Se disting următoarele grupuri de comenzi:

Transmitere de date;

Aritmetic;

Joc de inteligență;

Comenzi de salt;

Comenzi de intrare/ieșire, control și stiva.


Simboluri și abrevieri folosite la descrierea comenzilor și la compunerea programelor

Simbol Reducere
ADDR adresa pe 16 biți
DATE date pe 8 biți
DATE 16 date pe 16 biți
PORT Adresa dispozitivului I/O pe 8 biți
BYTE 2 Al doilea octet al comenzii
BYTE 3 Al treilea octet de comandă
R, R1, R2 Unul dintre registrele: A, B, C, D, E, H, L
R.P. Una dintre perechile de registre: B - precizează perechea BC; D - specifică o pereche DE; H – specifică perechea HL
RH Primul registru al perechii
R.L. Al doilea registru al perechii
Λ Înmulțirea logică
V Adăugarea logică
Adăugarea modulo doi
M O celulă de memorie a cărei adresă specifică conținutul perechii de registre HL, adică M = (HL)

1. Arhitectura PC………………………………………………………………………………5

    1.1. Registrele.

    1.1.1 Registre de uz general.

1.1.2. Registre de segmente

1.1.3 Registrul steagurilor

1.2. Organizarea memoriei.

1.3. Prezentarea datelor.

1.3.1 Tipuri de date

1.3.2 Reprezentarea caracterelor și șirurilor de caractere

2. Instrucțiuni de program în asamblator ……………………………………

    1. Comenzi în limbaj de asamblare

2.2. Moduri de adresare și formate de instrucțiuni ale mașinii

3. Pseudo-operatori………………………………………………………………….

3.1 Directive privind definirea datelor

3.2 Structura unui program de asamblare

3.2.1 Segmente de program. asuma directivă

3.2.3 Directiva de segmentare simplificată

4. Asamblarea și alcătuirea programului ………………………….

5. Comenzi de transfer de date…………………………………………………….

    5.1 Comenzi generale

    5.2 Stivuiți comenzi

5.3 Comenzi I/O

5.4 Comenzi de redirecționare a adresei

5.5 Marcați comenzile de redirecționare

6. Comenzi aritmetice…………………………………………………….

    6.1 Operații aritmetice pe numere întregi binare

6.1.1 Adunarea și scăderea

6.1.2 Comenzi pentru creșterea și decrementarea receptorului cu una

6.2 Înmulțirea și împărțirea

6.3 Schimbarea semnului

7. Operații logice…………………………………………………….

8. Schimbări și schimbări ciclice………………………………………………………

9. Operații cu șiruri…………………………………………………….

10. Logica și organizarea programelor………………………………………………

10.1 Salturi necondiționate

10.2 Salturi condiționate

10.4 Proceduri în limbaj de asamblare

10.5 INT Întreruperi

10.6 Software de sistem

10.6.1.1 Citirea tastaturii.

10.6.1.2 Afișarea caracterelor pe ecran

10.6.1.3 Încheierea programelor.

10.6.2.1 Selectarea modurilor de afișare

11. Memoria discului………………………………………………………………………..

11.2 Tabel de distribuție a fișierelor

11.3 Operațiuni I/O pe disc

11.3.1 Scrierea unui fișier pe disc

11.3.1.1 Date ASCIIZ

11.3.1.2 Numărul dosarului

11.3.1.3 Crearea unui fișier disc

11.3.2 Citirea unui fișier disc

Introducere

Limbajul de asamblare este o reprezentare simbolică a limbajului mașină. Toate procesele dintr-un computer personal (PC) la cel mai scăzut nivel hardware sunt conduse numai de comenzi (instrucțiuni) în limbajul mașinii. Este imposibil să rezolvi cu adevărat probleme legate de hardware (sau chiar, mai mult, dependente de hardware, precum creșterea vitezei unui program), fără cunoștințe de asamblare.

Asamblatorul este o formă convenabilă de comenzi direct pentru componentele PC și necesită cunoașterea proprietăților și capabilităților circuitului integrat care conține aceste componente, și anume microprocesorul PC. Astfel, limbajul de asamblare este direct legat de organizarea internă a PC-ului. Și nu este o coincidență faptul că aproape toate compilatoarele de limbaj de nivel înalt acceptă accesul la nivelul de asamblare al programarii.

Un element al pregătirii unui programator profesionist este în mod necesar studiul asamblatorului. Acest lucru se datorează faptului că programarea în limbaj de asamblare necesită cunoștințe de arhitectură PC, ceea ce vă permite să creați programe mai eficiente în alte limbi și să le combinați cu programele în limbaj de asamblare.

Manualul discută despre programarea în limbaj de asamblare pentru computere bazate pe microprocesoare Intel.

Acest tutorial se adresează tuturor celor care sunt interesați de arhitectura procesorului și de elementele de bază ale programării în limbaj Asamblare, în primul rând dezvoltatorilor de produse software.

    Arhitectura PC.

Arhitectura computerului este o reprezentare abstractă a unui computer, care reflectă organizarea sa structurală, circuitele și logică.

Toate computerele moderne au unele proprietăți arhitecturale comune și individuale. Proprietățile individuale sunt unice pentru un anumit model de computer.

Conceptul de arhitectură computerizată include:

    diagramă bloc computer;

    mijloace și metode de acces la elemente ale diagramei bloc computerizate;

    setarea și disponibilitatea registrelor;

    organizarea si metodele de adresare;

    metoda de prezentare si formatare a datelor computerizate;

    un set de instrucțiuni pentru computer;

    formate de instrucțiuni ale mașinii;

    manipularea întreruperii.

Elementele principale ale hardware-ului computerului: unitatea de sistem, tastatura, dispozitivele de afișare, unitățile de disc, dispozitivele de imprimare (imprimantă) și diverse echipamente de comunicații. Unitate de sistem constă dintr-o placă de bază, sursă de alimentare și celule de expansiune pentru carduri suplimentare. Placa de sistem conține un microprocesor, memorie doar pentru citire (ROM), RAM(RAM) și coprocesor.

      Registrele.

În interiorul microprocesorului, informațiile sunt conținute într-un grup de 32 de registre (16 utilizator, 16 sistem), într-o măsură sau alta, disponibile pentru utilizare de către programator. Deoarece manualul este dedicat programării pentru microprocesorul 8088-i486, este cel mai logic să începeți acest subiect cu o discuție despre registrele interne ale microprocesorului care sunt accesibile utilizatorului.

Registrele utilizatorilor sunt folosite de programator pentru a scrie programe. Aceste registre includ:

    opt registre pe 32 de biți (registruri de uz general) EAX/AX/AH/AL, EBX/BX/BH/BL, ECX/CX/CH/CL, EDX/DX/DLH/DL, EBP/BP, ESI/SI, EDI/DI, ESP/SP;

    șase registre de segmente de 16 biți: CS, DS, SS, ES, FS, GS;

    registre de stare și control: registru de steag EFLAGS/FLAGS și registru de indicator de comandă EIP/IP.

Părțile unui registru de 32 de biți sunt indicate printr-o bară oblică. Prefixul E (Extins) indică utilizarea unui registru de 32 de biți. Pentru a lucra cu octeți, se folosesc registre cu prefixele L (low) și H (high), de exemplu, AL, CH - indicând octeții mici și înalți ai părților de 16 biți ale registrelor.

        Registre de uz general.

EAX/AX/AH/AL (registru acumulator) – baterie. Folosit în înmulțire și împărțire, în operațiuni I/O și în unele operațiuni cu șir.

EBX/BX/BH/BL – registrul de bază(registru de bază), adesea folosit la adresarea datelor din memorie.

ECX/CX/CH/CL – tejghea(registru de numărare), folosit ca numărător pentru numărul de repetări ale buclei.

EDX/DX/DH/DL – registrul de date(registru de date), folosit pentru stocarea datelor intermediare. În unele echipe, utilizarea sa este obligatorie.

Toate registrele din acest grup permit accesul la părțile lor „inferioare”. Doar părțile inferioare de 16 și 8 biți ale acestor registre pot fi utilizate pentru auto-adresare. Cei 16 biți superiori ai acestor registre nu sunt disponibili ca obiecte independente.

Pentru a susține comenzile de procesare a șirurilor care permit procesarea secvențială a lanțurilor de elemente cu o lungime de 32, 16 sau 8 biți, se folosesc următoarele:

ESI/SI (registru index sursă) – index sursă. Conține adresa elementului sursă curent.

EDI/DI (registru index de destinație) – index receptor(destinatar). Conține adresa curentă în linia de destinație.

În arhitectura microprocesorului, o structură de date – o stivă – este suportată la nivel hardware și software. Există instrucțiuni speciale și registre speciale pentru lucrul cu stiva. Trebuie remarcat faptul că stiva este umplută către adrese mai mici.

ESP/SP (registru stivă pointer) – Inregistreaza-te indicator grămadă. Conține un indicator către partea de sus a stivei din segmentul de stivă curent.

EBP/BP (registru de punct de bază) – registru indicator de bază de stivă. Proiectat pentru a organiza accesul aleatoriu la date din interiorul stivei.

1.1.2. Registre de segmente

Modelul de software cu microprocesor are șase registre de segment: CS, SS, DS, ES, GS, FS. Existența lor se datorează organizării specifice și utilizării RAM de către microprocesoarele Intel. Hardware-ul microprocesorului suportă organizarea structurală a programului constând din segmente. Pentru a indica segmentele disponibile în acest moment sunt destinate registrelor de segmente. Microprocesorul acceptă următoarele tipuri de segmente:

    Segment de cod. Conține comenzi de program. Pentru a accesa acest segment, utilizați registrul CS (registru de segment de cod) - registrul codului de segment. Conține adresa segmentului de instrucțiuni al mașinii la care are acces microprocesorul.

    Segment de date. Conține date prelucrate de program. Pentru a accesa acest segment, utilizați registrul DS (registru de segment de date) - registrul de date segment, care stochează adresa segmentului de date al programului curent.

    Segment de stivă. Acest segment este o zonă de memorie numită stiva. Microprocesorul organizează stiva conform principiului - primul „înăuntru”, primul „ieșit”. Pentru a accesa stiva, utilizați registrul SS (registru de segmente de stivă) - registru de segmente de stivă, care conține adresa segmentului de stivă.

    Segment de date suplimentare. Datele prelucrate pot fi localizate în trei segmente de date suplimentare. În mod implicit, se presupune că datele se află în segmentul de date. Când se utilizează segmente de date suplimentare, adresele acestora trebuie specificate în mod explicit folosind prefixe speciale de înlocuire a segmentului în comandă. Adresele segmentelor de date suplimentare trebuie să fie conținute în registrele ES, GS, FS (registre de segmente de date de extensie).

        Registre de control și stare

Microprocesorul conține mai multe registre care conțin informații despre starea atât a microprocesorului în sine, cât și a programului ale cărui comenzi sunt încărcate în mod curent în conductă. Acest:

Registrul indicatorului de instrucțiuni EIP/IP;

    registru steag EFLAGS/FLAGS.

Folosind aceste registre, puteți obține informații despre rezultatele execuției comenzii și puteți influența starea microprocesorului în sine.

EIP/IP (registru pointer de instrucțiuni) – indicator echipe. Registrul EIP/IP are o lățime de 32 sau 16 biți și conține offset-ul următoarei instrucțiuni care urmează să fie executată în raport cu conținutul registrului de segment CS din segmentul de instrucțiune curent. Acest registru nu este direct accesibil, dar poate fi modificat folosind instrucțiuni de salt.

steaguri/steaguri (registru steaguri) – Inregistreaza-te steaguri. Dimensiunea biților 32/16 biți. Biții individuali ai acestui registru au un scop funcțional specific și sunt numiți steaguri. Un steag este un bit care ia valoarea 1 ("flag set") dacă o anumită condiție este îndeplinită, iar valoarea 0 ("flag cleared") în caz contrar. Partea inferioară a acestui registru este complet similară cu registrul FLAGS pentru i8086.

1.1.3 Registrul steagurilor

Registrul de steaguri este de 32 de biți și se numește EFLAGS (Fig. 1). Biții individuali ai registrului au un scop funcțional specific și sunt numiți steaguri. Fiecăruia dintre ele i se atribuie un nume specific (ZF, CF etc.). Cei 16 biți inferiori ai EFLAGS reprezintă registrul flag FLAGS de 16 biți utilizat la executarea programelor scrise pentru microprocesoarele i086 și i286.

Fig.1 Registrul steagului

Unele steaguri sunt denumite în mod obișnuit steaguri de condiție; se schimbă automat atunci când comenzile sunt executate și înregistrează anumite proprietăți ale rezultatului lor (de exemplu, dacă este egal cu zero). Alte steaguri se numesc steaguri de stat; se schimbă din program și influențează comportamentul ulterioară al procesorului (de exemplu, blochează întreruperile).

Steaguri de stare:

CF (drapel de transport) - poartă steagul. Ia valoarea 1 dacă, la adăugarea numerelor întregi, a apărut o unitate de transport care nu s-a „încadrat” în grila de biți sau dacă, la scăderea numerelor fără semn, prima dintre ele a fost mai mică decât a doua. În comenzile de schimbare, bitul care se află în afara grilei de biți este introdus în CF. CF surprinde, de asemenea, caracteristicile instrucțiunii de înmulțire.

OF (steagul de preaplin) - steag de revărsare. Setați la 1 dacă, la adăugarea sau scăderea numerelor întregi cu semn, rezultatul este un rezultat care depășește valoarea admisibilă în valoare absolută (mantisa a debordat și a „urcat” în cifra semnului).

ZF (steagul zero) - steag zero. Setați la 1 dacă rezultatul comenzii este 0.

SF (steagul semnului) - steag semn. Setați la 1 dacă o operație pe numerele cu semn produce un rezultat negativ.

PF (steagul de paritate) - steag paritate. Egal cu 1 dacă rezultatul comenzii următoare conține un număr par de binar. De obicei luate în considerare numai pentru operațiunile I/O.

AF (steagul de transport auxiliar) - steag de transport suplimentar. Fixează caracteristicile efectuării operațiilor pe numere zecimale binare.

Steaguri de stat:

DF (steagul de direcție) - steag de direcție. Setează direcția de vizualizare a liniilor în comenzile de linie: când DF=0, liniile sunt vizualizate „înainte” (de la început până la sfârșit), când DF=1 - în direcția opusă.

IOPL (nivel de privilegii de intrare/ieșire) – Nivel de privilegii I/O. Folosit în modul protejat de operare cu microprocesor pentru a controla accesul la comenzile I/O, în funcție de privilegiul sarcinii.

NT (sarcină imbricată) – steag de imbricare a sarcinilor. Folosit în modul protejat de operare cu microprocesor pentru a înregistra faptul că o sarcină este imbricată în alta.

Steagul de sistem:

IF (steagul de întrerupere) - steag de întrerupere. Când IF=0, procesorul nu mai răspunde la întreruperile de intrare; când IF=1, blocarea întreruperilor este eliminată.

TF (drapel de capcană) - urmă steag. Când TF=1, după executarea fiecărei comenzi, procesorul face o întrerupere (numerotată 1), care poate fi folosită la depanarea unui program pentru a-l urmări.

RF (steagul de reluare) – relua steag. Folosit la procesarea întreruperilor din registrele de depanare.

VM (mod virtual 8086) – steag virtual 8086. 1-procesor funcționează în modul virtual 8086. 0-procesor funcționează în mod real sau protejat.

AC (verificare aliniere) – steag de control al alinierii. Proiectat pentru a permite controlul alinierii la accesarea memoriei.

      Organizarea memoriei.

Se apelează memoria fizică la care are acces microprocesorul RAM ( sau memorie cu acces aleatoriu - RAM). RAM este un lanț de octeți care au propria lor adresă unică (numărul său), apelați fizic. Intervalul de valori ale adresei fizice este de la 0 la 4 GB. Mecanismul de gestionare a memoriei este în întregime hardware.

Hardware-ul microprocesorului acceptă mai multe modele de utilizare a memoriei RAM:

    model segmentat. În acest model, memoria pentru programe este împărțită în zone de memorie contigue (segmente), iar programul în sine poate accesa doar datele care se află în aceste segmente;

    modelul paginii. În acest caz, memoria RAM este considerată un set de blocuri cu o dimensiune fixă ​​de 4 KB. Aplicația principală a acestui model este legată de organizație memorie virtuala, care permite programelor să utilizeze mai mult spațiu de memorie decât memoria fizică. Pentru un microprocesor Pentium, dimensiunea memoriei virtuale posibile poate ajunge la 4 TB.

Utilizarea și implementarea acestor modele depind de modul de funcționare al microprocesorului:

    Modul adresa reală (mod real). Modul este similar cu funcționarea procesorului i8086. Necesar pentru funcționarea programelor dezvoltate pentru modelele de procesoare timpurii.

    Mod protejat. Modul protejat vă permite să efectuați mai multe sarcini procesarea informatiei, protecția memoriei folosind un mecanism de privilegii pe patru niveluri și organizarea sa de paginare.

    Mod virtual 8086.În acest mod, devine posibil să rulați mai multe programe pentru i8086. În acest caz, programele în mod real pot funcționa.

Segmentarea este un mecanism de adresare care asigură existența mai multor spații de adrese independente. Un segment este un bloc de memorie independent, suportat de hardware.

Fiecare program poate consta în general din orice număr de segmente, dar are acces direct la trei principale: cod, date și stivă - și de la unul până la trei segmente de date suplimentare. Sistemul de operare plasează segmente de program în RAM la anumite adrese fizice și apoi plasează valorile acestor adrese în registrele corespunzătoare. În cadrul unui segment, programul accesează liniar adrese relative la începutul segmentului, adică pornind de la adresa 0 și terminând cu o adresă egală cu dimensiunea segmentului. Adresa relativă sau părtinire, pe care microprocesorul îl folosește pentru a accesa datele dintr-un segment este numit efectiv.

Formarea unei adrese fizice în mod real

În modul real, intervalul de modificări ale adresei fizice este de la 0 la 1 MB. Dimensiunea maximă a segmentului este de 64 KB. Când contactați un anume adresă fizică RAM este determinată de adresa începutului segmentului și de decalajul din cadrul segmentului. Adresa de început a segmentului este preluată din registrul de segment corespunzător. În acest caz, registrul de segment conține doar cei mai semnificativi 16 biți ai adresei fizice a începutului segmentului. Cei patru biți minusți lipsă ai adresei de 20 de biți sunt obținuți prin deplasarea valorii registrului de segment la stânga cu 4 biți. Operația de schimbare se realizează în hardware. Valoarea rezultată de 20 de biți este adresa fizică reală corespunzătoare începutului segmentului. Acesta este adresa fizica este specificată ca o pereche „segment:offset”, unde „segment” este primii 16 biți ai adresei de pornire a segmentului de memorie căruia îi aparține celula, iar „offset” este adresa de 16 biți a acestei celule, numărată de la începutul acestui segment de memorie (valoarea 16 * segment +offset dă adresa absolută a celulei). Dacă, de exemplu, registrul CS stochează valoarea 1234h, atunci perechea de adrese 1234h:507h definește o adresă absolută egală cu 16*1234h+507h =12340h+507h = 12847h. O astfel de pereche este scrisă ca un cuvânt dublu și (ca pentru numere) într-o formă „inversată”: primul cuvânt conține un decalaj, iar al doilea - un segment, iar fiecare dintre aceste cuvinte, la rândul său, este prezentat într-un forma „inversată”. De exemplu, perechea 1234h:5678h ar fi scrisă astfel:| 78 | 56| 34 | 12|.

Acest mecanism de generare a unei adrese fizice face posibilă relocarea software-ului, adică independent de adresele de încărcare specifice din RAM.

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). Lungime maxima etichete – 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
  • Un 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 sala de operație sistem 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 pentru a marca sfârșitul cod sursa programe. 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