Sunteți pe pagina 1din 23

PROGRAMARE ÎN LIMBAJ

DE ASAMBLARE
• CURS - 2h / săptămână

• LABORATOR - 2h / săptămână

• COLOCVIU ….. În ultimele 2-3 săptămâni din


semestru

• EXAMEN ….. 8 subiecte teoretice

• NOTA_FINALĂ = 0.4 x NOTĂ_COLOCVIU + 0.6 x


NOTĂ_EXAMEN (minim 4)
Bibliografie
Gheorghe Muscă Programare în limbaj de asamblare, Editura Teora, Bucureşti,
1996
 Lance Leventhal, Z80 Assembly language programming, 1979.
 Pusztai K. s.a "Programare in limbaj de asambalare" Ed. UTCN, 1996
Richard C. Detmer, Fundametals of Assembly Language Programming, PC
Heath Comp., Lexington Masschusetts,1990
Irina Athanasiu, Alexandru Panoiu Microprocesoarele 8086, 286, 386 Editura
Teora, Bucureşti, 1992
IBM PC Assembly Language and Programming 3rd - Edition Prentice Hall
International, Inc, New Jersey, 1995
 Barry B. Brey, 8086/8088, 80286, 80386 and 80486 Assembly Language
Programming, Macmillan Publishing Company, New York, 1990
Ion Ivan , Cristian Codreanu, Optimizarea programelor asembler, ASE –
Departamentul de Informatică Economică, Bucureşti, 1996
D.S. Jones 80x86 Assembly Programming, Oxford University Press, New York,
1991
 orice alte cărţi, reviste, articole care tratează probleme legate de asamblare.
Structura cursului

• Noţiuni introductive
• Microprocesorul Z80: structură generală, registre
• Setul de instrucţiuni al microprocesorului Z80
• Moduri de adresare
• Cicluri maşină, cicluri instrucţiune
• Studiul cererilor de magistrală şi al întreruperilor (mascabile şi
nemascabile)
• Circuitul DMA al microprocesorului Z80
• Interfaţa paralelă programabilă Z8O-PIO
• Circuitul Z80-CTC (Counter/Timer Circuit)
De ce "programare în limbaj asamblare" ?

• cauze externe independente de voinţa voastră:


- este materie de examen
• coordonatorul de proiect insistă pentru scrierea programului în
asamblare
• trebuie modificat un program existent, scris în asamblare
• un specialist care se respectă ştie să programeze în asamblare
• programul lucrează prea încet sau este prea mare
• dispuneţi de resurse limitate de memorie
• vreţi să înţelegeţi modul în care lucrează un calculator
• vreţi să scrieţi programe eficiente (timp & spaţiu)
• vreţi să încercaţi ceva nou
De ce se evită limbajul de asamblare?

• este prea greu


• este greu de citit şi de înţeles
• este greu de scris
• este greu de depanat şi de întreţinut
• programarea este ineficientă
• viteza nu mai constituie o problema la calculatoarele de azi
• memoria nu mai constituie o problemă
• compilatoarele actuale generează cod eficient
• limbajul de asamblare nu este portabil (este în general specific
fiecărei familii de microprocesoare)
Ce este bun în limbajul de asamblare ?

• trei lucruri: viteza, viteza şi viteza


• VITEZA: cele mai rapide programe se scriu în asamblare
• SPAŢIU: programele scrise în asamblare ocupă cel mai puţin
spaţiu de memorie
• GRAD de LIBERTATE: maxim pt. programarea în asamblare
• CUNOAŞTERE: o mai bună înţelegere a modului de lucru al
procesorului, care poate ajuta la scrierea unor programe eficiente
Ce este bun în limbajul de asamblare ?

• Limbajele de asamblare sunt limbaje tipice pentru microprocesoare, microcontrollere şi alte tipuri
de circuite.
Exemplu: Fie un microprocesor oarecare. Îl vom considera de la început ca un simplu dispozitiv de
tip intrare-ieşire. La "intrare" primeşte nişte date pe care acesta le va prelucra şi va oferi rezultatele
la "ieşire". Exemplul acesta presupune un program fix - microprocesorul va executa întotdeauna
acelaşi program, ceea ce ştim că nu este cazul în realitate. De aceea, va trebui să îi specificăm şi
cum vrem să fie procesate datele. Astfel se introduce ideea de "comenzi" care trebuie transmise
procesorului. Cum comenzile se transmit sub formă binară, un programator ar trebui să scrie un
program sub forma: 000101101011 - ceea ce nu ar fi tocmai prietenos. Pentru a rezolva această
problemă au apărut limbajele de asamblare - limbaje care prezintă o interfaţă mai accesibilă
programatorilor.

