Cum se configurează smartphone-uri și PC-uri. Portal informativ
  • Acasă
  • OS
  • Principalele componente ale limbajului de asamblare și structura comenzilor. Caracteristici generale ale sistemului de comandă al limbajului Assembler pentru IBM-PC (set de comenzi de bază, metode de bază de adresare a operanzilor)

Principalele componente ale limbajului de asamblare și structura comenzilor. Caracteristici generale ale sistemului de comandă al limbajului Assembler pentru IBM-PC (set de comenzi de bază, metode de bază de adresare a operanzilor)

Comenzile pot fi distinse în funcție de scopul lor (în paranteze sunt exemple de coduri mnemonice de operații pentru comenzile de asamblare ale unui PC, cum ar fi IBM PC):

l efectuarea de operații aritmetice (ADD și ADC - adunare și adunare cu transfer, 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țiri nesemnate și semnate, CMP - comparații etc.) ;

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

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

l transfer de control (ramuri de program: JMP - ramură necondiționată, CALL - apel de procedură, RET - întoarcere din procedură, J * - ramură condiționată, LOOP - control de buclă etc.);

l procesarea șirurilor de caractere (MOVS - transferuri, CMPS - comparații, LODS - descă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ă în caz de depășire, IRET - întoarcere de la întrerupere);

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

O listă completă a comenzilor de asamblare poate fi găsită în lucrări.

Comenzi de transfer de date

l MOV dst, src - transfer de date (move - transfer 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 registru și memorie și, de asemenea, scrie o valoare imediată într-un registru sau memorie.

Operanzii dst și src trebuie să fie în același format de octet sau cuvânt.

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

mov AX, (152 + 101B) / 15

Expresia este evaluată numai în timpul traducerii. Nu schimbă steaguri.

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

l POP dst - scoateți un cuvânt din stivă (pop - pop; citiți din stivă în dst). Scoate un cuvânt din partea de sus a stivei și îl plasează în dst - orice registru de 16 biți (inclusiv segment) sau două locații de memorie. Steagurile nu se schimbă.

Introducere.

Se numește limba în care este scris programul original Intrare limba și limba în care este tradus pentru executare de către procesor-rom este sfârșit de săptămână limba. Procesul de conversie a unei limbi de intrare într-o limbă de ieșire este numit difuzat. Deoarece procesoarele sunt capabile să execute programe într-un limbaj mașină de coduri binare, care nu este folosit pentru programare, este necesară traducerea tuturor programelor sursă. Cunoscut doua feluri traduceri: compilare și interpretare.

La compilare programul original 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 compilatorul. Un compilator pentru care limbajul de intrare este o reprezentare simbolică a limbajului mașină (de ieșire) a codurilor binare se numește asamblator.

La interpretări fiecare linie a textului programului sursă este analizată (interpretată) și imediat executată comanda specificată în acesta. 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 sunt:

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

) se folosește mnemonicul

Scăderea (

inmultire (

Diviziuni (

și așa mai departe.Numele simbolice sunt folosite și pentru adresarea celulelor de memorie. Pentru programarea î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 afirmație se potrivește o comandă de mașină(cod), adică există o corespondență unu-la-unu între instrucțiunile 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 bitul de registru al steagurilor și un limbaj de nivel înalt (de exemplu,

) nu are această capacitate. Rețineți că limbajele pentru programarea sistemului (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ă timp. În ciuda acestui fapt, limbajul de asamblare a primit utilizare largă datorita urmatoarelor circumstante:

● un program scris în limbaj de asamblare este mult mai mic și 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, multe programe de sistem (inclusiv compilatoare), programe din cărți de credit, telefoane mobile, drivere de dispozitiv etc.;

● unele proceduri necesită acces complet la hardware, ceea ce de obicei nu este posibil într-un limbaj de nivel înalt. Acest caz include întreruperi și gestionari de întreruperi în sistemele de operare, precum și controlere de dispozitive în sistemele încorporate care funcționează î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 un asamblator, cât și unul dintre limbajele de nivel înalt.

Formatul operatorului în limbaj de asamblare.

Un program în limbaj de asamblare este o listă de comenzi (instrucții, 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. Există o coloană separată pentru fiecare câmp.

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:

● să facă un salt condiționat sau necondiționat la comandă;

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

Astfel de afirmații sunt etichetate. Pentru a desemna un nume, sunt folosite litere (majuscule) din alfabetul englez și numere. Numele trebuie să fie precedat de o literă și un separator de două puncte la sfârșit. O etichetă cu două puncte poate fi scrisă pe o linie separată, iar un cod operațional 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 operațional dacă acestea sunt situate pe linii separate.

În unele versiuni ale limbajului de asamblare, două puncte sunt plasate numai după etichetele de comandă, dar 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, câmpul de etichetă rămâne gol.

Câmpul pentru codul operațiunii.

Acest câmp conține codul mnemonic al comenzii sau pseudo-comenzii (vezi mai jos). Codul mnemonic al comenzilor este ales de designerii de limbaj. În limbaj de asamblare

mnemonic selectat pentru a încărca registrul din memorie

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

). În limbaje de asamblare

un singur nume poate fi folosit pentru ambele operațiuni, respectiv

Dacă alegerea numelor mnemonice poate fi arbitrară, atunci necesitatea de a folosi două instrucțiuni de mașină se datorează arhitecturii procesoarelor.

Mnemonicul registrului depinde și de versiunea de asamblare (Tabelul 5.2.1).

Câmp operand.

Informații suplimentare necesare pentru finalizarea operațiunii se găsesc aici. În domeniul operanzilor pentru instrucțiunile de salt este indicată adresa la care doriți să săriți, precum și adresele și registrele, care sunt operanzi pentru o instrucțiune de mașină. Ca exemplu, vom da operanzi care pot fi utilizați pentru procesoare pe 8 biți.

● date numerice,

prezentate în diverse sisteme numerice. Pentru a desemna sistemul numeric folosit, constanta este urmată de una dintre literele latine: B,

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

nu trebuie să-l notezi). 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 sistemul binar);

● identificatori,

pentru perechi de aeronave de înregistrare,

Primele litere B,

H; pentru o pereche de acumulatori și un registru de semne -

; pentru contorul de comenzi -

; pentru indicatorul de stivă -

● etichete care indică adresele operanzilor sau următoarele instrucțiuni din condițional

(dacă este îndeplinită condiția) și salturi neconditionate. 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ă modul în care este rezervat spațiul de date depinde de versiunea lingvistică. Dezvoltatori de limbaj de asamblare pentru

Definiți un cuvânt), iar ulterior a introdus o alternativă.

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

În versiune lingvistică

folosit de

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: ЕАХ - pentru plasarea operanzilor pe 32 de biți (tip

); АХ - pentru 16 biți (tip

și AH - pentru 8 biți (tip

● pentru procesoare

la fiecare opcode se adaugă sufixe: sufix

Pentru tip

; sufixul „.B” pentru tip

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

) și cuvintele din registrul pe 64 de biți, se folosesc 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 programul, 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 limbi pentru procesoarele companiei

● semnul exclamării (!) În limbi pentru

Fiecare linie de comentariu individuală este precedată de un caracter de început.

Pseudo-comenzi (directive).

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

de bază instrucțiuni care sunt echivalente cu codul mașină al procesorului. Aceste comenzi efectuează toate procesările oferite de program;

pseudo comenzi, sau directive, conceput pentru a deservi procesul de traducere a unui program în limbajul combinațiilor de coduri. De exemplu, în tabel. 5.2.2 sunt date câteva pseudo-comenzi de la ac-sampler

pentru familie

.

La programare există 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 dorită de comenzi ori de câte ori este întâlnită. Această abordare mărește dimensiunea programului;

● formaț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, cu o secvență scurtă și frecvent utilizată, poate reduce foarte mult viteza programului.

Cel mai simplu și eficient mod de a repeta un lanț de comenzi de mai multe ori este utilizarea macro, care poate fi gândită ca o pseudo-comandă concepută pentru a redifuza un grup de comenzi întâlnite frecvent într-un program.

O macro, sau macro, este caracterizată de trei aspecte: macro-definiție, macro-inversare și macro-extindere.

Definiție macro

Aceasta este o desemnare a unei secvențe repetate în mod repetat de comenzi de program, utilizată pentru legături în textul programului.

Definiția macro are următoarea structură:

Lista de expresii; Definiție macro

Trei părți pot fi distinse în structura de mai sus a unei macro-definiții:

● titlu

o macrocomandă care include un nume

Pseudo-comandă

și un set de parametri;

● marcate cu puncte corp macro;

● echipa

terminatii

macro-uri.

Setul de parametri de definiție macro conține o listă a tuturor parametrilor listați în câmpul operand pentru grupul de comenzi selectat. Dacă acești parametri sunt dați în program mai devreme, atunci aceștia pot fi omiși în antetul definiției macro.

Pentru a reasambla grupul selectat de comenzi, utilizați adresa constând din nume

macrocomenzi și o listă de parametri cu alte valori.

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

) al macrocomenzii, asamblatorul îl înlocuiește cu corpul macroului.

Utilizarea unui nume de macrocomandă ca opcode este apelată macro circulație(prin un apel macro), iar înlocuirea acestuia cu corpul macro-ului este extinderea macro.

Dacă programul este prezentat ca o secvență de caractere (litere, cifre, spații, semne de punctuație și întoarceri de cărucior pentru o nouă linie), atunci extinderea macro constă în înlocuirea unor șiruri din această secvență cu alte șiruri.

Extinderea macro-ului are loc în timpul procesului de asamblare, nu în timpul execuției programului. Modul de manipulare a șirurilor de caractere este responsabilitatea lui macrofonduri.

Procesul de asamblare este efectuat in doua treceri:

● la prima trecere, toate definițiile macro sunt salvate, 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;

● în a doua trecere, programul rezultat este procesat fără macro-uri.

Macro-uri parametrizate.

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

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

● cu formal parametrii. În procesul de extindere a macro-ului, fiecare parametru formal care apare în corpul macro-ului este înlocuit cu parametrul actual corespunzător.

folosind macro-uri cu parametri.

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

Iar al doilea

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

) și P2 este înlocuit cu al doilea parametru real (

) din programul nr 1. În macrozonă

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ă luăm în considerare câteva caracteristici avansate ale limbii

