MASM (Macro Assembler)

Conf. Dr. Carmen Timofte

 

1.     Structura fișierelor .exe și .com

2.     Etapele de dezvoltare a programelor in MASM

3.     Arhitectura microprocesorului 8086 – registrii microprocesorului

4.     Modurile de adresare ale datelor   

5.     Elemente de bază ale limbajului de asamblare

6.     Exemple de programe în MASM

7.     Bibliografie

 

1.     Structura fișierelor .exe și .com

 

MS-DOS poate să încarce și să execute 2 tipuri de programe:

-       .EXE – conțin un antet cu informații folosite de încărcătorul de sistem pentru a executa ajustările la referințele de segment (relocări în momentul încărcării); au o dimensiune mai mare de 64 KB; au o structură multisegment (stivă, date, cod)

-       .COM – conțin imaginea binară a datelor și codului unui program; au o dimensiune mai mică de 64 KB; nu se fac relocări ale adreselor de segment; au un singur segment, care include date și cod; se încarcă mai repede în memorie.

 

Fișierele .EXE au structura:

-       segment de stiv㠖 memorează datele care trebuie salvate și reapelate apoi de program; poate apărea în orice ordine față de celelalte segmente;

-       segment de date – conține variabilele referite de segmentul de cod; trebuie să fie plasat înaintea lui;

-       segment de cod – conține instrucțiunile executabile, începând cu o etichetă care identifică punctul de intrare în program

 

Terminarea execuției unui program .EXE se realizează cu INT 21H, iar registrul AX încărcat  cu funcția 4C00H.

 

2.     Etapele de dezvoltare a programelor în MASM

 

Medii de dezvoltare: MASM, TASM (Turbo Assembler), TASM pe 64b . Emulator- DosBox Portable. Se lucrează cu oricare dintre ele!

·       Emu8086

 

Exemplificare pentru MASM:

-       Editarea programelor – se realizează cu orice editor ASCII. Programul sursă se va salva cu extensia specifică limbajului utilizat;

 exp: numefis.asm;

 

-       Translatarea programului sursă în limbaj binar –se detectează eventualele erori de sintaxă, semantică; translatoarele sunt de 2 feluri: asambloare (specifice fiecărui sistem de calcul) și compilatoare. Dacă în urma translatării apar erori, se reia de etapa de editare, iar dacă nu sunt erori, se obține un program obiect (numefis.obiect)

Se realizează cu programul MASM.EXE, astfel:

MASM <enter>

      Numele_programului.asm= numefis.asm

      Numele_programului_obiect.obiect= <enter> și preia numele de sus, sau se introduce un nume nou

      Numele_programului_listing.lst= <enter> sau alt nume ; acest fișier este destinat listării

 

-       Editarea de legături – (link editare) permite efectuarea de legături între mai multe module obiect. Are ca rezultat un fișier cu extensia .exe. Se realizează cu programul LINK.EXE, asftel:

LINK <enter>

            Numele_fișierului_obiect= numefis.obiect

            Numele_fișierului_executabil=<enter> sau se introduce un nume nou.

 

-       Încărcarea în memoria internă și execuția efectiv㠖 se urmărește vizualizarea codului executabil al programului, rulat cu TRACE (pas cu pas)(ALT + T). Se realizează cu programul CV.EXE (Code View), asftel:

cv numefis.exe

            și se deschide o fereastră care arată instrucțiunile și adresele lor, conținutul regiștrilor microprocesorului și flag-urile (F2).

 

Pentru a vizualiza zona de memorie în care se află rezultatele se folosește comanda din SO Windows 9x/2000/NT, numită DEBUG:

            debug numefis.exe

            -?  (permite aflarea tuturor subcomenzilor din mediul debug)

            - t  (rulare Trace)

            - d DS:0000 (Dump de memorie pentru segmentul de date DS; adresa lui DS se vede la comanda t; DATELE IN MEMORIE SUNT REPREZENTATE INVERS DECAT IN REGISTRII MICROPROCESORULUI !!!)

            - q (quit)

 

3.     Arhitectura microprocesorului 8086 – registrii microprocesorului

 

Dispune de 13 registrii, astfel:

-       8 reg. generali, astfel:

-       4 reg. de date:

AX – acumulator (pentru instrucțiuni aritmetice)

BX – de bază

CX – contor

DX – de date, pentru operații de *, /;

Exp. de registru pe16 biți

      AX: 15 AH  8 7 AL  0        AX are 2B = 1 word (cuvânt)

                                                   AH= A HIGHT

                                                   AL= A LOW