• Instrucţiunile în aceste limbaje sunt foarte simple (din punct de vedere al operaţiunilor executate) şi
scurte (mai sunt numite şi "mnemonice" pentru că ajuta la memorarea operaţiilor).
Exemplu: Presupunem că pentru a aduna două valori microprocesorul va primi instrucţiunea 101 (în
format binar); în limbaj de asamblare se poate atribui o instrucţiune de tipul ADD 4, 5 pentru
însumarea celor două numere →această instrucţiune va fi apoi transformată în cod binar şi transmisă
procesorului sub forma 101 0100 0101 (valorile sunt codificate pe câte 4 biţi); se observă clar
avantajul folosirii unui astfel de limbaj intermediar.
- porţiune dintr-un cod C++
(*a)++;
(*a) *= 2.5;
- traducerea codului C în limbaj de asamblare pentru x86 (doar partea de calcul)

movl 4(%esp), %eax # citeşte a de pe stiva (a este un parametru de tip int *)


movl (%eax), %ecx # mută în registrul ECX (o zonă de memorie accesibilă direct de
procesor) # valoarea de la adresa din EAX - practic echivalentul lui *a
incl %ecx #incrementează valoarea din ECX
cvtsi2ss %ecx, %xmm0 ## în final *a va fi în registrul XMM0
mulss LCPI1_0, %xmm0 # LCPI1_0 este o constantă definită în altă parte a programului şi
egală cu 2.5); se face înmulţirea (MULtiply)
cvttss2si %xmm0, %ecx # se mută rezultatul înapoi în ECX
movl %ecx, (%eax) # se pune rezultatul la adresa de memorie indicată de pointerul a
ret # iese din funcţie

- traducerea codului în limbaj de asamblare pentru un ATI Radeon 4890 (din nou,
doar partea de calcul):

02 ALU: ADDR(34) CNT(5)


2 w: ADD_INT ____, R0.x, 1
3 t: I_TO_F ____, PV2.w
4 y: MUL_e ____, PS3, (0x40200000, 2.5f).x
5 t: F_TO_I R0.x, PV4.y
03 MEM_EXPORT_WRITE_IND: DWORD_PTR[0+R1.x].x___, R0, ELEM_SIZE(3)
În linii mari seamănă cu ce s-a întâmplat mai înainte, valoarea e stocată în registrul R0.x,
se incrementează, transformă şi apoi înmulţeşte... la sfârşit se rescrie în memorie...
Exemplu de buclă dintr-un program scris în asamblare pentru un ADSP Blackfin, un procesor
specializat pentru prelucrări de semnale / imagini:

lsetup(strt, end) lc0 = p4 >> 1;


mnop || r0 = [i0++] || r1 = [i3++];
strt: a1 = r0.h * r1.l, a0 = r0.l * r1.l (is) || r0.l = w[i0++] || r2 = [i3++];
-a1 += r0.l * r1.h, a0 += r0.h * r1.h (is) || r0.h = w[i0--];
-a1 += r0.h * r2.l, a0 += r0.l * r2.l (is) || r0 = [i1++] || r3 = [i3++];
-a1 += r0.h * r2.h, a0 += r0.l * r2.h (is) || r0.l = w[i1++];
-a1 += r0.l * r3.l, a0 += r0.h * r3.l (is) || r0.h = w[i1--] || r1 = [i3++];
-a1 += r0.h * r3.h, a0 += r0.l * r3.h (is) || r0 = [i2++];
-a1 += r0.h * r1.l, a0 += r0.l * r1.l (is) || r0.l = w[i2++] || r2 = [i3++];
-a1 += r0.l * r1.h, a0 += r0.h * r1.h (is) || r0.h = w[i2--] || r1 = [i3++];
-r6.h = (a1 += r0.h * r2.l), r6.l = (a0 += r0.l * r2.l) (is);
end: mnop || [p1++] = r6 || r0 = [i0++];