Dacă macrocomanda care conține comanda ramificație condiționată și eticheta la care se face ramificația este apelată de două sau mai multe ori, atunci eticheta va fi duplicată (problema etichetelor duplicate), ceea ce va provoca o eroare. Prin urmare, la fiecare apel, o etichetă separată este atribuită (de către programator) ca parametru. În limbaj

eticheta este declarată locală (

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

vă permite să definiți macrocomenzi în cadrul altor macrocomenzi. Această caracteristică avansată este foarte utilă atunci când este combinată cu legătura condiționată. Considera

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-ul 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 nu obține o buclă infinită, macro-ul trebuie să-și transmită un parametru, care se schimbă cu fiecare extindere și, de asemenea, Verifica acest parametru și încheie recursiunea când parametrul atinge o anumită valoare.

Despre utilizarea macrocomenzilor în asamblare.

Când utilizați macrocomenzi, asamblatorul trebuie să poată îndeplini două funcții: păstrează macro-definițiileși extinde apelurile macro.

Conservarea macro-urilor.

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, în timp ce 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 tabel cu numele macro-ului, numărul de parametri și un pointer către un alt tabel de definiții macro, unde va fi stocat corpul macro-ului;

● listă formal parametrii.

Apoi corpul macrocomenzii este citit și salvat în tabelul de definiții macro, care este doar un șir de simboluri. Parametrii formali găsiți în corpul buclei sunt marcați cu un simbol special.

Reprezentarea internă a unei macrocomenzi

din exemplul de mai sus pentru programul 2 (p. 244) arată astfel:

MOV EAX, MOV EBX, MOV MOV &

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

Extinderea apelurilor macro.

Ori de câte ori o macrocomandă este întâlnită în timpul asamblarii, aceasta este stocată în tabelul cu macrocomenzi. Când macro-ul este apelat, asamblatorul întrerupe temporar citirea intrării de pe dispozitivul de intrare și începe să citească corpul macro-ului salvat. Parametrii formali extrași din corpul macro-ului sunt înlocuiți cu parametrii actuali și furnizați de apel. Ampersantul și în fața parametrilor permite ca-sampler 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. Lucrarea asamblatorului cu două treceri este discutată mai jos.

Asamblator cu două treceri.

Programul este format dintr-un număr de operatori. 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 de mașină primit într-un fișier, iar partea corespunzătoare a listei - într-un alt fișier;

● repetați procedurile de mai sus până când întregul program a fost tradus.

Cu toate acestea, această abordare nu este eficientă. Un exemplu este așa-numita problemă link-uri anticipate. Dacă prima instrucțiune este un salt la instrucțiunea P situată la sfârșitul programului, atunci asamblatorul nu o poate traduce. El trebuie să determine mai întâi adresa operatorului P, iar pentru aceasta este necesar să citească întregul program. Fiecare citire completă a programului original este numită interval. Să vă arătăm cum puteți rezolva problema link-ului direct folosind două treceri:

urmează prima trecere a colectași salvaț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 a doua trecere prin programul original necesită timp suplimentar petrecut pe operațiunile I/O;

● la prima trecere, transforma program într-o formă intermediară și salvați-l în tabel și executați a doua trecere nu conform programului original, ci conform tabelului. Această metodă de asamblare economisește timp, deoarece nu se efectuează I/O la a doua trecere.

Prima trecere.

Prima trecere țintă- construiți un tabel de simboluri. După cum sa menționat mai sus, un alt obiectiv al primei treceri este păstrarea tuturor macrocomenzilor ș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:

; Valoare - dimensiunea tamponului

Prin atribuirea de valori numelor simbolice în câmpul de etichetă a instrucțiunii, asamblatorul stabilește în esență adresele pe care fiecare instrucțiune le va avea în timpul execuției programului. Pentru aceasta, asamblatorul în timpul procesului de asamblare salvează contor de adrese de comandă(

) ca o variabilă specială. La începutul primei treceri, valoarea variabilei speciale este setată la 0 și crește după fiecare comandă procesată cu lungimea acestei comenzi. De exemplu, în tabel. 5.2.3 arată un fragment al programului care indică lungimea comenzilor și valorile contorului. La prima trecere se formează mesele nume simbolice, directiveși opcodes, iar dacă este necesar literal masa. Un literal este o constantă pentru care asamblatorul își va rezerva automat memorie. Imediat, observăm că procesoarele moderne conțin instrucțiuni cu adrese imediate, astfel încât acsemblerele lor nu acceptă literale.

Tabel cu nume simbolice

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 arată dacă valoarea unui simbol se modifică dacă programul este încărcat la o adresă diferită de cea intenționată 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 operațional, tabelul oferă coloane separate: desemnarea codului operațional, operand 1, operand 2, valoarea hexazecimală a codului operațional, lungimea instrucțiunii și tipul instrucțiunii (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 acest grup.

A doua trecere.

Țintă de a doua pasă- crearea unui program obiect și tipărirea, dacă este cazul, a protocolului de asamblare; ieșirea informațiilor 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 enunțurile sunt citite și procesate una după alta. Operatorul original și derivat din acesta în ieșirea sistemului hexazecimal obiect codul poate fi tipărit sau stocat în tampon pentru imprimare ulterioară. După resetarea contorului adresei comenzii, este apelată următoarea instrucțiune.

Programul original poate conține erori, de exemplu:

simbolul dat este nedefinit sau definit de mai multe ori;

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

● nu există operator

Unii asamblatori pot prelua un caracter nedefinit și îl pot înlocui. Cu toate acestea, în majoritatea cazurilor, când detectează o instrucțiune cu o eroare, asamblatorul afișează un mesaj de eroare pe ecran și încearcă să continue procesul de asamblare.

Articole dedicate limbajului de asamblare.

Subiectul 1.4 Mnemonice asamblatorului. Structura și formatele comenzilor. Tipuri de adresare. Set de comenzi pentru microprocesor

Plan:

1 limbaj de asamblare. Noțiuni de bază

2 Simboluri în limbaj de asamblare

3 Tipuri de instrucțiuni de asamblare

4 Directive de adunare

5 Set de instrucțiuni pentru procesor

1 ilimbaj de asamblare. Noțiuni de bază

limbaj de asamblareeste o reprezentare simbolică a limbajului mașină. Toate procesele dintr-o mașină la cel mai scăzut nivel hardware sunt conduse numai de comenzile (instrucțiuni) în limbajul mașinii. Prin urmare, este clar că, în ciuda denumirii generale, limbajul de asamblare este diferit pentru fiecare tip de computer.

Un program în limbaj de asamblare este o colecție de blocuri de memorie numite segmente de memorie. Un program poate consta din unul sau mai multe astfel de segmente de bloc. Fiecare segment conține un set de propoziții de limbă, fiecare dintre acestea ocupând o linie separată de cod de program.

Propozițiile de adunare sunt de patru tipuri:

1) comenzi sau instrucțiuni, care sunt analogi simbolici ai instrucțiunilor mașinii. În procesul de traducere, instrucțiunile de asamblare sunt convertite în comenzile corespunzătoare ale setului de instrucțiuni ale microprocesorului;

2) macro-uri -propoziții din textul programului, formate într-un anumit mod, sunt înlocuite în timpul difuzării cu alte propoziții;