-       4 reg. de pointer și indecși:

SP –Stack Pointer – memorează adresa curentă a vârfului stivei

BP –Base Pointer- păstrează adresa din interiorul stivei, folosit la citirea unui cuvânt din stivă, fără a-l extrage

SI –Source Index – păstrează valoarea indexului necesară adresării unui șir de caractere;

DI –Destination Index – idem;

 

-       4 reg. de segment

CS –Code Segment – destinat adresării segm. de instrucțiuni curente

DS –Data Segment - destinat adresării segm. de date

ES –Extended Segment - destinat adresării segm. extins de date

SS –Stack Segment - destinat adresării stivei curente a programului

 

-       1 reg. pentru memorarea adresei următoarei instrucțiuni din segmentul curent IP (Instruction Pointer)

 

Indicatorii de condiție:

-       indicatori de stare – de tip Read-Only; sunt poziționați de instrucțiunile aritmetico-logice și nu pot fi decât citiți de programatori:

AF (Auxilliary Flag) – are valoarea 1 dacă apare transport între rangurile 3 și 4;

CF (Carry Flag) – are valoarea 1 dacă apare transport pe poziția cea mai semnificativă;

OF (Overflow Flag) – are valoarea 1 dacă apare depășire;

SF (Signe Flag) –are valoarea 1 dacă bitul de pe poziția cea mai semnificativă este 1;

PF (Parity Flag) – are valoarea 1 dacă numărul biților din byte-ul cel mai puțin semnificativ este par;

ZF (Zero Flag) – are valoarea 1 dacă rezultatul operației anterioare a fost 0.

 

-       indicatori de control – de tip Read-Write; sunt fixați de utilizator:

DF (Direction Flag) – are valoarea 1 dacă șirul de caractere este parcurs crescător;

IF (Interrupt Flag) –are valoarea  1 dacă se consideră întreruperile externe;

TF (Trace Flag) – are valoarea 1 dacă programul se execută pas cu pas.

 

4.     Modurile de adresare ale datelor  

 

Reprezintă maniera în care datele sunt memorare și accesate din memoria interna a microprocesorului.

 

Există 8 moduri de adresare:

 

1-    adresare imediat㠖 operandul se găsește într-un un cuvânt (word) imediat după codul instrucțiunii

ex:       MOV AX, 15

muta valoarea 15 in registrul acumulator AX;

 

2-    adresare utilizând registre generale – valoarea operandului se găsește într-un registru general

ex:       MOV AX, BX

mută conținutul registrului BX în registrul AX;

 

3-    adresare direct㠖 valoarea operandului se găsește la adresa specificată în instrucțiune

ex:       MOV AX, LUCRU

muta conținutul variabilei LUCRU în AX;

 

4-    adresare indirect㠖 valoarea operandului se găsește în locațîa definită la adresa adresei aflată în instrucțiune

ex:       MOV AX, [BX]

în BX se află o adresă; la adresa specificată în BX se găsește o altă adresă; la a II-a adresă se găsește operandul care va fi mutat în AX;

 

5-    adresare cu registre de bază -

ex:       MOV AX, [BX] val           (pt. <DS:BX>)

            MOV AX, [BP] val            (pt. <SS:BP>)

se utilizează pentru șiruri de date;

adresa relativă= valoarea din registrul de bază + val;

 

6-    adresare cu registre de index - adresa relativă= valoarea din registrul de index + val;

ex:       MOV AX, [SI] val           (pt. <DS:SI>)

            MOV AX, [DI] val            (pt. <DS:DI>)

se utilizează pentru tratare șiruri de date;

 

7-    adresare cu registre de bază  și registre de index-

ex:       MOV AX, [BX] [SI]

adresa relativă= valoarea din registrul de bază + valoarea din registrul de index;

 

8-    adresare cu registre de bază, registre de index și offset -

ex:       MOV AX, [BX] [SI]val       

            MOV AX, [BP] [SI]val

            MOV AX, [BX] [SI]val

            MOV AX, [BP][DI]val

adresa relativă= valoarea din registrul de bază + valoarea din registrul de index +val;

 

5.     Elemente de bază ale limbajului de asamblare

 

§  Un program în MASM se compune din mai multe segmente:

-       segment de stivă;

-       segment de date;

-       segment de cod.

 

§  Un program poate să înceapă cu directiva NAME, care atribuie un nume programului.

 