Comentarii:
lsetup = loop setup, iniţializează o buclă; a1, r0, i0, ... sunt o parte din regiştrii procesorului

Din exemplele de mai sus se pot trage câteva concluzii: limbajele de asamblare au
o serie de elemente comune, cel puţin la nivel teoretic: fiecare foloseşte registre -
niște regiuni de memorie proprie unde se pot stoca variabile; registrele sunt foarte
rapide dar şi puţine la număr. De asemenea, în fiecare există o serie de formate
de reprezentare a datelor - datele de tip întreg se stochează binar într-un fel, float-
urile altfel, de unde şi nevoia de instrucţiuni de conversie între formate - cvttss2si
şi mai sugestivele I_TO_F si F_TO_I. Mai e nevoie şi de modalităţi de a accesa
locaţii din memoria RAM, de obicei prin încadrarea adresei (sau registrului care
conţine adresa) între paranteze. Aceste concepte apar în TOATE limbajele de
Când trebuie utilizat un anumit limbaj ?
• Codul maşină – teoretic nimeni nu programează direct în cod maşină. Majoritatea
assembler-elor sunt “free” şi relativ uşor de utilizat comparativ cu programarea direct în cod
maşină.

• Limbajul de asamblare trebuie utilizat atunci când:


- dimensiunea programului este relativ mică
- memoria este un factor important
- aplicaţii de control în timp real
- se utilizează mai mult operaţii de intrare / ieşire (porturi) decât calcule propriu-zise
- un volum de procesare de date limitat
- nu este nevoie de o compatibilitate cu alte microprocesoare

• Limbajul de programare de nivel înalt trebuie utilizat atunci când:


- dimensiunea programului este mare
- aplicaţii care cer un volum mare de memorie
- se utilizează mai puţine operaţii de intrare / ieşire (porturi) decât calcule propriu-
zise
- se cere o compatibilitate ridicată a programului cu alte aplicaţii
- există deja o serie de proceduri, funcţii ce trebuie înglobate în program
Eficienţa codului scris în asamblare
Se doreşte implementarea unei proceduri de înmulţire a 2 numere întregi pe 16 biţi. Sunt realizate
două proceduri în C++ şi asamblare. Este contorizată durata execuţiei procedurilor pentru un număr de
până la 100 de milioane. Calculatorul de test a fost un Pentium 4 la 2.4 Ghz.

Se poate observa că la rularea procedurii de 100 de milioane de ori codul are un avantaj de 3.5 sec.

Observaţii - Performanţele superioare ale codului scris în asamblare depind de:


- Tipul aplicaţiei de implementat
- Compilatorul utilizat
- Tipul procesorului pe care se rulează codul (Ex: nu se utilizează toate nucleele procesorului)
- Eficienţa codului scris în asamblare (este important să nu existe instrucţiuni sau proceduri care să
consume timpul ineficient)
Caracterul neimplicit al definirilor şi prelucrărilor
Limbajele de programare evoluate posedă implementări la nivel de compilatoare care realizează:
• alocări automate de memorie pentru operanzii utilizaţi dar nedefiniţi în program;
• iniţializări la definirea operanzilor;
• semnalarea unor neconcordanţe între natura operanzilor sau incompatibilităţi, cu efectuarea
corecţiilor celor mai probabile sau prin eliminarea instrucţiunii din secvenţă;
• conversiile necesare pentru a asigura gradul de omogenitate necesar al prelucrărilor.

Limbajele de asamblare presupun existente la dispoziţia programatorului a tuturor resurselor sistemului