3) directive,care sunt instrucțiuni către traducătorul asamblator pentru a efectua unele acțiuni. Directivele nu au analog în reprezentarea mașinii;

4) linii de comentarii care conțin orice simboluri, inclusiv literele alfabetului rus. Comentariile sunt ignorate de traducător.

­ Structura unui program de asamblare. Sintaxa asamblatorului.

Propozițiile care alcătuiesc programul pot fi un construct sintactic corespunzător unei comenzi, macrocomenzi, directive sau comentarii. Pentru ca traducătorul asamblator să le recunoască, ele trebuie formate după anumite reguli sintactice. Cel mai bun mod de a face acest lucru este să folosiți o descriere formală a sintaxei limbii, cum ar fi regulile gramaticale. Cele mai comune moduri de a descrie un limbaj de programare ca acesta - diagrame de sintaxăși forme extinse Backus-Naur. Mai convenabil pentru utilizare practică diagrame de sintaxă. De exemplu, sintaxa propozițiilor de asamblare poate fi descrisă folosind diagramele de sintaxă prezentate în următoarele figuri 10, 11, 12.

Figura 10 - Format de propoziție de asamblare


­ Figura 11 - Formatul directivelor

­ Figura 12 - Formatul comenzilor și al macrocomenzilor

În aceste cifre:

­ numele etichetei- un identificator, a cărui valoare este adresa primului octet al acelei propoziții din textul sursă al programului, pe care îl desemnează;

­ Nume -identificator care distinge această directivă de alte directive cu același nume. Ca urmare a procesării unei directive specifice de către asamblator, acestui nume i se pot atribui anumite caracteristici;

­ opcode (COP) și directivă - sunt denumiri mnemonice ale instrucțiunii de mașină corespunzătoare, comenzii macro sau directivei de traducător;

­ operanzi -părți ale unei directive de comandă, macro sau asamblare care desemnează obiectele de manipulat. Operanzii de asamblare sunt descriși prin expresii cu constante numerice și text, etichete și identificatori de variabile folosind semne de operație și unele cuvinte rezervate.

Diagramele de sintaxă ajută găsiți și apoi treceți de la intrarea diagramei (stânga) la ieșirea acesteia (dreapta). Dacă o astfel de cale există, atunci propoziția sau construcția este corectă din punct de vedere sintactic. Dacă nu există o astfel de cale, atunci compilatorul nu va accepta această construcție.

­ 2 Simboluri în limbaj de asamblare

Caracterele permise atunci când scrieți textul programului sunt:

1) toate literele latine: A-Z,a-z... În acest caz, literele mari și mici sunt considerate echivalente;

2) numere de la 0 inainte de 9 ;

3) semne ? , @ , $ , _ , & ;

4) separatoare , . () < > { } + / * % ! " " ? = # ^ .

Propozițiile de asamblare sunt formate din jetoane, care sunt secvențe inseparabile sintactic de caractere valide ale limbii care au sens pentru traducător.

Lexeme sunt:

1) identificatori - secvențe de caractere valide utilizate pentru a desemna obiecte de program, cum ar fi coduri operaționale, nume de variabile și nume de etichete. Regula de scriere a identificatorilor este următoarea: un identificator poate consta din unul sau mai multe caractere;

2) șiruri de caractere - secvențe de caractere cuprinse între ghilimele simple sau duble;

3) numere întregi ale unuia dintre următoarele sisteme numerice : binar, zecimal, hexazecimal. Identificarea numerelor la scrierea lor în programele în limbaj de asamblare se realizează după anumite reguli:

4) numerele zecimale nu necesită simboluri suplimentare pentru identificarea lor, de exemplu 25 sau 139. Pentru identificare în codul sursă al programului numere binare este necesar după înregistrarea zerourilor și a celor care le alcătuiesc, puneți latinescul „ b”, De exemplu 10010101 b.

5) numerele hexazecimale au mai multe convenții atunci când sunt scrise:

În primul rând, ele constau din numere 0...9 , litere mici și mari ale alfabetului latin A,b, c,d,e,f sau A,B,C,D,E,F.

În al doilea rând, traducătorul poate avea dificultăți în recunoașterea numerelor hexazecimale din cauza faptului că acestea pot consta fie din cifre 0 ... 9 (de exemplu, 190845), fie să înceapă cu o literă din alfabetul latin (de exemplu, ef15). Pentru a „explica” traducătorului că un anumit token nu este un număr zecimal sau un identificator, programatorul trebuie să selecteze un număr hexazecimal într-un mod special. Pentru a face acest lucru, la sfârșitul secvenței de cifre hexazecimale care alcătuiesc un număr hexazecimal, scrieți litera latină „ h”. Aceasta este o condiție prealabilă. Dacă un număr hexazecimal începe cu o literă, atunci este scris un zero înainte: 0 ef15 h.

Aproape fiecare propoziție conține o descriere a obiectului asupra căruia sau cu ajutorul căruia se realizează o acțiune. Aceste obiecte sunt numite operanzi... Ele pot fi definite astfel: operanzi- sunt obiecte (unele valori, registre sau celule de memorie) asupra cărora se acționează instrucțiuni sau directive, sau sunt obiecte care definesc sau clarifică acțiunea instrucțiunilor sau directivelor.

Este posibil să se efectueze următoarea clasificare a operanzilor:

­ operanzi constanți sau imediati;

­ operanzi de adresă;

­ operanzi mobili;

contor de adrese;

­ registru operand;

­ operanzi de bază și index;

­ operanzi structurali;

înregistrări.

Operanzii sunt componente elementare din care se formează o parte a unei instrucțiuni de mașină, denotând obiectele pe care se efectuează o operație. Într-un caz mai general, operanzii pot fi incluși ca părți constitutive în formațiuni mai complexe, numite expresii.

Expresii sunt combinații de operanzi și operatori, tratați ca un întreg. Rezultatul evaluării unei expresii poate fi o adresă a unei celule de memorie sau o valoare constantă (absolută).

­ 3 Tipuri de instrucțiuni de asamblare

Să enumerăm tipurile posibile operatori de asamblareși reguli sintactice pentru formarea expresiilor de asamblare:

­ operatori aritmetici;

­ operatori de ture;

­ operatori de comparare;

­ operatori logici;

­ operator de index;

­ operator de tip override;

­ operator de redefinire a segmentului;

­ operator de denumire a tipului de structură;

­ operator pentru obținerea componentei de segment a adresei expresiei;

­ operator pentru a obține offset-ul unei expresii.

1 Directivele asamblatorului

­ Directivele asamblatorului sunt:

1) Directive de segmentare. În cursul discuției anterioare, am aflat toate regulile de bază pentru scrierea comenzilor și operanzilor într-un program de asamblare. Întrebarea cum să formuleze corect secvența de comenzi astfel încât traducătorul să le poată procesa și microprocesorul să le poată executa rămâne deschisă.

Luând în considerare arhitectura microprocesorului, am aflat că are șase registre de segmente, prin care poate funcționa simultan:

­ cu un singur segment de cod;

­ cu un segment de stivă;

­ cu un singur segment de date;

­ cu trei segmente de date suplimentare.

Din punct de vedere fizic, un segment este o zonă de memorie ocupată de instrucțiuni și (sau) date, ale căror adrese sunt calculate în raport cu valoarea din registrul de segment corespunzător. Descrierea sintactică a unui segment în asamblare este construcția prezentată în Figura 13:


­ Figura 13 - Descrierea sintactică a unui segment în asamblator

Este important de reținut că funcționalitatea unui segment este oarecum mai largă decât simpla împărțire a unui program în blocuri de cod, date și stivă. Segmentarea face parte dintr-un mecanism mai general legat de conceptul de programare modulară. Presupune unificarea designului modulelor obiect create de compilator, inclusiv a celor din diferite limbaje de programare. Acest lucru vă permite să combinați programe scrise în diferite limbi. Operanzii din directiva SEGMENT au scopul de a implementa diverse variante ale unei astfel de asocieri.

2) Directive de gestionare a listelor. Directivele de control al listării sunt împărțite în următoarele grupuri:

­ directive generale de control al listării;

­ directive pentru ieșirea în lista de fișiere incluse;

­ directive pentru ieșirea blocurilor de asamblare condiționată;

­ directive pentru listarea macrocomenzilor;

­ directive pentru afișarea de informații despre referințele încrucișate la listare;

­ directive pentru modificarea formatului de listare.

2 Set de instrucțiuni pentru procesor

Setul de instrucțiuni pentru procesor este prezentat în Figura 14.

Să luăm în considerare principalele grupuri de echipe.

­ Figura 14 - Clasificarea instrucțiunilor de asamblare

Echipele sunt:

1 Comenzi de transfer de date. Aceste comenzi ocupă un loc foarte important în setul de instrucțiuni al oricărui procesor. Ei îndeplinesc următoarele funcții esențiale:

­ stocarea în memorie a conținutului registrelor interne ale procesorului;

­ copierea conținutului dintr-o zonă de memorie în alta;

­ scrierea pe dispozitivele I/O și citirea de pe dispozitivele I/O.

Pe unele procesoare, toate aceste funcții sunt efectuate de o singură comandă. MOV (pentru transferuri de octeți - MOVB ) dar cu metode diferite de adresare a operanzilor.

Pe alte procesoare în afară de comandă MOV există mai multe comenzi pentru a efectua funcțiile enumerate. De asemenea, comenzile de transfer de date includ comenzi de schimb de informații (desemnarea lor se bazează pe cuvântul schimb valutar ). Schimbul de informații între registrele interne, între două jumătăți ale unui registru ( SWAP ) sau între un registru și o locație de memorie.

2 comenzi aritmetice. Instrucțiunile aritmetice tratează codurile operanzilor ca coduri binare numerice sau coduri binare-zecimale. Aceste comenzi pot fi împărțite în cinci grupuri principale:

­ comenzi de operații cu punct fix (adunare, scădere, înmulțire, împărțire);

­ comenzi în virgulă mobilă (adunare, scădere, înmulțire, împărțire);

­ comenzi de curatare;

­ comenzi de creștere și decrementare;

­ comanda de comparare.

3 Comenzile de operații cu punct fix funcționează cu coduri în registrele procesorului sau în memorie ca la codurile binare obișnuite. Instrucțiunile în virgulă mobilă (în virgulă) folosesc formatul de reprezentare a numerelor cu ordine și mantisă (de obicei, aceste numere ocupă două locații de memorie consecutive). În procesoarele moderne puternice, setul de instrucțiuni în virgulă mobilă nu este limitat la doar patru operații aritmetice, ci conține multe alte instrucțiuni mai complexe, de exemplu, calculul funcțiilor trigonometrice, funcții logaritmice, precum și funcții complexe necesare procesării sunetului și imagini.

4 Instrucțiunile de ștergere sunt concepute pentru a scrie un cod zero într-un registru sau într-o celulă de memorie. Aceste comenzi pot fi înlocuite cu comenzi de transfer zero, dar comenzile speciale clare sunt de obicei mai rapide decât comenzile de transfer.

5 comenzi pentru creștere (creștere cu unu) și descreștere

(scăderi cu unu) sunt, de asemenea, foarte convenabile. În principiu, ele pot fi înlocuite cu adunarea cu una sau scăderea unei comenzi, dar creșterea și decrementarea sunt mai rapide decât adunarea și scăderea. Aceste instrucțiuni necesită un operand de intrare, care este și un operand de ieșire.

6 Instrucțiunea de comparare compară doi operanzi de intrare. De fapt, calculează diferența dintre acești doi operanzi, dar nu formează un operand de ieșire, ci doar schimbă biții din registrul de stare a procesorului pe baza rezultatului acestei scăderi. Următoarea instrucțiune care urmează instrucțiunii de comparare (de obicei o instrucțiune de ramificare) va analiza biții din registrul de stare a procesorului și va efectua acțiuni în funcție de valorile acestora. Unele procesoare oferă instrucțiuni pentru conectarea în lanț a două secvențe de operanzi în memorie.

7 Comenzi logice. Instrucțiunile logice efectuează operații logice (pe biți) asupra operanzilor, adică consideră codurile operanzilor nu ca un singur număr, ci ca un set de biți separați. Acesta este modul în care ele diferă de comenzile aritmetice. Comenzile logice efectuează următoarele operații de bază:

­ ȘI logic, SAU logic, adunare modulo 2 (SAU exclusiv);

­ deplasări logice, aritmetice și ciclice;

­ verificarea biților și operanzilor;

­ setarea și ștergerea biților (steaguri) ai registrului de stare a procesorului ( PSW).

Instrucțiunile logice vă permit să calculați funcții logice de bază din doi operanzi de intrare, bit cu bit. În plus, operația AND este folosită pentru a șterge forțat biții specificați (un cod de mască este folosit ca unul dintre operanzi, în care biții care trebuie șterși sunt setați la zero). Operația SAU este utilizată pentru a seta forțat biții specificați (ca unul dintre operanzi, se folosește codul masca, în care biții care necesită setarea la unu sunt egali cu unu). Operația „SAU exclusivă” este utilizată pentru a inversa biții specificați (un cod de mască este folosit ca unul dintre operanzi, în care biții de inversat sunt setați la unul). Instrucțiunile necesită doi operanzi de intrare și formează un operand de ieșire.

8 Comenzile Shift permit deplasarea codului operandului bit cu bit spre dreapta (spre biții de ordin inferior) sau spre stânga (spre biții de ordin superior). Tipul de deplasare (logică, aritmetică sau ciclică) determină care va fi noua valoare a bitului cel mai semnificativ (când este deplasat la dreapta) sau a bitului cel mai puțin semnificativ (când este deplasat la stânga) și, de asemenea, determină dacă valoarea anterioară bitul cel mai semnificativ (când este deplasat la stânga) va fi salvat undeva sau bitul cel mai puțin semnificativ (când este deplasat la dreapta). Schimbările ciclice permit deplasarea biților unui operand într-un mod circular (în sensul acelor de ceasornic când sunt deplasați la dreapta sau în sens invers acelor de ceasornic când sunt deplasați la stânga). În acest caz, steagul de transport poate fi inclus sau nu în inelul de schimbare. Bit-ul indicator de transport (dacă este utilizat) stochează valoarea bitului cel mai semnificativ când este ciclat la stânga și a bitului cel mai puțin semnificativ când este ciclat la dreapta. În consecință, valoarea bitului de semnalizare de transport va fi suprascrisă în bitul cel mai puțin semnificativ atunci când deplasați la stânga și în bitul cel mai semnificativ când faceți ciclism la dreapta.

9 comenzi de tranziții. Instrucțiunile de salt sunt concepute pentru a organiza tot felul de bucle, ramuri, apeluri de subrutine etc., adică perturbă fluxul secvenţial al programului. Aceste comenzi scriu o nouă valoare în registrul contorului de comenzi și astfel fac ca procesorul să nu sară la următoarea comandă în ordine, ci la orice altă comandă din memoria programului. Unele comenzi de tranziție oferă o revenire suplimentară înapoi la punctul de la care a fost făcută tranziția, altele nu prevăd acest lucru. Dacă returnarea este furnizată, atunci parametrii actuali ai procesorului sunt salvați în stivă. Dacă nu este furnizat niciun răspuns, atunci parametrii actuali ai procesorului nu sunt salvați.

Comenzile de tranziție fără backtracking sunt împărțite în două grupuri:

­ comenzi de sărituri necondiționate;

­ comenzi de sărituri condiționate.

Aceste comenzi folosesc cuvintele Ramura și Salt.

Instrucțiunile de salt necondiționat provoacă un salt la o nouă adresă, indiferent de orice. Ele pot provoca un salt cu o anumită cantitate de offset (înainte sau înapoi) sau la o anumită adresă de memorie. Valoarea offset sau noua valoare a adresei este specificată ca operand de intrare.

Instrucțiunile de salt condiționat nu provoacă întotdeauna un salt, ci numai atunci când sunt îndeplinite condițiile specificate. Aceste condiții sunt de obicei valorile steagurilor din registrul de stare a procesorului ( PSW ). Adică, condiția de tranziție este rezultatul operației anterioare care modifică valorile steagurilor. Pot exista în total între 4 și 16 astfel de condiții de sărituri. Câteva exemple de comenzi de sărituri condiționate:

­ tranziție dacă este egală cu zero;

­ tranziție dacă nu este egală cu zero;

­ sari daca exista preaplin;

­ sari daca nu exista preaplin;

­ tranziție dacă este mai mare decât zero;

­ sari daca este mai mic sau egal cu zero.