§  Fiecare segment începe cu directiva SEGMENT și se termină cu directiva ENDS.

                   Exp:

                                  nume   SEGMENT ……

                                              ………

                                  nume   ENDS

 

§  Programul se termină cu directiva END.

 

§  O directivă obligatorie este directiva

ASSUME reg_segm: nume_segm

 care definește registrii de segment (CS, DS, ES, SS) folosiți de fiecare segment în parte.

 

§  Directiva SEGMENT marchează începutul segmentului. Sintaxă:

                        nume SEGMENT tip_aliniere, tip_combinare, clasă

unde:

 tip_aliniere – reprezintă multiplul adresei de segment; poate lua valorile:

                                  .BYTE             - multiplu de 1;

                                  .WORD           - multiplu de 2;

                                  .PARA             - multiplu de 16;

                                  .PAGE             - multiplu de 256.

tip_combinare – reprezintă adresa cerută de link-editor pt. a încarca în memorie diferite module; poate lua valorile:

                        PUBLIC – 2 segm. cu același nume din 2 module diferite vor fi încărcate în memorie prin acoperire parțială;

                        COMMON- idem, dar se vor suprapune total;          

                        AT <expr.>- idem, dar se vor încărca la adresa specificată în expresie;    

                        STACK – idem, dar se vor încărca în segmentul de stivă;

                        MEMORY - idem, dar se vor încărca în orice locație liberă din memorie;

                        blank – se vor crea segmente separate de tip PRIVATE.

                     

clas㠖 reprezintă un șir de caractere între ‘  ‘;  segmentele care au această clasă sunt încărcate  in memorie în locații contigue, apropiate.

 

§  VARIABILELE – sunt elemente de date definite prin:

-       tip – poate fi:

DB – (Define Byte) date de lungine 1B;

DW – date de lungime 2 B (1 Word);

DD - ------,,------------ 4 B (2 W);

DQ- -------;;-----------  8 B (4 W);

DT - -------;;---------- 10 B.

-       segement – poate fi: CS, DS, SS, ES

-       offset – valoare întreagă fără semn care reprezintă  distanța față de baza segmentului;

 

§  CONSTANTELE – sunt de 2 tipuri:

-       de tip șir – succesiune de caractere ASCII cuprinse între ‘ ‘ sau “ “;

-       de tip numeric – pot fi :

-binare (B)

-octalw (Q)

-zecimale (D)

-hexazecimale (H)

-virgulă mobilă (L, E)

 

§  OPERATORI

1.     Aritmetici :

-       unari: - (negare)

-       binari: *, /, MOD, +, -, SHL (shift left), SHR (shift right)

Exp.: MOV AX, 100H/7      (operanzii trebuie să fie valori absolute)

         MOV AX, 1010000B SHR 3   (mută în AX 1010B)

 

2.     Relaționali : LE (left equal), LT (left than), EQ (equal), GT (great than), GE (great equal), NE (not equal)

 

3.     Logici : .AND., .OR., .XOR., .NOT.

 

4.     Analitici : SEG, OFFSET, TYPE,  LENGTH, SIZE, .TYPE

- returnează informații despre expresiile specificate; expresiile pot fi variabile, adrese, etichete, constante;

SEG  - returnează conținutul registrului de segment atașat variabilei sau etichetei specificate

Sintaxă: SEG var/etichetă

Exp: MOV AX, SEG var1   - mută în reg. AX, conținutul registrului de segment din care face parte var1

 

OFFSET – returnează deplasarea variabilei sau etichetei specificate față de începutul segmentul în care a fost definit

Sintaxă: OFFSET var/etichetă

 

TYPE -

Sintaxă: TYPE var – returnează lungimea în bytes a tipului de dată corespunzător variabilei specificate; dacă este de tip byte, returnează 1, Word, 2 etc.

Exp: var1 DW 100

         ..................

        MOV AX, TYPE var1    - mută în AX valoarea 2

Sintaxă: TYPE etichet㠖 returnează distanța asociată etichetei specificate; poate lua valorile NEAR sau FAR.

 

LENGHT var – returnează nr. de apariții al tipului de variabilă; se utilizează pentru variabile de tip vector, când returnează numărul de elemente al vectorului.

Exp: var1 DW 100

         ..................

        MOV AX, LENGHT  var1    - mută în AX valoarea 1

 

SIZE var – returnează lungimea în bytes a variabilei specificate; SIZE=TYPE*LENGHT;

Exp: var1 DW 100

         ..................

        MOV AX, SIZE var1    - mută în AX valoarea 2

 