de calcul. Înseamnă deci, că programatorul este obligat să:
• definească în program toţi operanzii;
• iniţializeze toate zonele de memorie;
• asigure omogenitatea operanzilor în vederea efectuării corecte a operaţiilor de calcul.
În programele scrise în limbaj de asamblare se execută exact operaţiile pentru care există instrucţiuni.
Dacă un operand nu este definit dar este utilizat, asamblorul semnalează acest eveniment ca fiind major şi nu se
va proceda la trecerea la etapele ulterioare asamblării.
Dacă un operand nu a fost iniţializat se va lucra cu conţinutul existent al zonei de memorie. Simplitatea
programului asamblor nu permite analiza corelaţiilor dintre instrucţiuni aşa fel încât să poată semnala că se
folosesc variabile neiniţializate.
În cazul în care un operand A este iniţializat cu un întreg binar, iar operandul B este iniţializat cu un număr
zecimal împachetat, dacă se scrie instrucţiunea:
add a, b
cei doi operanzi sunt trataţi ca întregi binari. Dacă programatorul nu a inclus în program procedura de realizare
a conversiei operandului B această operaţie nu este implicită, deci nu se efectuează.
Secvenţialitatea instrucţiunilor
În programele scrise în limbaj de asamblare instrucţiunile sunt dispuse una după cealaltă formând
secvenţe lineare. Apariţiile instrucţiunilor de salt întrerup caracterul liniar al programelor. Chiar dacă
nu sunt dispuse unele după altele, instrucţiunile tot secvenţial se execută
I1
I2
JMP A
B: I3
I4
A: I5
I6
I7
JZ B
I8
Instrucţiunile se execută în ordinea: I1 I2 I5 I6 I7 I3 I4 I5 I6 I7 I3 … I7 I8.

Absenţa priorităţilor
Limbajele evoluate de programare au definite liste de operatori cu priorităţile din matematică
sau priorităţi definite special.
La construirea de expresii, evaluarea se efectuează în raport cu priorităţile. Astfel, expresia:
a--*++b-c
a--*++b-c
se evaluează astfel:
• se incrementează b;
• se înmulţeşte a cu b;
• se scade c;
• se decrementează a.

Absenţa priorităţilor operatorilor în limbajele de asamblare determină ca ordinea de efectuare a operaţiilor


să fie cea indicată de succesiunea instrucţiunilor în program. Astfel, dacă se consideră expresia:
a*b+c*d
şi se construieşte secvenţa:
mov ax, a
mul b
add c
mul d
se obţine de fapt evaluarea expresiei:
((a*b)+c)*d

Limbajul de asamblare dă posibilitatea programatorului să recompună expresii complexe prin traversarea


secvenţială a instrucţiunilor elementare.
Conversia Binar – Hexazecimal – Octal
Zecimal Binar Octal Hexazecimal
0 0000 0 0 Pentru a converti un număr din binar în hexazecimal se formează grupe de câte
1 0001 1 1 4 cifre care au corespondent o cifră în baza 16. Fie de exemplu numărul:
2 0010 2 2 101011,1010112 pe care dorim să-l convertim în baza 16. Se vor forma
3 0011 3 3 următoarele grupe:
4 0100 4 4
0 0 1 0 1 0 1 1 1 0 1 0 1 1 0 0
5 0101 5 5
6 0110 6 6 2 B A C
7 0111 7 7
Se observă că, în cazul în care nu sunt cifre în număr multiplu de 4 se va completa
8 1000 10 8
numărul cu zerouri nesemnificative la dreapta în partea fracţionară, respectiv la
9 1001 11 9 stânga în partea mai semnificativă.
10 1010 12 A
11 1011 13 B
12 1100 14 C
13 1101 15 D
14 1110 16 E
15 1111 17 F
Codificarea informaţiilor
Prin procesul de codificare informaţiei i se ataşează un cod unic. Prin codificare se urmăreşte:
• reprezentarea coerentă, univocă a informaţiilor in vederea stocării, transmiterii şi a prelucrării acestora
• utilizarea eficientă a spaţiului alocat (spaţiu minim)
• detecţia (şi corecţia) erorilor
• facilitarea (simplificarea) operaţiilor de prelucrare, stocare şi transmitere
• securizarea datelor
Pentru a realiza codificarea se utilizează diverse metode/algoritmi/standarde de codificare care depind de tipul de
informaţie care se codifică.
Formate binare de reprezentare
Bit: binary digit;
unitatea elementară de informaţie
starea unui bistabil, sau a unei celule elementare de memorie
Octet (byte):
grup de 8 biţi
unitatea elementară de adresare la cele mai multe calculatoare actuale (inclusiv Intel x86)
poate reprezenta: o valoare numerică, un caracter (cod ASCII), un set de variabile (semnale) logice
7 6 5 4 3 2 1 0 D7 - bitul cel mai semnificativ
D0 - bitul cel mai puţin semnificativ
Cuvant (word)
15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 D15-D8 - octetul superior (High)
D7-D0 - octetul inferior (Low)
folosit pt. reprezentarea întregilor, simplă precizie
Dublu-cuvânt (double word):