Dacă condiția de tranziție este îndeplinită, atunci noua valoare este încărcată în registrul de comenzi. Dacă condiția de salt nu este îndeplinită, contorul de instrucțiuni este pur și simplu incrementat, iar procesorul selectează și execută următoarea instrucțiune în ordine.

Comanda de comparație (CMP) care precede comanda de ramificare condiționată (sau chiar mai multe comenzi de ramificare condiționată) este utilizată în mod special pentru a verifica condițiile de salt. Dar steagurile pot fi setate de orice altă comandă, de exemplu, o comandă de transfer de date, orice comandă aritmetică sau logică. Rețineți că comenzile de salt în sine nu schimbă steagurile, ceea ce vă permite doar să puneți mai multe comenzi de sărituri una după alta.

Comenzile de întrerupere ocupă un loc special printre comenzile de salt înapoi. Aceste instrucțiuni necesită un număr de întrerupere (adresă vectorială) ca operand de intrare.

Concluzie:

Limbajul de asamblare este o reprezentare simbolică a unui limbaj de mașină. Limbajul de asamblare pentru fiecare tip de computer este diferit. Un program în limbaj de asamblare este o colecție de blocuri de memorie numite segmente de memorie. Fiecare segment conține un set de propoziții de limbă, fiecare dintre acestea ocupând o linie separată de cod de program. Propozițiile de asamblare sunt de patru tipuri: comenzi sau instrucțiuni, macrocomenzi, directive, linii de comentarii.

Toate literele latine sunt caractere valide atunci când scrieți textul programului: A-Z,a-z... În acest caz, literele mari și mici sunt considerate echivalente; cifre din 0 inainte de 9 ; semne ? , @ , $ , _ , & ; separatoare , . () < > { } + / * % ! " " ? = # ^ .

Se aplică următoarele tipuri de instrucțiuni de asamblare și reguli de sintaxă pentru formarea expresiilor de asamblare. operatori aritmetici, operatori de deplasare, operatori de comparare, operatori logici, operator de index, operator de înlocuire a tipului, operator de înlocuire a segmentului, operator de denumire a tipului de structură, operator de obținere a componentei de segment a unei adrese de expresie, operator de obținere a offset-ului unei expresii.

Sistemul de comandă este împărțit în 8 grupuri principale.

­ Întrebări de control:

1 Ce este limbajul de asamblare?

2 Ce simboluri pot fi folosite pentru a scrie comenzi în limbaj de asamblare?

3 Ce sunt etichetele și scopul lor?

4 Explicați structura comenzilor de asamblare.

5 Enumerați 4 tipuri de propoziții de asamblare.

Structura de instruire în limbaj de asamblare Programarea la nivelul de instruire al mașinii este nivelul minim la care este posibilă programarea computerului. Setul de instrucțiuni al mașinii trebuie să fie suficient pentru a efectua acțiunile necesare prin emiterea de instrucțiuni către hardware-ul mașinii. Fiecare instrucțiune de mașină constă din două părți: una de operare care definește „ce să faci” și un operand care definește obiectele de procesare, adică ce să faci. O instrucțiune de mașină cu microprocesor scrisă în limbaj de asamblare este o singură linie de următoarea formă: instrucțiune de etichetă / operand(i) de directivă; comentarii Eticheta, comanda/directiva și operandul sunt separate de cel puțin un spațiu sau un caracter de tabulație. Operanzii de comandă sunt separați prin virgule.