5.     Sintetici : PTR, THIS, SHORT, HIGH, LOW, OVERWRITE

Permit modificarea atributelor unei expresii, care poate fi: variabilă, etichetă, adresă, constantă.

 

PTR – modifică temporar atributul corespunzător expresiei specificate;

Sintaxă:  atribut PTR expresie 

Atributele pot fi:

      - de distanță: NEAR, FAR;

      - în funcție de tipul expresiilor: BYTE, WORD, DWORD, QWORD, TBYTE, STRUC.

Exp: var1 DW 100

         ..................

        MOV AH, var1 - incorect

  MOV AH, BYTE PTR var1    - var1 va fi considerată  ca o zonă de 1B, în cadrul acestei instrucțiuni; are caracter temporar;

 

THIS – definește o adresă de memorie, fără a o rezerva;

Sintaxă: THIS var/etichetă

 

SHORT etichet㠖 efectuează un salt prin intermediul instrucțiunii JUMP în interiorul a 127B

Exp: JMP SHORT et1

 

HIGH var / LOW var – extrag dintr-un cuvânt, byte-ul cel mai semnificativ, respectiv cel mai puțin semnificativ

Exp: var1 DW 100

         ..................

        MOV AH, HIGH var1    - mută în AH p.c.m.s. din var1

  MOV AL, LOW var1    - mută în AL p.c.m.p.s. din var1

 

6.     Tratare înregistrări: SHIFT COUNT, WIDTH, MASK

 

 

§  DIRECTIVE

1.     Directive condiționale

2.     Directive pentru erorile condiționale

3.     Directive pentru declararea și alocarea datelor: ASSUME, GROUP, INCLUDE, EQU, ORG, =, EVEN, DB, DW, DD, DQ, DT, DUP, RADIX, RECORD, STRUC, PROC, LABEL

4.     Directive pentru controlul listării și a fișierelor de listare: PAGE, .TITLE, .LIST, .CREF, XCREF

5.     Directive pentru declararea macroinstrucțiunilor sau macrodefiniților

6.     Directive pentru controlul modului de lucru

7.     Directive pentru încarcarea segmentului

 

EQU –asociază simbolul cu expresia specificată

Sintaxă: simbol EQU expresie

Exp: A EQU 50  - în loc de constanta 50 se folosește simbolul A

 

ORG expr – șterge conținutul registrului locației curente IP și îl înlocuiește cu valoarea rezultată din evaluarea expresiei; dacă apare $, se calculează de la valoarea curentă a IP;

Exp: ORG 7   - IP ia valoarea 7

        ORG 7+2 – IP ia valoarea 9

        ORG $+2  - IP=IP+2

 

 EVEN – nu are parametrii și are ca efect forțarea unei adrese pare pentru instrucțiunea următoare.

 

.RADIX expresie – modifică asumția implicită a calculatorului; expresia poate fi 2, 8, 16

Exp: MOV AX, 55  - mută 55 în baza 10 în AX

        .RADIX 8      - modifică baza implică de lucru din 10 în 8

        MOV AX, 55 – muta 55 (baza 8) în AX

 

 Directive pentru alocarea și inițializarea datelor

nume_var {DB/ DW/ DD/ DQ/ DT} [expresie]

– alocă o zonă de memorie cu lungimea de 1B sau 2B ,.... sau 10B și eventual inițializarea ei cu o valoarea rezultată din evaluarea expresiei.

- dacă apar mai multe constante separate prin virgulă, se rezervă o zonă de memorie multiplă;

Exp: var1 DB 5,7,3 – se declară 3 zone de memorie, fiecare de 1 B, inițializate cu valorile 5, 7, 3.

- dacă apare semnul ?, zona de memorie va fi neinițializată, ci doar rezervată;

Exp: var1 DW ?

-valorile de sus pot fi mixate

Exp: var1 DW 3,2,?, 5,7

 

DUP – semnifică declararea unui vector de date, cu numărul de elemente specificat,inițializat sau nu;

Sintaxă: 

nume_var {DB/ DW/ DD/ DQ/ DT} numar DUP (expresie)

Exp: vect DW 100 DUP (5,7)  - alocă o zonă de memorie unui vector de 100 de elemente, fiecare de 1W, inițializat asftel: primul element 5,al doilea 7, al treilea 5 etc.

Câmpul expresie poate fi și un șir de caractere ASCII, cuprinse între apostrofuri.

Exp: sir DB ’LIMBAJE’ – se rezervă 7B, inițializați cu caracterele L, I, ..., E.

 