31 ...... 24 23 ...... 16 15 ...... 8 7 ...... 0

- 32 biti, 4 octeţi, 2 cuvinte


–D31-D16 cuvântul superior
–D15-D0 cuvântul inferior
–folosit pentru reprezentarea numerelor în virgulă fixă (dublă precizie la sistemele pe 16 biţi) sau în virgulă
flotantă simplă precizie

Cuadruplu-cuvânt (quad-word)
63 0

- 64 de biţi, 8 octeţi, 4 cuvinte, 2 dublu-cuvinte


- folosit pentru reprezentarea numerelor în virgula fixă (dublă precizie pt. sist. pe 32 biţi) şi in virgulă flotantă
Formate extinse:
–80 de biţi - pt. reprezentarea numerelor in virgula flotanta (formate interne/intermediare)
Reprezentarea numerelor
numere pozitive:
 intervalul de reprezentare: [0.. 2n-1], unde n - nr. de biţi
numere negative:
 mai multe metode de reprezentare (codificare): MS, C1, C2
 intervalul de reprezentare: [-(2n-1-1) ... (2n-1-1)]
 bitul cel mai semnificativ - bit de semn:
 0 - număr pozitiv

 1 - număr negativ
Reprezentarea în virgula flotantă (mobilă) – floating point
• scopul: reprezentarea numerelor foarte mari şi foarte mici
Forma generală a unui număr reprezentat în virgulă mobilă este:
(-1)SxMxBE
unde:
- S este un bit folosit la reprezentarea semnului numărului;
- M este un număr pozitiv subunitar, numit mantisă;
- B este baza de numeraţie în care se face reprezentarea numărului;
- E este un număr întreg cu semn, numit exponent.

Observaţie: Pentru a elimina problema reprezentării semnului exponentului, se adună la valoarea acestuia o
constantă C pentru a deplasa astfel intervalul în care exponentul poate lua valori. Dacă exponentul se reprezintă pe 8
biţi, iar un bit va fi folosit pentru semn, exponentul va lua valori în intervalul [-128, 127]. Pentru a deplasa acest
interval, se adună la valoarea exponentului constanta C = 128, intervalul în care va putea lua valori exponentul după
această transformare devenind [0, 255]. Deoarece cel mai mic număr din interval este acum pozitiv, semnul nu se va
mai reprezenta, cei 8 biţi fiind suficienţi în continuare pentru reprezentarea exponentului deplasat.

• forma de reprezentare: semn, caracteristică şi mantisă