Structura de instrucție în limbaj de asamblare O instrucțiune de limbaj de asamblare îi spune traducătorului ce acțiune ar trebui să întreprindă 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 definește valoarea inițială a datelor (în segmentul de date) sau elementele asupra cărora se acționează comanda (î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 de comandă. Dacă o comandă sau o directivă trebuie continuată pe următoarea linie, atunci se folosește caracterul backslash: „”. În mod implicit, Assembler-ul nu face distincție între litere mari și mici în scrierea comenzilor și directivelor. Exemple de directive și comandă Count db 1; Nume, directivă, un operand mov eax, 0; Comandă, doi operanzi

Identificatorii sunt secvențe de caractere valide utilizate 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. Lungimea maximă a identificatorului este de 255 de caractere, dar traducătorul acceptă primele 32 de caractere, ignoră restul. Toate etichetele care sunt scrise într-o linie care nu conține o directivă de asamblare trebuie să se încheie cu două puncte „:”. Eticheta, comanda (directiva) și operandul nu trebuie să înceapă la o anumită poziție din șir. Este recomandat să le scrieți într-o coloană pentru o mai bună lizibilitate a programului.

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

Comentarii Utilizarea comentariilor într-un program îmbunătățește claritatea, mai ales acolo unde intenția setului de instrucțiuni nu este clară. Comentariile încep pe orice linie din modulul sursă cu punct și virgulă (;). Toate caracterele la dreapta lui „; „Până la sfârșitul rândului sunt un comentariu. Comentariul poate conține orice caractere imprimabile, inclusiv „spațiu”. Un comentariu se poate întinde pe întreaga linie sau poate urma o comandă pe aceeași linie.

Structura unui program în limbaj de asamblare Un program scris în limbaj de asamblare poate consta din mai multe părți, numite module, în fiecare dintre acestea putând fi definite 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, segmente de date și o stivă, declarate folosind directivele corespunzătoare.

Modele de memorie Înainte de a declara segmente, trebuie să specificați modelul de memorie folosind o directivă. MODEL MODEL memory_model, call_convention, OS_type, stack_parameter Modele de memorie de bază ale limbajului de asamblare: Model de memorie Adresarea codului Adresarea datelor Sistemul de operare Intercalarea codului și a datelor TINY NEAR MS-DOS Permis 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 Permis 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 într-un singur segment fizic. În acest caz, dimensiunea fișierului de program 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 singur segment de date, toate legăturile din segmentele de cod considerate în mod implicit departe și linkurile dintr-un segment de date ca fiind aproape. Modelul compact acceptă mai multe segmente de date folosind adresarea datelor departe și un segment de date apropiat. Modelul mare acceptă mai multe segmente de cod și mai multe segmente de date. În mod implicit, toate referințele de 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 pe sisteme de operare pe 32 de biți. Acest model este similar cu modelul mic prin faptul că datele și codul sunt conținute într-un singur segment de 32 de biți. Pentru a dezvolta un program pentru modelul plat înainte de directivă. model plat ar trebui plasat una din directive:. 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 indică un mod de funcționare protejat. Adresarea datelor și codului este aproape, toate adresele și indicatorii fiind pe 32 de biți.

Modele de memorie. MODEL modificator memory_model, call_convention, OS_type, stack_parameter Parametrul modificator este utilizat pentru a defini tipurile de segmente și poate lua următoarele valori: folosește 16 (segmentele modelului selectat sunt folosite ca pe 16 biți) folosește 32 (segmente ale modelului selectat sunt folosite ca pe 32 de biți). Parametrul call_convention este utilizat pentru a determina modul în care parametrii sunt transmisi atunci când se apelează o procedură 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, call_convention, os_type, stack_parameter OS_type este OS_DOS implicit și este în prezent singura valoare acceptată pentru acest parametru. Stack_parameter este setat la: NEARSTACK (registrul SS este 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 „a nu face nimic”. 686 P. MODEL PLAT STDCALL. DATE. COD START: RET END START RET - comandă microprocesor. Asigură terminarea corectă a programului. Restul programului este legat de munca traducătorului. ... 686 P - Comenzi în mod protejat Pentium 6 (Pentium II) permise. Această directivă selectează setul de instrucțiuni de asamblare suportat prin specificarea modelului procesorului. ... MODEL FLAT, stdcall este un model de memorie plată. Acest model de memorie este utilizat în sistemul de operare Windows. stdcall este convenția de apelare a procedurii utilizată.

Un exemplu de program „a nu face nimic”. 686 P. MODEL PLAT STDCALL. DATE. COD START: RET END START. DATA este un segment de program care conține date. Acest program nu folosește stiva, deci. STACK lipsește. ... COD - un segment al programului care conține codul. START este o etichetă. END START - sfârșitul programului și un mesaj către compilator că programul trebuie pornit de la eticheta START. Fiecare program trebuie să conțină o directivă END pentru a marca sfârșitul codului sursă al programului. Toate liniile care urmează directivei END sunt ignorate.Eticheta specificată după directiva END spune traducătorului numele modulului principal de la care pornește programul. 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 mijloc tehnic care convertește un program dintr-unul dintre limbajele de programare într-un program în limba țintă, numit cod obiect. Pe lângă suportul mnemonic al instrucțiunilor de mașină, fiecare traducător are propriul său set de directive și instrumente macro, care sunt adesea incompatibile cu orice. Principalele tipuri de traducători de limbaj de asamblare: MASM (Microsoft Assembler), TASM (Borland Turbo Assembler), FASM (Flat Assembler) - un asamblator gratuit cu mai multe treceri scris de Tomasz Grishtar (polonez), NASM (Netwide Assembler) - un asamblator gratuit pentru Intel x architecture 86, a fost creat de Simon Tatham în colaborare cu Julian Hall și este în prezent dezvoltat de o mică echipă de dezvoltare pe Source. Forja. net.

Src = "https://present5.com/presentation/-29367016_63610977/image-15.jpg" alt = "(! LANG: Difuzarea programului la Microsoft Visual Studio 2005 1) Creați un proiect alegând Fișier-> Nou-> 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 = "(! LANG: Difuzarea programului la Microsoft Visual Studio 2005 2) În arborele proiectului (Vizualizare-> 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 opțiunile 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 făcând clic dreapta în salut. asm din arborele de proiect din meniul Proprietăți și setați General-> Instrument: Microsoft Macro Assembler.

Src = "https://present5.com/presentation/-29367016_63610977/image-22.jpg" alt = "(! LANG: Difuzarea programului la Microsoft Visual Studio 2005 6) Compilați fișierul alegâ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 (Application Program Interface). Numărul lor ajunge la 2000. Programul pentru Windows constă în mare parte din astfel de apeluri. Toată interacțiunea cu dispozitivele externe și resursele sistemului de operare are loc, de regulă, prin astfel de funcții. Sistemul de operare Windows utilizează un model de memorie plată. Adresa oricărei locații 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 (fereastră principală - dialog), structură consolă sau fără ferestre, structură clasică (fereastră, wireframe).

Apelarea funcțiilor API Windows În fișierul de ajutor, orice funcție API este reprezentată ca tipul nume_funcție (FA 1, FA 2, FA 3) Tip - tipul valorii returnate; ФАх - 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 - mâner la fereastra în care va apărea fereastra de mesaj, lp. Text - textul care va apărea în fereastră, lp. Legendă - textul din legenda ferestrei, u. Tip - tipul ferestrei, în special, puteți defini numărul de butoane de ieșire.

Apelarea funcțiilor API Windows int Mesaj. Casetă (HWND h. Wnd, LPCTSTR lp. Text, LPCTSTR lp. Legendă, UINT u. Tip); Aproape toți parametrii funcțiilor 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 atașat la numele funcției pentru a trece la versiuni mai noi ale funcției.

Apelarea funcțiilor API Windows int Mesaj. 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 Win 32 API, acest număr poate fi definit ca numărul de argumente n ori 4 (octeți în fiecare argument): N = 4 * n. Comanda CALL assembler este folosită pentru a apela funcția. Î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. Primul argument care trebuie împins în stivă este u. Tip. Apelul către funcția specificată va arăta astfel: CALL Message. Cutie. [email protected]

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

Un 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. [email protected]: LÂNGĂ. COD START: PUSH MB_OK PUSH OFFSET STR 1 PUSH OFFSET STR 2 PUSH HW CALL Mesaj. Cutie. [email protected] RET END START

Directiva INVOKE Translatorul limbajului MASM face posibilă, de asemenea, simplificarea apelului de funcții folosind un instrument macro - directiva INVOKE: funcția INVOKE, parametrul1, parametrul2, ... În acest caz, nu este nevoie să adăugați @ 16 la apel de funcție; parametrii se scriu exact în ordinea în care sunt dați în descrierea funcției. parametrii sunt împinși pe stivă cu ajutorul translatorului. 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ă programul utilizează multe funcții API Win 32, este recomandabil să utilizați directiva include C: masm 32includeuser 32. inc

Lucru de curs

La disciplina „Programare sistem”

Subiectul numărul 4: „Rezolvarea problemelor pentru proceduri”

Opțiunea 2

UNIVERSITATEA DE STAT SIBERIAN DE EST

TEHNOLOGIE ȘI CONTROL

____________________________________________________________________

COLEGIUL DE TEHNOLOGIE

EXERCIȚIU

pentru lucrarea de termen

Disciplina:
Subiect: Rezolvarea problemelor pentru proceduri
Interpret(i): Glavinskaya Arina Aleksandrovna
Șef: DambaevaSesegma Viktorovna
Rezumatul lucrării: studiul rutinelor în limbaj de asamblare,
rezolvarea problemelor folosind subrutine
1. Partea teoretică: Informații de bază despre limbajul Asamblare (set
comenzi etc.), Organizarea subrutinelor, Metode de trecere a parametrilor
în subrutine
2. Parte practică: Dezvoltați două subrutine, dintre care una transformă orice literă dată în majuscule (inclusiv pentru literele rusești), iar cealaltă transformă litera în minuscule.
convertește orice literă dată în majuscule, iar cealaltă convertește litera în minuscule.
transformă o literă în minuscule.
Termenele limită ale proiectului conform programului:
1. Partea teoretică - 30% la 7 săptămâni.
2. Partea practică - 70% până la 11 săptămâni.
3. Protectie - 100% pana la 14 saptamani.
Cerințe pentru înregistrare:
1. Soluționarea și nota explicativă a proiectului de curs trebuie prezentate în
copii electronice și hârtie.
2. Volumul raportului trebuie să fie de cel puțin 20 de pagini dactilografiate, cu excepția anexelor.
3. RPZ este întocmit în conformitate cu GOST 7.32-91 și semnat de șef.

director de munca __________________

Antreprenorul __________________

Data emiterii " 26 " Septembrie 2017 G.


Introducere. 2

1.1 Informații de bază despre limbajul de asamblare. 3

1.1.1 Set de comenzi. 4

1.2 Organizarea subrutinelor în limbaj de asamblare. 4

1.3 Metode de transmitere a parametrilor în subrutine. 6

1.3.1 Trecerea parametrilor prin registre .. 6

1.3.2 Trecerea parametrilor prin stivă. 7

2 SECȚIUNEA PRACTICĂ .. 9

2.1 Enunțarea problemei. 9

2.2 Descrierea soluției problemei. 9

2.3 Testarea programului .. 7

Concluzie. opt

Referințe .. 9


Introducere

Este cunoscut faptul că este dificil de programat în Assembler. După cum știți, există multe limbi diferite acum. nivel inalt care vă permit să cheltuiți mult mai puțin efort atunci când scrieți programe. Desigur, se pune întrebarea când un programator poate avea nevoie să folosească Assembler atunci când scrie programe. În prezent, există două domenii în care utilizarea limbajului de asamblare este justificată și adesea necesară.

În primul rând, acestea sunt așa-numitele programe de sistem dependente de mașină, de obicei controlează diverse dispozitive de pe computer (astfel de programe se numesc drivere). Aceste programe de sistem folosesc instrucțiuni speciale ale mașinii care nu trebuie să fie utilizate în mod obișnuit (sau, după cum se spune aplicat) programe. Aceste comenzi sunt imposibil sau foarte greu de definit într-un limbaj de nivel înalt.

A doua zonă de aplicare a Asamblatorului este legată de optimizarea execuției programului. Foarte des, programele de traducere (compilatoare) din limbi de nivel înalt produc un program de limbaj automat foarte ineficient. Acest lucru se aplică de obicei programelor de natură computațională, în care o secțiune foarte mică (aproximativ 3-5%) a programului (bucla principală) este executată de cele mai multe ori. Pentru a rezolva această problemă, pot fi utilizate așa-numitele sisteme de programare multilingve, care vă permit să scrieți părți ale programului în diferite limbi. De obicei, partea principală a programului este scrisă într-un limbaj de programare de nivel înalt (Fortran, Pascal, C etc.), iar secțiunile critice ale programului sunt scrise în Assembler. În acest caz, viteza întregului program poate fi crescută semnificativ. Aceasta este adesea singura modalitate de a face ca programul să ofere un rezultat într-o perioadă rezonabilă de timp.

Scopul acestui curs este de a obține abilități practice de programare în limbaj de asamblare.

Sarcini de lucru:

1. Să studieze informațiile de bază despre limbajul Assembler (structura și componentele programului Assembler, formatul comenzilor, organizarea subrutinelor etc.);

2. Să studieze tipurile de operații pe biți, formatul și logica instrucțiunilor logice ale Asamblatorului;

3. Rezolvați o problemă individuală privind utilizarea subrutinelor în Assembler;

4 .. Formulați o concluzie despre munca depusă.

1 SECȚIUNEA TEORETICĂ

Înțelegerea limbajului de asamblare

Assembler este un limbaj de programare de nivel scăzut, care este un format care poate fi citit de om pentru scrierea instrucțiunilor mașinii.

Instrucțiunile din limbajul de asamblare corespund unu la unu cu instrucțiunile procesorului și, de fapt, reprezintă o notație simbolică convenabilă (cod mnemonic) a comenzilor și a argumentelor acestora. De asemenea, limbajul de asamblare oferă abstracții software de bază: legarea părților programului și a datelor prin etichete cu nume simbolice și directive.

Directivele Assembler vă permit să includeți blocuri de date (descrise explicit sau citite dintr-un fișier) în program; repetați un anumit fragment de un anumit număr de ori; compilați un fragment condiționat; setați adresa de execuție a fragmentului, modificați valorile etichetelor în timpul procesului de compilare; utilizați macrocomenzi cu parametri etc.

Avantaje și dezavantaje

· Cantitatea minimă de cod redundant (folosind mai puține instrucțiuni și accesări la memorie). Ca rezultat - viteză mai mare și dimensiune mai mică a programului;

· Cantități mari de cod, un număr mare de sarcini mici suplimentare;

· Lizibilitate slabă a codului, dificultate în menținere (depanare, adăugare de caracteristici);

· Dificultatea implementării paradigmelor de programare și a oricăror alte convenții mai complexe, complexitatea dezvoltării comune;

· Mai puține biblioteci disponibile, compatibilitatea lor scăzută;

· Acces direct la hardware: porturi de intrare-ieșire, registre speciale ale procesorului;

· „Potrivire” maximă pentru platforma dorită (utilizarea instrucțiunilor speciale, caracteristici tehnice ale „hardware”);

· Intoleranță față de alte platforme (cu excepția compatibilelor binare).

Pe lângă instrucțiuni, un program poate conține directive: comenzi care nu se traduc direct în instrucțiuni de mașină, dar controlează funcționarea compilatorului. Setul și sintaxa lor variază semnificativ și depind nu de platforma hardware, ci de compilatorul utilizat (dând naștere la dialecte ale limbilor din aceeași familie de arhitecturi). Ca un set de directive, se pot evidenția:

· Definirea datelor (constante și variabile);

· Gestionarea organizării programului în memorie și a parametrilor fișierului de ieșire;

· Setarea modului de operare al compilatorului;

· Tot felul de abstracții (adică elemente ale limbajelor de nivel înalt) - de la proiectarea procedurilor și funcțiilor (pentru a simplifica implementarea paradigmei de programare procedurală) până la structuri și bucle condiționate (pentru paradigma de programare structurată);

· Macrocomenzi.

Set de comenzi

Comenzile tipice din limbajul de asamblare sunt:

Comenzi de transfer de date (mov etc.)

Comenzi aritmetice (adăugați, sub, imul etc.)

Operații logice și pe biți (sau, și, xor, shr etc.)

· Comenzi pentru controlul execuției programului (jmp, loop, ret, etc.)

Întreruperea comenzilor de apelare (uneori denumite comenzi de control): int

Comenzi I/O către porturi (in, out)

Pentru microcontrolere și microcalculatoare, comenzile sunt, de asemenea, caracteristice care efectuează verificarea și tranziția după condiție, de exemplu:

· Jne - mutare dacă nu este egală;

· Jge - sari daca este mai mare sau egal.

Top articole similare