§  INSTRUCȚIUNI PT. EXEC. OPERAȚII

ADD   destin, sursă

            adună  sursa (registru, zonă de memorie, constantă) la destinația (AX, zonă de memorie, registru), punând rezultatul în destinație.

 

SUB    destin, sursă

scade sursa din destinație, punând rezultatul în destinație

 

DIV     sursă

            Execută împărțirea dintre:

           

Deîmpărțit

:

Împărțitor

=

Cât

Rest

Pe byte

AL

:

Sursă

=

AL

AH

Pe word

AX

:

Sursa

=

AX

DX

 

MUL   destin

Execută înmulțirea dintre:

           

 

 

 

 

p.c.m.s.

p.c.m.p.s.

Pe byte

AH

*

Sursă

=

AH

AL

Pe word

AX

*

Sursa

=

DX

AX

 

CMP   destin, sursă              

Realizează operația de scădere (comparare) între sursă și destinație, punând indicatorii de condiție în funcție de rezultat; sursa și destinația rămân nemodificate.

 

CMPS șir_destin, șir_sursă - compară șirurile; se utilizează regiștrii SI, DI.

 

§  INSTRUCȚIUNI DE SALT

JE        etichetă           - (Jump =) salt la etichetă dacă cei 2 operanzi implicați în operația de comparare anterioară sunt egali)

JL        etichetă           - Jump Less

JG        etichetă           - Jump Great

JMP     etichetă

            INC     destinație

            DEC    destinație       

           

§  INSTRUCȚIUNI PT. APEL INTRERUPERI (interne –software/ externe –hardware)

INT     tip_întrerupere            - un nr. întreg între [0, 255]

IRET                                       - reconstituie contextul inițial al programului

INTO                                       - în caz de depășire (Interrupt Overflow)

 

§  INSTRUCȚIUNI PT. INCARCARE DE ADRESE

LEA    dest, sursă       - Load Effective Addresse

LDS     -----,,------       - Load Data Segment

LES     -----,,-----         - Load Extended Segment

PUSH sursă                - depune în stivă (SP=SP+2)

POP     destin              - extrage din stivă (SP=SP –2)

MOV   destin, sursă    - mută sursa în destinație

 

§  INSTRUCȚIUNI PT. MUTARE DE ȘIRURI

MOVS                         dest, sursa       - pt. adresarea sirurilor sursă/destinație se folosesc reg. SI/ DI

MOVSB          ------;;------      - se mută 1 B

MOVSW         ------;;------      - se mută 1 W

LODS                                      - idem MOVS

LODSB                                   - idem MOVSB

LODSW                                  - idem MOVSW

 

§  INSTRUCȚIUNI DE CICLARE

LOOP etichetă   - decrementează cu 1 registrul CX; dacă valoarea lui CX<>0, atunci se execută salt la eticheta specificată

 

6.     Exemple de programe în MASM

 

Să se calculeze expresia E= a+b-c, unde a,b,c sunt numere generate în memorie la nivel de byte.

            Vom folosi SI pe a fi contor de adrese, offset – pentru deplasare în cadrul șirului de date.

 

segm_stiva        SEGMENT

            stiva     DB 128 DUP (?)

segm_stiva       ENDS

 

segm_date        SEGMENT

            sir_date DB        7,23,13, ?

segm_date        ENDS

 

segm_cod         SEGMENT

            ASSUME CS:segm_cod, DS:segm_date, SS:segm_stiva

            et:        MOV AX, segm_date

                        MOV DS, AX

 

                        MOV  SI, offset sir_date

                        MOV    AL, [SI]

                        ADD     AL, [SI+1]

                        SUB     AL, [SI+2]

                        MOV    [SI+3], AL

 

                        MOV AX, 4C00H

                        INT 21H

segm_cod         ENDS

END et

 

Exemple de programe

 

7.     Bibliografie

 

-       G. Muscă, „Programarea în limbaj de asamblare, Ed. Teora, 1997 (1999);

-       Floarea Năstase, „Sisteme de calcul și operare – elemente ale limbajului de asamblare, ASE, București, 1997;

-       Dan Somnea, Teodor Vlăduț, „Programarea în ASSEMBLER”, Ed. Tehnică, 1992;

-       Irina Athanasiu, Alexandru Pănoiu, „Microprocesoarele 8086, 286, 386- Programarea în limbaj de asamblare, Ed. Teora, 1992;

-       Vlad Căprăriu, „Sistemul de operare DOS –Funcții sistem, Microinformatica, Cluj-Napoca, 1991.