S Caracteristica Mantisa
1 c m
- simplă precizie: 32 de biţi
• 1 Semn, 8 Caracteristica, 23 Mantisa
- dublă precizie: 64 de biti
• 1 Semn, 11 Caracteristica, 52 Mantisa
- caracteristica = exponent + 1/2 (domeniu_exponent)
Reprezentarea şi codificarea informaţiilor
Din punctul de vedere al limbajului de asamblare calculatorul este văzut la nivel hardware: adrese
fizice de memorie, registre, întreruperi, etc. Unitatea de bază a informaţiei memorate în calculator este
bitul (0 sau 1) care corespunde din punct de vedere hardware unui circuit bistabil. Un circuit bistabil
este un circuit electronic care are două stări stabile codificate cu 1 sau 0, capabil să memoreze un bit
de informaţie.
Informaţia care se prelucrează într-un sistem de calcul este foarte variată. Astfel, se reprezintă în
memorie:
– instrucţiuni - prin coduri de instrucţiuni
– date:
• logice: Adevărat/Fals, Închis/Deschis, Pornit/Oprit
• numerice: întregi, nr. fracţionare, nr. pozitive/negative
• alfanumerice: caractere, text
• multimedia: sunet, imagine (audio/video)
– structuri de date
Structuri de date utilizate în limbaje de asamblare
Ca orice limbaj de programare şi limbajul de asamblare presupune operarea cu anumite structuri de date pentru care
trebuie precizate elementele legate de memorarea şi operarea acestora. Astfel specificarea (declararea) structurilor
de date se poate face :
– explicit: prin declaraţii, care indică în general lungimea datei
– implicit: prin utilizarea unor tehnici de adresare
– numele variabilei reprezintă o adresă de memorie
Reprezentarea şi codificarea informaţiilor
Date care intervin într-un program în limbaj de asamblare sunt:
• date booleene (logice). Aceste tipuri de date intervin când se lucrează cu:
– indicatori de condiţie (flag-uri): C,Z,O,...
– zone de memorie cu acces la nivel de bit (numai la anumite procesoare – ex:
microcontrolere)
• caractere
– date reprezentate pe octet în codificare ASCII
• întregi fără semn
– reprezentaţi pe octet, cuvânt sau dublu-cuvânt
• întregi cu semn
–în codificare C2 – anumite instrucţiuni pot face distincţie între întregi cu semn şi
fără semn
–la declarare nu se face distincţie între cele două forme de întregi
• numere în reprezentare flotantă
–dacă se acceptă aritmetica în virgulă flotantă (ex.: prezenţa unui coprocesor
matematic)
–reprezentare pe 32, 64 sau 80 biţi
• pointeri:
– folosiţi pentru păstrarea unor adrese (adr. segment: adr. offset)
• şiruri de caractere sau de cuvinte
• înregistrări
Etapele dezvoltării unui program în limbajul de asamblare sunt următoarele:
• Editarea
• Asamblarea
• Link-editarea
• Rularea şi eventuala depanare
Programul în limbaj de asamblare este scris mai întâi cu un editor de text oarecare, constituind aşa-
numitul program sursă. El trebuie să respecte două categorii de reguli:
- Reguli specifice setului de instrucţiuni ale procesorului pentru care este scris. Aceste reguli
cuprind scrierea corectă a mnemonicelor instrucţiunilor, a operanzilor, diverse prefixe şi notaţii
suplimentare, toate fiind precizate în documentaţia referitoare la procesorul respectiv.
- Reguli specifice programului asamblor cu care se lucrează. Aceste reguli se referă la
declaraţii, etichete, directive de asamblare, pseudoinstrucţiuni, eventual macroinstrucţiuni, etc. Ele sunt
precizate în documentaţia aferentă mediului de asamblare.

După scrierea programului sursă, el este încărcat în asamblor care îl transforma în final în program
obiect. În plus, din procesul de asamblare se pot obţine şi alte fişiere, care permit vizualizarea
programului, a simbolurilor folosite, etc.

Programul obiect este la rândul său preluat de link-editor, fiind transformat într-un fişier executabil
- programul final.

Programul executabil obţinut este testat în diverse moduri, iar în caz de funcţionare
necorespunzătoare din cauze care nu sunt evidente, se încarcă într-un program depanator (debugger).
Acesta permite rularea pas cu pas a zonelor neclare din funcţionarea programului, cu afişarea continuă
a conţinutului registrelor şi memoriei, permiţând astfel localizarea problemelor. După clarificarea lor,
este modificat corespunzător programul sursă, şi procesul se reia.
Elemente ale limbajului de asamblare
Programul sursă este format dintr-un număr de linii, care pot fi:
 Directive de asamblare
 Etichete şi declaraţii de simboluri
 Comentarii
 Linii de instrucţiuni
O linie de instrucţiune a programului sursă are următoarea structură:
{Etichetă:}_Mnemonic_{Prefix}_Operand1{,{Prefix}_Operand2}_{;Comentariu}

unde:
 Acoladele indică un câmp opţional;
 Semnul _ indică un separator, care poate fi format din spaţii sau tab-uri; Între Operand1 şi
Operand2, separatorul este de regula o virgulă;
 Eticheta este un grup de caractere care începe cu o litera şi nu coincide cu un cuvânt rezervat.
Ea trebuie urmată de semnul “:” atunci când se află la începutul liniei. Când este referita ca
operand (de exemplu la o instrucţiune de salt), ea nu mai este urmată de acest semn. Exemple:
Eticheta1, Loop15, Salt, Label, L22, etc.
 Mnemonicul este o prescurtare a descrierii instrucţiunii şi este conform cu setul de
instrucţiuni al procesorului;
 Operandul poate fi un nume de registru, o constantă numerică (date sau adrese), sau o
etichetă, conform descrierii instrucţiunii respective;
 Prefixele dau precizări suplimentare despre operanzi, conform descrierii instrucţiunii
respective;
 Comentariul este opţional şi trebuie precedat de semnul “;” . Tot ceea ce urmează pe o linie
după acest semn este ignorat de asamblor.

S-ar putea să vă placă și