Sunteți pe pagina 1din 395

399

Ion IVAN

Paul POCATILU

Doru CAZAN

Coordonatori

PRACTICA DEZVOLTRII
SOFTWARE
N
LIMBAJE DE ASAMBLARE

Editura Economic
Bucureti 2002

400

Colectivul de autori
Ilie ADRIAN
Laureniu ARICIU
Doru CAZAN
Cristian CODREANU
Valentin DRAGOMIR
Ion IVAN
Laur IVAN
Alexandru LEAU
Adrian LICURICEANU
Zsolt MARK
Teodor MIHAI
Paul POCATILU
Mihai POPESCU
Gabriel UTAC
Sebastian TCACIUC
Daniel VERNI

401

CUPRINS
1
2

Introducere
Caracteristicile limbajelor de asamblare
2.1 Prelucrri elementare
2.2 Caracterul neimplicit al definirilor si prelucrrilor
2.3 Secvenialitatea instruciunilor
2.4 Absena prioritilor
2.5 Contextul dinamic
2.6 Libera poziionare
2.7 Adresarea generalizat
2.8 Necompactitatea construciilor
2.9 Incluziunea
2.10 Concluzii
Reprezentarea informaiei
3.1 Codificarea informaiei
3.2 Organizarea datelor
3.3 Reprezentarea informaiei numerice
3.4 Reprezentri ale irurilor de caractere
Moduri de adresare
4.1 Calculul adresei unui operand
4.2 Modul de adresare imediat
4.3 Modul de adresare registru
4.4 Adresarea direct
4.5 Adresarea indexat
4.6 Adresarea bazat
4.7 Adresarea bazat i indexat

11
13
13
14
16
17
19
20
21
23
24
25
27
27
28
30
36
39
39
41
43
44
45
47
48

402
5

10

11

12

4.8 Adresarea indirect


Indicatorii de condiie
5.1 Registrul FLAGS
5.2 Operaii cu indicatorii de condiie
5.3 Poziionarea indicatorilor de condiie la execuie
5.4 Interaciunea indicatori de condiie - instruciuni
Instruciuni
6.1 Clasificarea instruciunilor
6.2 Descrierea instruciunilor
6.3 Forma extern a instruciunilor
6.4 Forma intern a instruciunilor
6.5 Comentariile
6.6 Efectele execuiei instruciunilor
Definirea structurilor de date
7.1 Date elementare
7.2 Masive unidimensionale
7.3 Masive bidimensionale
7.4 Articolul
7.5 Variabile pointer
7.6 Variabile enumerative
7.7 Tabele de date
7.8 Obiecte
Implementarea structurilor fundamentale
8.1 Programarea structurat
8.2 Structura liniar
8.3 Structura alternativ
8.4 Structura repetitiv standard
8.5 Structura repetitiv condiionat posterior
8.6 Structura alternativ multipl
Aritmetici binare
9.1 Aritmetica binar pe 8 bii
9.2 Aritmetica binar pe 16 bii
9.3 Aritmetica binar pe 32 bii
Aritmetici zecimale
10.1 Ajustri
10.2 Adunarea i scderea
10.3 nmulirea i mprirea
10.4 Proceduri de calcul
10.5 Determinarea lungimii rezultatului evaluri unei expresii aritmetice
ntreruperi
11.1 ntreruperi interne i externe
11.2 Modul de funcionare al ntreruperilor
11.3 Tipuri de ntreruperi
11.4 Exemplu de folosire al ntreruperilor
11.5 Concluzii
Macrodefiniii
12.1 Structura macrodefiniiei

49
53
53
55
56
56
61
61
63
65
71
77
78
81
81
82
82
84
88
89
90
91
95
95
95
96
99
102
103
107
107
109
112
117
117
119
120
122
129
131
131
131
134
138
145
147
147

403

13

14

15

16

17

12.2 Macroapelul i macroexpandarea


12.3 Etichete locale
12.4 Variabile locale
12.5 Macrodefiniii derivate
12.6 Macrodefiniii recursive
12.7 Redefinirea macrodefiniiilor
12.8 Macrodefiniii uzuale
12.9 Concluzii
Proceduri
13.1 Reutilizabilitatea
13.2 Structura unei proceduri
13.3 Apelarea procedurilor
13.4 Locul procedurilor
13.5 Instruciuni specifice lucrului cu proceduri
Prelucrri n virgul mobil
14.1 Scurt istorie a prelucrrilor n virgul mobil
14.2 Resurse
14.3 Setul de instruciuni
14.4 Sintaxa instruciunilor
14.5 Forma extern a instruciunilor
14.6 Exemple
14.7 Concluzii
Lucrul cu iruri de caractere
15.1 Caracteristicile instruciunilor de lucru cu iruri de caractere
15.2 Setul de instruciuni pentru lucrul cu iruri de caractere
15.3 Lucrul cu iruri de caractere fr a folosi instruciuni specializate
15.4 Prefixul REP
15.5 Compararea a dou iruri
15.6 Poziia unui subir intr-un ir
15.7 Eliminarea spatiilor
15.8 Copierea unui ir surs n ir destinaie
15.9 Stabilirea lungimii unui ir
15.10 Conversie de la ntreg binar la hexazecimal ca ir de caractere
15.11 nlocuirea apariiilor unui caracter
15.12 Concatenarea a dou iruri
15.13 Iniializarea unui ir
15.14 Copierea unui ir dintr-o zon de memorie ntr-o alt zon de memorie
15.15 Numrarea caracterelor identice cu un caracter specificat
Fiiere
16.1 Fiiere, articole, identificatori
16.2 Operaii cu fiiere
16.3 Utilizarea de fiiere pentru calculul fondului de salarii
16.4 Operaii cu directori si subdirectori
Programarea mixt C - limbaj de asamblare
17.1 Programul principal este scris n limbaj de asamblare,
procedurile apelate sunt scrise n limbajul C

149
151
153
155
156
157
157
163
165
165
166
168
172
173
179
179
179
182
187
189
190
193
195
195
196
198
199
201
203
204
205
205
206
207
207
209
210
211
213
213
215
221
231
235
235

404

18

19

20

21

22

23

17.2 Programul principal este scris n limbajul C,


procedurile apelate sunt scrise n limbaj de asamblare
17.3 Concluzii
Dezvoltarea de aplicaii orientate obiect in limbaj de asamblare
18.1 Concepte folosite n dezvoltarea programelor orientate obiect
18.2 Definirea obiectelor prin structuri
18.3 Definirea obiectelor prin macrodefiniii
18.4 Folosirea specificaiilor proprii limbajului de asamblare
18.5 Analiza comparativ a variantelor de implementare a obiectelor
Structuri de programe
19.1 Programul ca singur secven (0, 0, 1)
19.2 Programul din secvene distincte grupate ntr-un segment (1, 1, 1)
19.3 Proceduri incluse n segmentul programului principal (1, 1, 1)
19.4 Definiri distincte pentru toate componentele (m, k, n)
19.5 Structuri liniare de program
19.6 Structura arborescent
19.7 Structuri de tip reea
19.8 Concluzii
Optimizarea programelor
20.1 Criterii de optim
20.2 Cicluri main
20.3 Volumul de operaii
20.4 Secvene echivalente
20.5 Alegerea tipului de dat
20.6 Eliminarea subexpresiilor comune
20.7 Gestionarea corect a invarianilor
20.8 Regruparea ciclurilor
20.9 Eliminarea secvenelor inconsistente
20.10 Eliminarea secvenelor inactive
20.11 Reacoperirea segmentelor
20.12 Alocarea optim a regitrilor
20.13 Concluzii
Designul limbajelor de asamblare
21.1 Cerine ale designului
21.2 Structura instruciunii limbajului de asamblare
21.3 Designul corectiv pentru limbajele de asamblare
21.4 Stabilirea numrului de registre
21.5 Concluzii
Elemente de grafica
22.1 Istoric al adaptoarelor grafice
22.2 Rutine BIOS i moduri grafice
22.3 Lucrul n mod grafic folosind un adaptor VGA
22.4 Lucrul n mod grafic folosind un adaptor SVGA
22.5 Concluzii
Programe rezidente
23.1 Caracteristicile programelor rezidente
23.2 ntreruperi pentru programe rezidente

242
251
253
253
257
260
276
282
289
289
296
300
304
306
307
316
318
319
319
320
323
327
329
330
331
332
334
334
335
336
338
339
339
340
342
344
345
347
347
349
351
359
364
365
365
366

405
23.3 Sistemul de operare MS-DOS
23.4 Resurse ale programelor rezidente
23.5 Controlul proceselor
23.6 Probleme specifice n realizarea programelor rezidente
23.7 Activarea programelor rezidente
23.8 Program rezident pentru afiarea ceasului
23.9 Concluzii
24
Programarea n modul protejat
24.1 Moduri de operare ale procesorului 80x86
24.2 Regitrii procesoarelor i386/i486
24.3 Moduri de gestiune a memoriei
24.4 Comutarea in modul protejat
24.5 Implementarea modului de lucru multitasking
24.6 Concluzii
25
Programarea aplicaiilor Windows n limbaj de asamblare
25.1 Interfaa de programare a aplicaiilor Windows
25.2 Organizarea memoriei in Windows 9x
25.3 ncrcarea programelor Win32
25.4 Structura unui program n limbaj de asamblare
25.5 Programarea sub Windows
25.6 Asamblarea si editarea de legturi
25.7 Exemplu de program Win32
Bibliografie
Anexe
A I Arhitectura procesoarelor din familia Intel 80x86
A II Mnemonicele instruciunilor procesorului 80x86
A III Setul de instruciuni ale procesoarelor Intel 80x86
A IV Regitrii coprocesorului 80x87
A V Mnemonicele instruciunilor coprocesorului 80x87
A VI Primul program n limbaj de asamblare
A VII Analiza comparat a utilizrii diferitelor tipuri de reprezentri
A VIII Calcul matriceal - studiu de caz

369
370
373
378
385
388
398
399
399
400
407
409
423
426
427
427
428
430
430
432
441
441
447
A-1
A-5
A-11
A-69
A-73
A-77
A-89
A-101

406

2
CARACTERISTICI ALE LIMBAJELOR DE
ASAMBLARE
2.1 Prelucrri elementare
Limbajele algoritmice de programare (FORTRAN, COBOL, PL/I,
ALGOL) i limbajele evoluate de programare (C++, PASCAL) conin construcii
care realizeaz prelucrri complexe. Compilatoarele lor dezvolt secvene cu multe
instruciuni n module obiect. n schimb, limbajele de asamblare conin prelucrri
elementare. Instruciunile lor sunt puse n coresponden cu operaii simple.
Instruciunea
add O1, O2

realizeaz adunarea operandului O2 la operandul O1. Rezultatul este dat de


operandul O1. Instruciunea
mov O1, O2

efectueaz copierea operandului O2. Dup executarea ei, operandul O1 are acelai
coninut cu cel al operandului O2.
Instruciunea
shl O1,x

realizeaz multiplicarea operandului O1 cu 2x sau deplasarea spre stnga a biilor


ce alctuiesc coninutul operandului O1 cu x poziii.
Instruciunea
xchg O1, O2

realizeaz interschimbul dintre operanzii O1 i O2. Dac nainte de execuie


operandul O1 este egal cu 7 iar operandul O2 este egal cu 13, dup execuia
instruciunii xchg, operandul O1 va fi 13, iar operandul O2 va fi 7.

407

Se identific o multitudine de prelucrri elementare. Fiecrei prelucrri


elementare i se asociaz o instruciune. Proiectarea limbajului de asamblare ia n
considerare rezolvarea oricrei probleme prin construirea de algoritmi la nivelul
pailor elementari. nseamn c mai jos de acest nivel de detaliere nu se mai poate
cobor.
Este foarte important de observat c diferenele dintre limbajele de
asamblare sunt nesemnificative dac sunt analizate prelucrrile elementare.
Dac se studiaz listele de instruciuni ale limbajelor de asamblare
ASSEMBLER, ASSIRIS, MACRO-11, corespunztoare unor generaii mai vechi,
cu cele ale limbajelor de asamblare definite pentru microprocesoarele de azi se
observ existena aceluiai nivel de detaliere n cazul aritmeticii binare i n aria
instruciunilor destinate controlului execuiei.
Tabelul 2.1.
Limbajul
ASSEMBLER

Instruciunea
Adunare
Scdere
nmulire
mprire
Comparare
Salt
necondiionat
Salt condiionat

ASSIRIS

MACRO-11

Limbaj asamblare
microprocesor
486

PENTIUM II

add
sub
mul
div
cmp
jmp

ad4, add
sb4, sbd
mp4, mpd
dv4, dvd
cp4, cp1
bru

add
sub
mul
div
cmp
br

add
sub
mul
div
cmp
jmp

add
sub
mul
div
cmp
jmp

jz, je, jne,...

bcf, bz, ...

beq, bne,...

jz, je, jne,...

jz, je, jne,...

2.2 Caracterul neimplicit al definirilor i prelucrrilor


Limbajele de programare evoluate posed implementri la nivel de
compilatoare care realizeaz:
alocri automate de memorie pentru operanzii utilizai dar nedefinii n
program;
iniializri la definire a operanzilor;
semnalarea unor neconcordane ntre natura operanzilor sau
incompatibiliti, cu efectuarea coreciilor celor mai probabile sau prin
eliminarea instruciunii din secven;
conversiile necesare pentru a asigura gradul de omogenitate necesar al
prelucrrilor.
Limbajele de asamblare presupun existente la dispoziia programatorului a
tuturor resurselor sistemului de calcul. nseamn deci, c programatorul este
obligat s:
defineasc n program toi operanzii;
iniializeze toate zonele de memorie;

408

asigure omogenitatea operanzilor n vederea efecturii corecte a


operaiilor de calcul.
n programele scrise n limbaj de asamblare se execut exact operaiile
pentru care exist instruciuni.
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
asamblrii.
Dac un operand nu a fost iniializat se va lucra cu coninutul existent al
zonei de memorie. Simplitatea programului asamblor nu permite analiza
corelaiilor dintre instruciuni aa fel nct s poat semnala c se folosesc variabile
neiniializate.
n cazul n care un operand A este iniializat cu un ntreg binar, iar
operandul B este iniializat cu un numr zecimal mpachetat, dac se scrie
instruciunea:
add a, b

cei doi operanzi sunt tratai ca ntregi binari. Dac programatorul nu a inclus n
program procedura de realizare a conversiei operandului B aceast operaie nu este
implicit, deci nu se efectueaz.
ntr-un limbaj algoritmic, dac operandul de tip ntreg A este iniializat cu
27, iar operandul B de tip zecimal mpachetat este iniializat cu 13, instruciunea:
C=A+B
se efectueaz prin parcurgerea pailor urmtori:
se convertete operandul B de la zecimal mpachetat la ntreg binar
00

13

00
0D
Temp B

Figura 2.1 Rezultatul conversiei de la zecimal mpachetat la binar

se adun operanzii A i Temp B i rezultatul este memorat n variabila


C
00

1B
A

00
0D
Temp B

00

28
C

409

Figura 2.2 Rezultatul adunrii


Dac n programul scris n limbaj de asamblare sunt definii operanzii A i
B n secvena:
A
B
C

dw
dw
dw

27
0013h
?

executarea adunrii fr ca n prealabil s se apeleze de ctre programator


procedura de conversie de la reprezentarea zecimal mpachetat la reprezentarea
binar,
mov
add
mov

ax, A
ax, B
C, ax

conduce la obinerea n operandul C a irului 002Eh ce corespunde valorii ntregi


46.
2.3 Secvenialitatea instruciunilor
n programele scrise n limbaj de asamblare se afl instruciuni dispuse una
dup cealalt, care formeaz secvene lineare. Apariiile instruciunilor de salt
ntrerup caracterul liniar al programelor. Chiar dac nu sunt dispuse unele dup
altele, instruciunile tot secvenial se execut, figura 2.3.

B:
A:

I1
I2
JMP A
I3
I4
I5
I6
I7
JZ B
I8

Figura 2.3 Secven de instruciuni


Instruciunile se execut n ordinea: I1 I2 I5 I6 I7 I3 I4 I5 I6 I7 I3 I7 I8.
n cazul utilizrii instruciunilor de apel pentru proceduri, secvenialitatea
este construit dinamic.
Programului din figura 2.4 i corespunde secvena:

410

I1 I2 A1 A2 A3 I3 I4 B1 B2 I5 I6.
I1
I2
call A
I3
I4
call B
I5
I6
mov ax,4C00h
int 21h
A

proc
A1
A2
A3
Ret
endp
proc
B1
B2
ret
endp

Figura 2.4 Apel de proceduri


Programatorul cunoate exact c secvena liniarizat conine instruciuni de
salt necondiionat, tocmai elementele care disting liniarizarea aa cum e definit n
programarea structurat.
Programului din figura 2.4 i corespunde n realitate secvena:
I1 I2 J A1 A2 A3 J I3 I4 J B1 B2 J I5 I6

unde prin J s-au notat instruciunile de salt necondiionat ce corespund apelului de


proceduri, respectiv, rentoarcerii n programul apelator.
2.4 Absena prioritilor
Limbajele evoluate de programare au definite liste de operatori cu
prioritile din matematic sau prioriti definite special.
La construirea de expresii, evaluarea se efectueaz n raport cu prioritile.
Astfel, expresia:
a--*++b-c

411

se evalueaz astfel:
se incrementeaz b;
se nmulete a cu b;
se scade c;
se decrementeaz a.
Absena prioritilor operatorilor n limbajele de asamblare determin ca
ordinea de efectuare a operaiilor s fie cea indicat de succesiunea instruciunilor
n program. Astfel, dac se consider expresia:
a*b+c*d

i se construiete secvena:
mov
mul
add
mul

ax,a
b
c
d

se obine de fapt evaluarea expresiei:


((a*b)+c)*d

Pentru evaluarea corect, cu luarea n considerare a ordinei de efectuare a


operaiilor aritmetice se scrie secvena:
mov
mul
mov
mov
mul
add

ax,a
b
e,ax
ax,c
d
e,ax

ceea ce corespunde evalurii:


e=a*b
e=e+c*d

sau:
(e=(e=(a*b))+(c*d))

Limbajul de asamblare d posibilitatea programatorului s recompun


expresii complexe prin traversarea secvenial a instruciunilor elementare.

412

2.5 Contextul dinamic


Limbajele de programare sunt structurate n definiri de tipuri de operanzi i
referiri de operanzi n vederea prelucrrii.
Contextul de prelucrare ncepe cu definirea operanzilor. ntre modul de
definire i modul de utilizare exist restricii pe care programatorul trebuie s le
respecte.
n definirea limbajelor evoluate sau la implementrile unor compilatoare
sunt specificate restriciile i libertile care sunt n legtur cu o serie de operaii.
Sunt numeroase tabelele n care apar tipuri de operanzi i se indic prin Y (Yes)
sau N (No) dac o anumit operaie sau conversie este posibil (implementat) sau
nu.
Astfel, pentru instruciunea MOVE op1 to op2 din limbajul COBOL se
consider tipurile de date i permitivitile din tabelul
Tabelul 2.2.
Op2
Zecimal
Zecimal
ir
ntreg
Display
mpachetat despachetat
caractere
Op1
ntreg
Y
Y
Y
Y
Y
Zecimal
Y
Y
Y
Y
Y
mpachetat
Zecimal
Y
Y
Y
Y
Y
despachetat
Display
Y
Y
Y
Y
Y
ir
N
N
N
N
Z
caractere
Limbajele de asamblare definesc tipuri de zone de memorie ca lungime (DB
define byte, DW define word, DD define double etc. ) i ca aliniere, fr a le
pune n coresponden cu tipurile constantelor (integer, float, char, pointer,
boolean, complex, decimal, display, computational, real, double, string, etc.).
Sensul unui operand este dat de locul pe care l are n lista de operanzi i de
instruciuni care l folosete.
Se consider definirea:
a

dw

n instruciunea
add

a, 2

80

413

operandul a este termen al unei adunri i rezultat al acesteia.


n instruciunea:
add

ax,[a]

operandul a este o variabil pointer care indic adresa unde se afl operandul care
particip ca termen la efectuarea adunrii.
n instruciunea
cmp

a+1,c

se preia unul dintre baii i este interpretat caracter pentru a fi comparat cu


caracterul c.
Semnificaiile operandului a sunt date de contextul creat de programator
prin utilizarea unei anumite instruciuni i prin poziionarea anumit a respectivului
operand n expresia de adresare. Cunoaterea foarte exact a tipurilor de expresii de
referire i a instruciunilor permit gsirea de soluii elegante de a obine prelucrri
foarte diferite i de a da sensuri noi limbajului nsui.
2.6 Libera poziionare
Orice program folosete operanzi i operatori. Limbajul de asamblare
permite structurarea distinct pe segmente a datelor, a stivei i a codului executabil.
Mai mult, exist posibilitatea de a defini o variabil oriunde n segmente i de a o
referi cu semnificaia pe care contextul local (cod instruciune, poziie n lista de
operanzi) l d.
De exemplu, pentru evaluarea expresiei z=x+y variabilele x,y,z se definesc
n segmentul de date:
.data
x
y
z
.stack
dw
.code
...
mov
add
mov

dw
dw
dw

3
5
?

1000 dup (?)

ax,x
ax,y
z,dx

Aceeai soluie se obine i dac variabilele se definesc pe stiv:


.data
.stack

414
x
y
z

dw
dw
dw

3
5
?

...
mov
mov
add
mov

bx, bp
ax, [bx]
ax, [bx+2]
[bx+4], ax

.code

Dac variabilele x, y, z se definesc n segmentul de cod al programului se


obine construcia:
.code
mov
mov
jmp
x
y
z

ax,@code
ds,ax
alfa
dw
3
dw
5
dw
?

mov
add
mov

ax,a
ax,y
z,ax

alfa:

Mai mult, poziionarea operanzilor se efectueaz fie cu luarea n


considerare a cerinelor de aliniere, fie fr a se ine seama de cerinele de aliniere
se procedeaz astfel:
se definesc mai nti variabilele de tip dd;
se definesc mai apoi variabilele de tip dw, dt;
ultimele se definesc variabilele de tip db sau de tip struc.
n cazul n care nu este respectat aceast regul i variabilele de tip dw, dd,
dt se afl la adrese impare, pentru referirea operanzilor sunt necesare cicluri main
n plus la execuie.
2.7. Adresarea generalizat
n limbajele de asamblare sunt definite modaliti variate de referire a
operanzilor (adresare direct, adresare indirect, adresare indexat, adresare bazat,
etc.). Baiii sunt pui n coresponden cu identificatori i cu etichete.
Adresarea generalizat se refer la faptul c n program sunt adresabili toi
baiii, indiferent de locul pe care l au n segmentul de stiv, n segmentul de date
sau n segmentul de cod. Semnificaia zonei de memorie referite este dat de
context (codul instruciunii i poziia n lista de operanzi).
Adresarea generalizat include i posibilitatea de a referi oricare bait din
orice punct al segmentului din care baitul face parte.

415

n definirea:
.data
a
b
...
mov
mov

dw
dw

300 dup (?)


100 dup (?)

ax,a+200
bx,b-400

se refer acelai element din masivul unidimensional, A[100] ( figura 2.5.).


A[0]

A[1]

A[100]

A[299] B[0]

B[1]

a+2

a+200

a+598

b+2

b-400
mov ax, a+200

mov bx, b-400

Figura 2.5 Referiri element n raport cu bazele a i b


Tratarea difereniat a identificatorilor i a etichetelor din programele scrise
n limbaje algoritmice exclud posibilitatea modificrii textului executabil n timpul
execuiei programului.
Dac ntr-un program C++, alfa este eticheta, instruciunea
alfa++

este o construcie incorect, semnalat n faza de compilare.


ntr-un program scris n limbaj de asamblare, considernd secvena:
b:
a:

mov
mov
inc

ax,5
ax,5
ax

atunci instruciunile:
inc

sau
add b, 01h

n cazul n care ar fi acceptate de asamblor, ar putea fi folosite n transformarea


dinamic a codului operaiei.

416

Se observ absena restriciilor n referirea de baii i modificarea acestora.


Instruciunea
mov

ax,7

se structureaz astfel:
b

b+1

b+2
00

07

cod operaie
Figura 2.6 Structura instruciunii mov ax,7
dei la asamblare pe baitul al treilea al instruciunii cu eticheta b se afl numrul 7
instruciunea:
mov

b+2,15

modific valoarea coninut de acest bait, iar rezultatul adunrii este 25 (10+15) i
nu 17 (10+7).
2.8 Necompactitatea construciilor
ntruct o instruciune efectueaz o operaie simpl i instruciunile se
organizeaz n secvene programul scris n limbaj de asamblare este vzut ca
secvene i nu ca expresii.
Mai mult, limitele de poziionare a instruciunilor n secvene reduc gradul
de compactare a programelor.
Dac n limbajul C++ expresia de atribuire multipl sau expresia virgul
permit creterea gradului de agregare cum o efectueaz i operatorul condiional, n
programele scrise n limbaj de asamblare acest grad de agregare nu este atins
datorit simplitii operaiilor cu care sunt asociate instruciunile.
Evaluarea expresiei:
m = min(a,b,c)

se realizeaz prin secvenele de program scris n limbajul C.


m=a
if (mb) m=b;
if (mc) m=c;

Compactitatea secvenei crete prin utilizarea operatorului condiional:

417
(ab) ? (bc) ? m=c: m=b:
(ac) ? m=c: m=a;

se evalueaz o singur expresie cu grad de complexitate ridicat.


n programul scris n limbaj de asamblare evaluarea expresiei revine la
utilizarea secvenei.

e1:

e2

...
mov
cmp
jle
mov
cmp
jle
mov
mov
...

ax,a
ax,b
e1
ax,b
ax,c
e2
ax,c
m,ax

2.9 Incluziunea
Pn la apariia limbajelor de programare din anii 70, limbajelor de
asamblare li se atribuiau o serie de caracteristici, dintre care se enumer:
accesul la toate resursele sistemelor de calcul (registre, funcii de baz,
memorie la nivel de bit);
posibilitatea de a efectua prelucrri imposibil de efectuat n limbaje
precum COBOL, FORTRAN din cauza modurilor de adresare i a
expresiilor de referire;
definirea de mecanisme specifice, particulare de referire a operanzilor i
operatorilor.
Odat cu apariia limbajelor C++, Pascal aceste bariere au disprut. Toate
prelucrrile specifice limbajelor de asamblare sunt incluse n limbajele C++ i
Pascal.
Instruciunilor inc i dec le corespund operatorii ++, respectiv --. Mai mult,
n limbajul C++ apar nuanrile de preincrementare, postincrementare,
predecrementare, postdecrementare.
Accesul la registre se efectueaz cu structura:
struct REGPACK
{
unsigned
unsigned
unsigned
};

r_ax, r_bx, r_cx, r_dx;


r_bp, r_si, r_di;
r_ds, r_es, r_flags;

Figura 2.7 Structura folosit pentru accesul la regitri

418

Accesul la funciile sistemului de operare se efectueaz direct, folosind


funcii cu acelai cod pe care l au ntreruperile sistemului de operare. De exemplu
secvena de schimbare a directorului curent cu ajutorul funciilor sistemului de
operare:
int main(void)
{
char directory[80];
struct REGPACK reg;
printf("Introducei numele directorul de schimbat:");
gets(directory);
reg.r_ax = 0x3B << 8;
/*incarc AH cu 3Bh*/
reg.r_dx = FP_OFF(directory);
reg.r_ds = FP_SEG(directory);
intr(0x21, &reg);
if (reg.r_flags & CF)
printf("Schimbare director esuat\n");
getcwd(directory, 80);
printf("Directorul curent este: %s\n", directory);
return 0;
}

Mai mult, n programele C++ se scriu secvene de instruciuni scrise n


limbaj de asamblare care dau posibilitatea programatorului s controleze mai bine
utilizarea resurselor fizice din programul su.
#include <stdio.h>
void main()
{
unsigned char a=10, b=11, c;
asm {
mov al,a
add al,b
mov c,al
}
printf("\nc=%d\n",c);
}

Figura 2.8 Folosirea limbajului de asamblare ntr-un program scris n C++


2.10 Concluzii
Aceste caracteristici au rolul de a diferenia limbajele de asamblare de
celelalte limbaje. Va fi mai clar momentul n care programatorul trebuie s

419

dezvolte secvene sau proceduri n limbaj de asamblare pentru a obine performana


n aplicaiile sale complexe.

3
REPREZENTAREA INFORMAIEI
Chiar dac un computer stocheaz diverse tipuri de informaie (texte,
imagini, sunete), aceast informaie este reprezentat intern ca informaie numeric.
Aceasta face ca o importan deosebit s fie acordat reprezentrii i prelucrrii
acestui tip de informaie.
3.1 Codificarea informaiei
Sistemele de calcul folosesc pentru prelucrarea i transmiterea
informaiei dou nivele de tensiune (de obicei 0V pentru 0 logic si +3.3V pn la
+5V pentru 1 logic). Cu aceste dou nivele de tensiune se reprezint cele dou
valori diferite, notate prin convenie cu 0 i 1, i care corespund cifrelor
sistemului de numeraie binar.
Binar
0000
0001
0010
0011
0100
0101
0110
0111
1000
1001
1010
1011
1100
1101

Octal
0
1
2
3
4
5
6
7
10
11
12
13
14
15

Hexazecimal
0
1
2
3
4
5
6
7
8
9
A
B
C
D

Tabelul 3.1.
Zecimal
0
1
2
3
4
5
6
7
8
9
10
11
12
13

420

1110
1111

16
17

E
F

14
15

Pe lng sistemul de numeraie binar care utilizeaz baza de


numeraie 2, n sistemele de calcul sunt folosite i sistemele de numeraie octal,
hexazecimal i bineneles zecimal, care folosesc bazele de numeraie 8, 16
respectiv 10. n sistemul de numeraie hexazecimal, numerele de la 10 la 15 sunt
codificate cu ajutorul literelor: A, B, C, D, E, F. n tabelul 3.1 este
prezentat corespondena pentru cele patru sisteme de numeraie.
Toate aceste sisteme de numeraie sunt numite i sisteme de numeraie
poziionale, aceasta nsemnnd c valoarea fiecrei cifre depinde, la formarea
numerelor, de poziia acesteia n cadrul numrului.
Pentru a exemplifica aceast afirmaie considerm numrul 42349(10) scris
n baza 10 (vom folosi n continuare notaia (b) pentru a indica baza b n care a
fost scris numrul). Valoarea acestui numr se calculeaz astfel:
410.000 + 21.000 + 3100 + 410 + 91 = 42349(10)
Se observ c cifra 4 particip la formarea numrului de dou ori, prima dat avnd
valoarea 40.000, iar a doua oar avnd valoarea 40.
O alt observaie foarte important este aceea c valorile cifrelor se obin
nmulindu-le cu puteri ale bazei (1=100, 10=101, 100=102, 1.000=103, etc.).
Aceasta afirmaie este valabil i n cazul altor sisteme de numeraie poziionale,
printre care i sistemele binar, octal i hexazecimal. Numrul 10010(2) reprezint:
124 + 023 + 022 + 121 + 020 = 18(10).
3.2 Organizarea datelor
O singur cifr binar (0 sau 1) este numit bit (prescurtare de la
BInary digiT) atunci cnd este implementat hardware ntr-un computer. Deoarece
n memoria computerului informaia este reprezentat ca o niruire de bii, (0 i
1), se pune problema localizrii unei anumite pri a informaiei (de exemplu un
numr care particip la o operaie de adunare). Pentru a facilita accesul la
informaie, biii au fost grupai prin convenie. Modalitile uzuale de grupare
folosite sunt: un singur bit, cte patru bii (numii nibble), cte opt bii (numii
bait sau 'octet'), cte 16 bii (numii cuvnt), cte 32 bii (numii dublucuvnt).
3.2.1 Bit

421

Deoarece un singur bit este capabil s reprezinte doar dou valori diferite,
exist impresia c foarte puin informaie poate fi reprezentat cu ajutorul unui
bit. Dar nu este chiar aa! Se poate reprezenta cu ajutorul unui bit informaie
privitoare la valori de adevr (Adevrat sau Fals), la strile unui comutator (nchis
sau Deschis), la sexul unei persoane (Brbtesc sau Femeiesc), etc.
3.2.2 Nibble
Construcia nibble este un grup de patru bii. El prezint interes numai din
punctul de vedere al codificrii numerelor n format BCD (Binary-Coded Decimal)
i al reprezentrii numerelor hexazecimale. Cu ajutorul unui nibble se reprezint cel
mult 16 valori distincte.
Structura intern a unui nibble este:
b3

b2

b1

b0

Figura 3.1 Structura intern a unui nibble


unde cu b0,b1,b2,b3 au fost notai cei patru bii care l compun.
3.2.3 Bait
Baitul este cea mai important structur de date folosit ntr-un computer.
Are o lungime de opt bii, notai b0, b1, b2, b3, b4, b5, b6, b7, cel mai semnificativ
fiind bitul b7, iar cel mai puin semnificativ b0.
b7

b6

b5

b4

b3

b2

b1

b0

Figura 3.2 Structura intern a unui bait


Un bait conine exact doi nibble, ceea ce nseamn c se reprezint cu
ajutorul unui bait dou cifre hexazecimale. Numrul de valori distincte ce pot fi
reprezentate pe un byte, este de 256 (28). n computer un bait este folosit pentru a
reprezenta:
- numere fr semn de la 0 la 255;
- numere cu semn de la -128 la +127;
- codurile caracterelor ASCII;
- alte tipuri de date pentru care 256 simboluri distincte sunt suficiente.
3.2.4 Cuvnt

422

Limitele pentru cuvnt au fost stabilite prin convenie la 16 bii sau la


dimensiunea magistralei de date a procesorului. Aceasta nseamn c dimensiunea
unui cuvnt este variabil, depinznd de procesorul instalat pe sistem. n continuare
vom folosi ns cuvntul definit doi baii (16 bii).
Structura unui cuvnt este:

b15 b14 b13 b12 b11 b10 b9

b8

b7

b6

b5

b4

b3

b2

b1

b0

Figura 3.3 Structura intern a unui cuvnt


Un cuvnt este mprit n doi baii sau patru nibble. Cei doi baii din
componena unui cuvnt poart numele de baitul cel mai semnificativ (MSB
most significant byte) i baitul cel mai puin semnificativ (LSB less significant
byte) format din biii b7-b0.
Cu ajutorul unui cuvnt sunt reprezentate 216=65536 valori distincte. Cele
mai importante utilizri ale unui cuvnt sunt pentru reprezentarea:
ntregilor pe 16 bii;
adreselor pe 16 bii;
numerelor ce au nevoie de cel mult 16 bii;
instruciunilor cu operanzi implicii.
3.2.5 Dublu-cuvnt
Aa cum arat i numele un dublu cuvnt este format prin concatenarea a
dou cuvinte. Lungimea unui dublu-cuvnt este de 32 bii i stocheaz
4,294,967,296 valori distincte.
3.3 Reprezentarea informaiei numerice
Informaia numeric este organizat ntr-un computer n diferite moduri, n
funcie de scopul memorrii acesteia i de modurile de prelucrare. Din punct de
vedere al existenei prii zecimale, numerele sunt ntregi sau reale.
3.3.1 Reprezentarea numerelor ntregi n formatul binar
Numerele ntregi se reprezint pe unul sau mai muli baii. Se noteaz acest
numr cu n. De obicei numrul n are valoarea 1, 2, sau 4. Exist dou cazuri
distincte de reprezentri:
- pentru numere ntregi fr semn;
- pentru numere cu semn.

423

Pentru numerele ntregi fr semn, reprezentarea acestora ntr-un sistem de


calcul se face identic cu reprezentarea acestora n sistemul de numeraie binar.
Pentru aceste numere, valoarea maxim reprezentabil pe numrul dat de baii, este
2n8-1 unde 8 este numrul de bii ai unui bait (-1 apare datorit necesitaii de a
reprezenta numrul 0). n tabelul urmtor sunt prezentate cteva numere i
reprezentrile lor ca numere ntregi fr semn pe doi baii.

Valoare
0
1
2
3
4
64
128
256
1024

Tabelul 3.2.
Reprezentare (n=2)
0000 0000 0000 0000
0000 0000 0000 0001
0000 0000 0000 0010
0000 0000 0000 0011
0000 0000 0000 0100
0000 0000 0100 0000
0000 0000 1000 0000
0000 0001 0000 0000
0000 0100 0000 0000

Reprezentarea numerelor ntregi cu semn se face cu ajutorul unui sistem de


reprezentare numit complement fa de doi, primul bit (cel mai semnificativ) fiind
considerat prin convenie bit de semn. Dac acest bit are valoarea 1, atunci
numrul are o valoare negativ, iar dac are valoarea 0, numrul este pozitiv.
Valoarea absolut a numrului se calculeaz diferit dup cum valoarea numrului
numrul este pozitiv sau negativ:
dac valoarea numrului este pozitiv (primul bit are valoarea 0),
atunci restul de n8-1 bii reprezint chiar valoarea numrului;
dac valoarea numrului este negativ (primul bit are valoarea 1),
atunci valoarea absolut a numrului se obine prin complement fa de
2.
Pentru a obine complementul fa de 2 al unui numr se inverseaz toi biii
numrului (0 trece n 1 i invers) i apoi se adun la rezultat valoarea 1. Acest
procedeu se aplic i n cazul transformrii inverse (din numr pozitiv n numr
negativ).
De exemplu pentru a gsi reprezentarea numrului 5 pe un bait, se va
proceda astfel:
se scrie numrul n sistemul binar:
0000 0101
se inverseaz toate cifrele numrului:
1111 1010
se adun valoarea 1 la rezultat:
1111 1011

424

n continuare este prezentat transformarea invers, pentru a obine numrul


reprezentat prin configuraia de bii 1111 1011 (se cunoate c numrul este
reprezentat cu semn, pe un bait):
primul bit este 1 deci numrul este negativ; se aplic procedeul de
complementare fa de 2 pentru a obine valoarea absolut a numrului;
biii _111 1011 se inverseaz: _000 0100 (nu s-a inut cont de bitul de
semn);
se adun 1 la rezultat: _000 0100 + 1 = _000 0101, adic
reprezentarea numrului 5 n sistemul binar.
Numerele ce se reprezint pe n baii n acest format au domeniul de valori
cuprins ntre 2n8-12n8-1-1. n tabelul urmtor se gsesc cteva numere ntregi
negative reprezentate pe doi baii:

Valoare
0
1
2
3
-1
-2
-3
-4
-5

Tabelul 3.3.
Reprezentare (n=2)
0000 0000 0000 0000
0000 0000 0000 0001
0000 0000 0000 0010
0000 0000 0000 0011
1111 1111 1111 1111
1111 1111 1111 1110
1111 1111 1111 1101
1111 1111 1111 1100
1111 1111 1111 1011

3.3.2 Reprezentarea numerelor ntregi n formatul BCD


Formatul BCD(binary-coded decimal) este folosit pentru a reprezenta
numere zecimale ntregi, fiecare cifr fiind reprezentat pe patru bii (un nibble).
De exemplu, numrul 375 va fi reprezentat astfel:
0011 0111 0101
Un avantaj al acestei reprezentri fa de reprezentarea binar este acela c
nu exist o limit maxim a dimensiunii numrului reprezentat. Pentru a mai
aduga o cifr numrului se adaug nc patru bii, n timp ce numerele
reprezentate n format binar sunt limitate de 8, 16, 32 sau 64 de bii.
n computer, pentru stocarea acestor numere sunt folosite dou reprezentri
diferite:
reprezentarea zecimal mpachetat (packed BCD);
reprezentarea zecimal despachetat (unpacked BCD).

425

3.3.2.1 Reprezentarea zecimala despachetat se concretizeaz prin


ocuparea de ctre fiecare cifr a numrului a cte unui bait. Astfel, numrul 75431
se va reprezenta n format zecimal despachetat pe 5 baii, astfel:
00

07

00

05

00

04

00

03

00

01

un bait
Figura 3.4 Reprezentarea zecimal despachetat
Dac numerele se introduc de la tastatur ca ir de caractere ASCII, cifrele
numrului reprezentat zecimal despachetat se obin prin scderea numrului 30h
din codurile caracterelor.

Caracter
0
1
2
3
4
5
6
7
8
9

Tabelul 3.4.
Codul hexazecimal ASCII
30
31
32
33
34
35
36
37
38
39

3.3.2.1 Reprezentarea zecimala mpachetat presupune ocuparea fiecrui


bait de cte dou cifre zecimale. Astfel numrul 75431 se va reprezenta n format
zecimal mpachetat astfel:
00

07

05

04

03

01

un bait
Figura 3.5 Reprezentarea zecimal mpachetat
3.3.3 Reprezentarea numerelor reale
Reprezentarea numerelor reale se face n dou moduri distincte, i anume
reprezentare n virgul fix i reprezentare n virgul mobil, n funcie de modul
de reprezentare a prii ntregi i a prii fracionare a numrului.

426

3.3.3.1 Reprezentarea numerelor reale n virgul fix presupune c se


aloc pentru reprezentarea prii ntregi i a prii fracionare a numrului, un
numr de cifre constant. Dac se consider, de exemplu, c un numr n baza 10
reprezentat va avea o precizie de 0.001 i c acest numr nu poate fi mai mare
dect 9999, atunci numrul de cifre pentru partea ntreag este 4, iar cel pentru
partea fracionar este 3. Dac numrul are i valori negative, atunci se impune
folosirea i a unui cmp separat pentru reprezentarea semnului, care prin convenie
va avea valoarea 0 dac numrul este pozitiv sau valoarea 1 dac numrul este
negativ. Deoarece sunt cunoscute numrul de cifre al prii ntregi i numrul de
cifre al prii fracionare, necesitatea reprezentrii virgulei dispare. Fiecare cifr se
va reprezenta fie pe un octet (din care vor fi ocupai doar patru bii), fie cte dou
pe un octet. Cteva numere astfel reprezentate sunt:

Numr

semn
4823.493
0
-52.3
1
2.445
0

mii
4
0
0

sute
8
0
0

Tabelul 3.5.
Reprezentare
zeci uniti zecimi Sutimi Miimi
2
3
4
9
3
5
2
3
0
0
0
2
4
4
5

3.3.3.2 Reprezentarea numerelor reale n virgul mobil (floating


point) se folosete n reprezentarea numerelor implicate n calcule tiinifice.
Forma general a unui numr reprezentat n virgul mobil este:
(-1)SMBE
unde:
S este un bit folosit la reprezentarea semnului numrului;
M este un numr pozitiv subunitar, numit mantis;
B este baza de numeraie n care se face reprezentarea numrului;
E este un numr ntreg cu semn, numit exponent.
Pentru a elimina problema reprezentrii 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 bii, 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 numr din interval este acum pozitiv, semnul nu se va mai
reprezenta, cei 8 bii fiind suficieni n continuare pentru reprezentarea
exponentului deplasat.
La reprezentarea numerelor n virgul mobil se aplic o transformare i
asupra mantisei, numit normalizare, n urma creia, prima cifr de dup virgul
va fi diferit de 0 (ceea ce impune i modificarea exponentului). Dac

427

reprezentarea numrului se face n baza 2, atunci prima cifr de dup virgul va fi


ntotdeauna 1 i nu va fi reprezentat nici aceasta.
Trei standarde privind reprezentrile numerelor n virgul mobil sunt
folosite n funcie de precizia dorit. Cele trei standarde difer din punctul de
vedere al numrului de cifre disponibile reprezentrilor prii ntregi i a prii
fracionare. Aceste standarde sunt prezentate n urmtoarele figuri:
B7
B15
E0
S

B6
B14
B22
E7

B5
B13
B21
E6

B4
B12
B20
E5

B3
B11
B19
E4

B2
B10
B18
E3

B1
B9
B17
E2

B0
B8
B16
E1

Figura 3.6 Reprezentarea n virgul mobil, simpl precizie


B7
B15
B23
B31
B39
B47
E3
S

B6
B14
B22
B30
B38
B46
E2
E10

B5
B13
B21
B29
B37
B45
E1
E9

B4
B12
B20
B28
B36
B44
E0
E8

B3
B11
B19
B27
B35
B43
B15
E7

B2
B10
B18
B26
B34
B42
B50
E6

B1
B9
B17
B25
B33
B41
B49
E5

B0
B8
B16
B24
B32
B40
B48
E4

Figura 3.7 Reprezentarea n virgul mobil, dubl precizie


B7
B15
B23
B31
B39
B47
B55
1
E7
S

B6
B14
B22
B30
B38
B46
B54
B62
E6
E14

B5
B13
B21
B29
B37
B45
B53
B61
E5
E13

B4
B12
B20
B28
B36
B44
B52
B60
E4
E12

B3
B11
B19
B27
B35
B43
B51
B59
E3
E11

B2
B10
B18
B26
B34
B42
B50
B58
E2
E10

B1
B9
B17
B25
B33
B41
B49
B57
E1
E9

B0
B8
B16
B24
B32
B40
B48
B56
E0
E8

Figura 3.8 Reprezentarea n virgul mobil, precizie extins


S-au notat cu Bi biii mantisei normalizate, cu Ei biii exponentului deplasat
i cu S semnul mantisei. Se observ aezarea baiilor n memorie, primul fiind
baitul cel mai puin semnificativ al mantisei.

428

3.4 Reprezentri ale irurilor de caractere


3.4.1 Definire ir de caractere
Coninutul unei zone de memorie este interpretat n funcie de context. Cei
opt bii care alctuiesc un bait sunt pui n coresponden ntr-un context dat cu un
element al alfabetului ASCII .
irurile de constante se definesc i se iniializeaz prin construcii de forma:
sir1 db Ionescu Gheorghe
sir2 db c, i, m, e, n, t
sir3 db 30 dup (=)

Utilizarea irurilor n programe pentru operaii de intrare / ieire presupune


luarea n considerare a unor caractere de control:
delimitatorul de sfrit de ir; n limbajul C++ delimitatorul de sfrit de
ir este \0 iar funciile sistemului de operare impun ca delimitator
caracterul $.
caracterul de control pentru trecerea la pagin nou sau rnd nou; pentru
sfrit de rnd (trecere pe rnd nou) sunt folosite mpreun dou
caractere: \13, \10. Primul (\13) numit CR (carriage return) este
folosit pentru ntoarcerea la nceputul rndului iar al doilea (\10) numit
LF (line feed) este folosit pentru avansul la rndul urmtor.
deplasarea cu o poziie napoi nsoit de tergerea caracterului de pe
acea poziie se face cu ajutorul caracterului \8 (backspace).
deplasarea nainte cu opt poziii se realizeaz cu ajutorul caracterului
TAB (\9).
3.4.2 Constante de tip ir de caractere
Constantele ir de caractere sunt definite cu ajutorul apostrofurilor. Astfel:
abcdEFG
12345678
+-.a()

sunt iruri de caractere.

429

Lungimea unui ir de caractere este dat de numrul simbolurilor cuprinse


ntre apostrofuri. Astfel, irul a+b+c+-d are lungimea 8 (caractere), iar irul x
are lungimea 1.
Cu ajutorul irurilor de caractere se iniializeaz numeroase cmpuri ale
structurilor de date care descriu nume de persoane, denumiri de materiale, adrese
de instituii, numere de telefon (Ionescu Gheorghe, ciment, +40.1.15.15.00 sau
(40)115.15.15).
3.4.3 Variabile de tip ir de caractere
Sunt limbaje de programare care lucreaz cu tipul de date ir de caractere
(string). Alte limbaje ns lucreaz cu zone de memorie date prin adres de nceput
(sau de sfrit) i prin lungime. Coninutul baiilor este interpretat ca reprezentnd
simbolurile codului ASCII . i limbajul de asamblare definete zona de memorie ca
ir de baii pe care o iniializeaz. Astfel, n secvena:
sir1 db 15 dup(?)
sir2 db abcdefghijk
sir3 db 100 dup(a), b

sau alocat trei zone de memorie dup cum urmeaz:


prima zon de memorie are 15 baii, nu este iniializat, iar primul bait
este pus n coresponden cu identificatorul sir1;
a doua zon de memorie are atia baii cte simboluri se afl ntre
apostrofurile ce delimiteaz constanta ir de caractere (11 caractere);
primul bait este pus n coresponden cu identificatorul sir2;
a treia zon a lungimea de 101 baii, din care primii 100 baii au fost
iniializai cu caracterul a, iar ultimul bait a fost iniializat cu
caracterul b; primul bait al zonei este pus n coresponden cu
identificatorul sir3. Expresiile de referire sir2+5, sir3+100 sau sir3-5
refer baiii ce conin caracterele 'f', 'b', respectiv 'g'.

430

4
MODURI DE ADRESARE
4.1 Calculul adresei unui operand
Adresa fizic a unui bait este un numr natural. n funcie de dimensiunea
memoriei care se acceseaz sunt proiectate dimensiunile registrelor care stocheaz
informaia de adres.
Exist calculatoare care au n structur registre pe patru baii numite
registre de baz care stocheaz adresa de nceput a segmentului program, de
exemplu. Adunnd la aceast adres deplasamentul operandului se obine adresa lui
fizic. Numrul reprezentat pe 32 bii este suficient de mare, i nu mai necesit
artificii de combinare adres segment cu deplasament.
Exist tabele care concentreaz corelaia dintre lungimea expresiei de
adres n bii i lungimea maxim a zonei ce poate fi accesat. Astfel, cu adrese
definite pe 20 bii se pot accesa baiii ce formeaz o memorie de 1 MB.
Algoritmul pentru calculul de adres este format din operaii de deplasare
spre stnga i din adunri. Valoarea adresei apare ca o agregare a mai multor
elemente. Sunt rare cazurile cnd este impus proprietatea de dezagregare unic a
adresei, n componentele iniiale.
De cele mai multe ori, dezagregarea vizeaz determinarea deplasrii unui
operand avnd ca elemente de calcul adresa fizic i coninutul registrului segment,
adic adresa de nceput a segmentului.
Procesorul 286 de exemplu, ia n considerare pentru calculul de adres:
coninutul registrului segment (16 bii);
deplasarea operandului a crui adres se calculeaz (16 bii).
Prin deplasarea cu patru poziii spre stnga a coninutului registrului
segment i prin adugarea la noua valoare obinut a deplasrii operandului, se
obine adresa fizic a operandului.
De exemplu, registru segment DS are coninutul 00F0h, iar deplasarea
operandului este 000Ah. Deplasarea spre stnga cu 4 bii conduce la
00F00h + 000Ah=00F0Ah,
acest rezultat reprezint adresa fizic a operandului considerat.

431

Expresia de calcul a adresei fizice a unui operand va apare de fiecare dat,


indiferent de sistemul de calcul cu care se opereaz sub forma unei expresii de
forma:
EA=x1*y1 + x2*y2 + + xn*yn
unde:
xi numr ntreg, deplasare absolut sau relativ;
yi coeficient de forma 2k, k=0,1,2,,m;
n numrul termenilor care intervin n calcul;
m are valoarea 15 dac se lucreaz pe 16 bii
respectiv, 31 dac se lucreaz pe 32 bii.
Se consider memoria unui calculator ca fiind format din baiii dispui
unul dup altul, avnd adresele fizice 0000, 0001, ., FFFFh.
Memoria este mprit n segmente de lungime fix, lungime care se transform n
raia unei progresii aritmetice. Termenii progresiei sunt de fapt adresele de nceput
ale segmentelor. Segmentul Si va avea adresa de nceput a0 + (i-1)*L unde a0
reprezint adresa primului bait al memoriei, iar L este lungimea segmentului.
n cadrul unui segment se consider un punct fix, a crui poziie se
stabilete fa de nceputul segmentului. Se consider n continuare un alt punct a
crui poziie este stabilit fa de cel considerat anterior. Poziiile astfel obinute
sunt poziii relative.
Aa cum rezult din figura 4.1. adresa baitului x se calculeaz lund n
considerare deplasrile relative d1, d2, d3, d4 i deplasarea absolut d0.
d0
0

Sk

d1

d2
B

d3
C

d4
D

Figura 4.1 Calculul adresei unui operand


unde:
di distane relative, iar d0 este distana absolut;
Sk segmentul k din memoria calculatorului;
A adresa de nceput a segmentului;
B, C, D, - baiii considerai repere n segmentul Sk alese de
programatori;
x bait oarecare ce se asociaz unei variabile.
n cazul procesorului 286 adresa se calculeaz dup formula:
EA=c0a0*22 + c1*x1 + c2*x2 + c3*x3

432

unde:
a0 adresa de nceput a segmentului, coninut ntr-un registru
(CS, DS, ES);
ci coeficientul cu valoare unu dac tipul de deplasare relativ
i este definit (c1 corespunde deplasrii ca baz, c2
corespunde deplasrii variabile, c3 corespunde deplasrii
baitului asociat unei variabile); dac c0=c1=c2=c3=0
adresarea este imediat;
xi deplasarea de tip i; x1 este stocat ntr-un registru de baz,
x2 este stocat ntr-un registru index, iar deplasarea x3
este pus n coresponden cu numele unei variabile.
Expresiile de calcul ale adreselor prin valorile diferite ale coeficienilor c i
determin modurile de adresare.
Modul de adresare este definit ca algoritm de calcul al adresei absolute pe
baz de distane ale operanzilor.
Modul de adresare ofer posibilitatea implementrii att a structurilor
fundamentale de date (capacitatea de a referi elemente din matrice, linii din matrice
sau chiar matricea n ansamblul ei) ct i a structurilor de programare (structura
repetitiv este posibil numai utiliznd registrul de index, iar includerea de structuri
repetitive presupune i utilizarea unui registru de baz).
4.2 Modul de adresare imediat
Acest mod de adresare corespunde situaiei n care programatorul scrie
instruciuni de forma R-I, M-I, ca de exemplu:
mov
add
xor
mov

ax, 1ah
ax, 2
bx, 0fa00h
alfa, 500

Programul asamblor genereaz codul asociat fiecrei instruciuni incluznd


lng baitul (baiii) de descriere ai codului operaiei i ai modului de adresare codul
asociat constantei definite n al doilea operand. Astfel, secvena:
mov
sub
add
mov
mov

cx, 4
si, 15
ax, 100
byte ptr[bx+1], 120
dx, 16

;b9
;83
;05
;c6
;ba

0004
ee 0f
0064
47 01 78
0010

pune n eviden faptul c asamblorul genereaz chiar n corpul codului asociat


fiecrei instruciuni constanta (al doilea operand) cu care se opereaz.
Din analiza numrului de cicluri main rezult c adresarea imediat
necesit un numr de cicluri mai mare. Constantele se utilizeaz cnd trebuie

433

incrementat sau decrementat un registru cu o raie mai mare ca 2, cnd se lucreaz


cu mti n instruciuni logice i cnd se efectueaz comparri pentru a defini limite
de intervale. Astfel, instruciuni ca:
mov
cmp
jl
cmp
jg
and
add
sub

ax,0
bx,100
alfa
bx,400
beta
bx,0ff0h
si,4
di,2

;iniializare registru
;comparare
;salt dac este la stnga intervalului
;comparare
;salt dac este la dreapta intervalului
;i pe bii registru bx cu masca 0ff0h
;incrementare registru si
;decrementare registru di

demonstreaz utilitatea modului de adresare imediat pentru a nu face exces de


definire de variabile n memorie i de folosire a instruciunilor de tip R-M.
Instruciunea:
mov

ax,200

;iniializare registru 4 cicluri

poate fi nlocuit prin instruciunea:


mov

ax,val_200

;14 cicluri

unde variabila val_200 a fost definit prin:


val_200 dw 200

i este folosit o singur dat. De regul nu se definesc zone de memorie pentru a fi


folosite o singur dat i mai ales pentru iniializri. Este necesar definirea corect
a constantelor, aa fel nct lungimea operandului destinaie s fie mai mare sau
egal cu lungimea operandului surs la definire, conversia de lungime este
efectuat de programul asamblor.
n secvena:
mov
mov
mov

al, 2000
ax, 100
bx, 4000

lungimea registrului al este de un bait n timp ce constanta 2000 se reprezint pe 2


baii, deci construcia este eronat.
A doua instruciune are operandul destinaie cu lungime de 2 baii, iar
operandul surs poate fi generat pe un bait. Programul asamblor va face conversia,
genernd constanta 0064h. n a treia instruciune, lungimile operanzilor coincid.
Adresarea imediat se dovedete ineficient atunci cnd constantele definite ca

434

operanzi trebuie modificate la dezvoltarea programelor n timp. Acest impediment


se elimin prin definirea de constante simbolice. Instruciunea:
mov

ax,100

este echivalent cu instruciunea:


mov

ax,c_100

unde n prealabil s-a fcut definirea:


c_100 equ

100

4.3 Modul de adresare registru


Se utilizeaz atunci cnd operanzii se afl n registre, fiind specific tipurilor
de instruciuni R-R.
La definirea mnemonicelor i a codurilor de operaii, cnd se lucreaz n
modul R-R instruciunile au asociate coduri distincte.
Viteza de calcul este superioar, prin numrul de cicluri, de regul mai mic
necesar pentru acest mod de adresare.
Secvena:
inc
push
pop
xchg

ax
ax
ax
cx,ax

40h
50h
58h
91h

pune n eviden faptul c registrele prefixate sunt cele care influeneaz structura
codului fiecrei instruciuni.
Modul de adresare registru conduce la dezvoltarea n procesul de asamblare
a codurilor de instruciuni pe un bait (dac registrele sunt prefixate) sau pe doi baii
pentru combinaii oarecare de registre.
Unele dezvoltri de coduri sunt prezentate n secvena:
mov
mov
mov
shr
xor
sub

cs,ax
ds,ax
ss,ax
ah,cl
ax,ax
si,cx

8e
8e
8e
d2
33
2b

c8
d8
d0
ec
c0
f1

Se observ c al doilea bait conine constantele hexazecimale F, D, E, C


fapt ce determin ca dezvoltarea biilor 7, 6 ce corespund codului mm din baitul
MODRM (vezi capitolul INSTRUCIUNI) s fie 11b, adic biii 2, 1, 0 vor fi

435

interpretai cod registru. Modul de adresare registru este obligatoriu la iniializarea


registrelor segment (mov reg-seg, AX).
Cnd se efectueaz calcule i rezultate intermediare sunt stocate n alte
registre, n final se va obine un rezultat care va fi n registrul AX. Exist operaii
care impun lucrul cu registre, precum XCHG (Exchange), PUSH, POP, INC, ns pot
lucra i cu operanzi definii n memorie, dar specificul informaiilor pe care le
vehiculeaz ofer frecven mai mare structurilor de tip R-R a naturii operanzilor.
Deci, n programe, acestea vor apare frecvent avnd operanzi registre.
4.4 Adresarea direct
Este modul de adresare cel mai frecvent ntlnit n programe. Corespunde
tipurilor de instruciuni R-M, M-R. Un operand este registru, iar al doilea operand
ocup o zon de memorie, pus n coresponden cu un nume.
Adresarea direct presupune instruciuni de forma:
cod_operaie operand_1, nume_variabil
sau
cod_operaie nume_variabil,operand_2.
Figura urmtoare arat cum funcioneaz o instruciune mov ax, x n care se
folosete acest mod de adresare:
mov ax, x

AX
4F

13

13
4F
x
Figura 4.2 La primul pas se face calculul adresei de memorie iar la al doilea pas
coninutul zonei de memorie este mutat n registrul AX
Secvena:
mov
mov
mov
add
sub
mov
add

ax, alfa
al, byte ptr beta
gama, dx
ax, sum
cx, ratia
ah, sir+2
sir-5, al

436

utilizeaz operanzii alfa, beta, gama, sum, ratia, ir, direct prin numele lor, tiind c
n procesul de asamblare acestor nume li se asociaz deplasri fa de adresa de
nceput a segmentului unde sunt definite.
Dac s-au definit i s-au alocat zone pentru operanzii din secvena:
00a0
00a2
00a4
00ac

a
b
c
e

dw
dw
dw
dw

10
20
30, 40, 10, 20
?

referirea lor folosind modul de adresare direct din secvena:


mov
add
add
add
mov

ax, a
ax, b
ax, c
ax, c+6
e, ax

i generarea la asamblare arat modul de folosire a deplasrilor 00A0, 00A2, 00A4,


00AC, care dei puteau fi reprezentate pe un bait sunt expandate pe doi baii, lucrul
cu deplasri impune operanzi pe 16 bii. n modelul de calcul al expresiei de adres
c1=c2=0 i c0=c3=1. Distana apare dintr-o singur bucat. Expresia de adres
este constant, includerea n structuri repetitive echivaleaz cu folosirea de
invariani, dac se justific.
Secvena:
mov
ciclu:
add
loop

ax, alfa+10*3-4
ax, beta
ciclu

exemplific introducerea unui invariant (beta) n structura repetitiv, justificabil


dac se urmrete o nmulire cu un numr dat a coninutului zonei beta.
4.5 Adresarea indexat
Procesorul este nzestrat cu registrele index SI i DI. Coninutul unui
registru index este un numr, termen al unei progresii aritmetice, cu semnificaie de
deplasare relativ.
Adresarea indexat permite traversarea de structuri de date omogene i
implementarea structurilor repetitive.
Registrul index trebuie mai nti iniializat, dup care coninutul su se
modific. Dac traversarea structurii omogene se efectueaz de la primul element
spre ultimul, iniializarea registrului index se face cu valoarea zero, iar n timpul
traversrii i se va aduga o raie. Cnd traversarea se efectueaz de la ultimul spre

437

primul element, coninutul registrului index va conine o deplasare care n expresia


de adres, va accesa ultimul element, dup care din registrul index se scade o raie.
Registrul index poate fi utilizat pentru controlul numrului de repetri.
Forma expresiei de adresare cu registrului de index este:
cod_operaie
cod_operaie
cod_operaie

reg, deplasare [registru_index]


reg, deplasare+registru_index
registru_index
deplasare
reg.

Urmtoarea secven evideniaz modul de calcul al adresei pentru


adresarea indexat:
mov
xor
xor
ciclu:
add
inc
inc
loop

cx,20
si,si
ax,ax
ax, x[si]
si
si
ciclu

n aceast secvena de program este pus n eviden iniializarea registrului SI,


utilizarea sa pentru referirea unui element al masivului unidimensional x i
adugarea unei raii.
Secvena:
xor
xor
ciclu:
add
inc
inc
cmp
jle

si,si
ax,ax
ax,a[si]
si
si
si,2*(20-1)
ciclu

arat cum registrul index este folosit ca registru de control pentru gestionarea
ciclurilor.
n expresie poate lipsi deplasarea, caz n care registrul index trebuie pregtit
ca s refere corect elementele, ncrcnd adresa primului element ce se acceseaz.
Secvena:
mov
lea
xor
ciclu:
add
add
loop

cx,20
si,x
ax,ax
ax,[si]
si, 2
ciclu

438

utilizeaz o expresie de referire a elementului unui masiv unidimensional fr


termenul deplasare, acesta fiind inclus deja n registrul si de index.
4.6 Adresarea bazat
n cazul structurilor complexe referirea prilor i a elementelor este
realizat difereniat. O variabil de tip articol corespunde unei structuri cu dou
nivele. La primul nivel se afl ntregul, variabila n totalitatea ei, iar la nivelul al
doilea sunt membrii ei. n cazul masivelor bidimensionale, reprezentarea
arborescent conduce la o structur cu trei nivele. Pe primul nivel se afl matricea
ca un ntreg, cu toate componentele sale i se refer ca zon de memorie nedivizat.
La nivelul al doilea se afl liniile matricei, iar pe al treilea nivel se afl elementele
acesteia.
Baitul care delimiteaz nceputul zonei de memorie a unei structuri
compuse este considerat bait de baz. Referirile membrilor se efectueaz n raport
cu poziia acestuia. Registrele BX i BP se utilizeaz pentru a memora adresele
baiilor de baz. Aceste registre se numesc din aceast cauz registre de baz. Dac
registrul de baz utilizat este BX, registrul de segment pentru evaluarea expresiei
de adres va fi DS. Prin utilizarea registrului de baz BP, registrul de segment este
SS, deci se va lucra pe stiv.
Ca i n cazul adresrii indexate, registrul de baz ce se iniializeaz, este
utilizat pentru referire i este incrementat sau decrementat sau se utilizeaz
deplasri n mod adecvat, care la evaluarea expresiei de adres vor referi corect
membrul cerut din structura compus.
mov AX, [BX]+2

1
BX

00

04

AX

FC

3
01

02

03

04

05

4A

4
4A
06

FC
07

08

09

0A

0B

0C

Figura 4.3 Calculul adresei n cazul adresrii bazate


Secvena:
mov
mov
add
add

bp,
ax,
ax,
ax,

offset alfa
bp + 2
bp + 8
bp + 144

439

exemplific referire de membri cu poziii neregulate n structur.


Dac structura compus nu are un grad de omogenitate sczut, registrul de
baz, mpreun cu deplasarea refer elementele ca n expresii de forma:
mov
mov
mov

ax, beta[bp + 52]


bx, gama + bp
cx, delta + bx + 54

4.7 Adresarea bazat i indexat


Structurile de date definite pe mai multe nivele necesit expresii complexe
pentru referirea elementelor. Astfel, pentru referirea unui element dintr-o matrice
este necesar poziionarea pe linia matricei i apoi n cadrul liniei, pe element.
Formula de referire a elementului aij al unei matrice cu m linii i n coloane
este:
adresa(aij) = adresa(a00) + (i*n + j)*lungime_element.
Adresa primului element este reper fix, iar adresa de nceput a liniei i-1 este
adres de baz pentru referirea unui element.
n formul apar dou progresii aritmetice, una refer linia, a doua refer
elementul n cadrul liniei. Expresia de adres crete n complexitate. Mai mult, n
timp ce un registru operand n expresia de adres are coninut cresctor, cellalt
poate avea coninut cresctor sau descresctor. Traversarea structurilor complexe se
va efectua n direcii compuse, ceea ce permite realizarea unor algoritmi de referire
cu grad de generalitate ridicat.
Expresiile de adres au una din structurile:
bp + di
bx + si
bp
[di]
bx
[si]
reg_baz + reg_index + deplasare
deplasare
reg_baz + reg_index
deplasare
[reg_baz] [reg_index].

Secvena:

ciclul_1:
ciclul_2

xor
xor
xor
mov
push
mov
add
add

bx,
si,
ax,
cx,
cx
cx,
ax,
si,

bx
si
ax
nr_linii
nr_coloane
x [bx] [si]
2

440
loop
xor
pop
mov
shl
add
loop

ciclul_2
si, si
cx
dx, nr_coloane
dx,2
bx, dx
ciclul_1

exemplific accesarea elementelor unei structuri cu trei nivele i utilizeaz registrul


de baz BX, pentru accesarea liniilor (elementele de pe al doilea nivel) i registrul
index SI pentru accesarea membrilor de pe ultimul nivel.
4.8 Adresarea indirect
Utilizarea variabilelor pointer presupune implementarea modului de
adresare indirect. Adresarea indirect presupune ca un registru sau o zon de
memorie s conin adresa (deplasamentul) unei variabile. De asemenea, adresarea
indirect presupune existena unui operator care s realizeze extragerea
coninutului din acea zon de memorie i s-l interpreteze ca deplasament.
mov AX, [BX]

1
BX

00

02

AX
2

00

01

E5

26

3
26
02

E5
03

04

Figura 4.4 Calculul adresei n cazul adresrii indirecte


Dac se consider secvena:
mov
xor
xor
add

si,
bx,
ax,
ax,

offset x
bx
ax
[bx + si]

aceasta conine evaluarea de adres BX + SI care nseamn: coninutul lui BX se


adun cu coninutul registrului SI i rezult adresa operandului al crui coninut
este adunat la registrul acumulator AX, deci registrul SI conine un deplasament
care localizeaz operandului care e folosit la adunare.
Sunt limbaje de asamblare n care modul de adresare indirect este
implementat, n acest scop utilizndu-se un operator. Se presupune c este definit

441

limbajul de asamblare XX, iar operatorul de indirectare este *. n aceast situaie se


impune restructurarea formei interne a instruciunii ca s accepte descrierea
distinct pentru adresarea direct, i respectiv, pentru adresarea indirect (un bit cu
valoare zero adresare direct, unu adresare indirect).
Operatorul * este utilizat i pentru construirea de secvene ce corespund
indirectrii pe mai multe nivele. Astfel secvena:
mov
mov
mov
mov
mov
mov
mov

ax, offset a
adr_a, ax
ax, offset adr_a
adr_adr_a, ax
ax, offset adr_adr_a
adr_adr_a, ax
bx, *** adr_adr_adr_a

pregtete mai nti variabilele pointer. Variabila pointer adr_a va conine adresa
operandului a. Variabila adr_adr_a va conine adresa variabilei pointer adr_a.
Variabila adr_adr_adr_a conine adresa variabilei pointer spre pointer spre variabila
a.
Ultima instruciune din secven are ca efect ncrcarea n registrul BX a
coninutului zonei de memorie (a) a crei adres se afl ntr-o zon de memorie
(adr_a), a crei adres la rndul ei se afl ntr-o zon de memorie (adr_adr_a), a
crei adres se afl n zona de memorie adr_adr_adr_a. Cele trei asteriscuri pun n
eviden c este vorba de o adresare indirect cu trei nivele de indirectare. Deci n
structura instruciunii, dac este adresare indirect, al localizarea operandului se va
specifica dac acesta este sau nu pointer, pentru a continua sau a ntrerupe procesul
de referire.
Adresarea indirect poate fi simpl, adresare indirect indexat i adresare
indirect bazat. Toate aceste mecanisme de indirectare pot fi implementate n
limbajele evoluate i cu setul de faciliti de evaluare a expresiilor de adres
existent acum la microprocesorul 80x86.
Expresiile de evaluare a adreselor pot fi dezvoltate mult n sensul
specificrii momentului n care intervin registrele index sau de baz. Astfel, se
poate proiecta un limbaj de asamblare n care expresia:
** alfa

bp

si

s fie interpretat astfel:


alfa variabil pointer spre pointer, conine adresa unei zone ce conine
la rndul ei adresa unei zone de memorie;
BP registrul de baz care conine adresa unei zone de memorie, zon
ce conine o deplasare relativ;
SI registrul de index, ce conine o deplasare fa de deplasarea relativ
identificat n zona de memorie localizat prin registrul BP.

442

Mai nti folosind variabila alfa (acum alfa nu este o deplasare) se gsete
variabila ce conine o adres. La aceast adres se adaug coninutul zonei de
memorie a crei adres s-a aflat n registrul BP, obinndu-se o nou adres. Este
adresa unei zone de memorie ce conine o adres (al doilea nivel de indirectare). La
aceast adres se adaug coninutul registrului index i rezult adresa operandului
cu care se va lucra de fapt.
Fiecare mod de adresare este nsoit de un numr de cicluri main.
Alegerea unui anumit mod este dictat de structurile de date cu care se opereaz.
Expresia de adres, ca sum de un numr de termeni fixat se particularizeaz
funcie de codul specificat pe biii 2, 1, 0 ai baitului MODRM (v. capitolul
Instruciuni).
Modurile de adresare trebuie privite ca algoritmi de calcul ai expresiilor de
adres. Operanzii sunt registre sau numere, n final se obin adrese ale unor zone de
memorie al cror coninut este ntrebuinat fie pentru a iniializa, fie pentru a
modifica (prin adunare, scdere, deplasare, interschimb, conversie) un alt operand,
registru.
Indiferent care este procesorul cu care se lucreaz, programatorul n
limbajul de asamblare va cunoate restriciile de utilizare registre i structurile
posibile ale expresiilor de adres. Folosirea adecvat a unui mod de adresare se
pune n vedere prin lungimea textului scris i prin mulimea de instruciuni ce pot fi
nlocuite dac s-ar folosi un alt mod de adresare, mod care s-ar dovedi mai eficient.

443

5
INDICATORII DE CONDIIE
5.1 Registrul FLAGS
Procesoarele din familia x86 dispun de o serie de indicatori de condiie.
Acetia reprezint informaii legate de starea procesorului i efectul execuiei
instruciunilor. Fiecare indicator de condiie ocup 1 bit n cadrul unui registru
special, registrul F. Pentru microprocesorul 8086, structura acestui registru este cea
din figura 5.1.

15 14 13 12 11 10 09 08 07 06 05 04 03 02 01
-- -- -- -- OF DF IF TF SF ZF -- AF -- PF --

00
CF

Figura 5.1 Registrul de indicatori de condiie al procesorului 8086.


Semnificaia indicatorilor de condiie este urmtoarea:
CF (Carry Flag, indicator de transport) semnific un transport sau un
mprumut n, respectiv din bitul cel mai semnificativ al rezultatului.
PF (Parity Flag, indicator de paritate) este poziionat dup cum biii din
cel mai puin semnificativ octet al rezultatului sunt n numr par
(poziionare pe 1) sau impar (poziionare pe 0).
AF (Adjust Flag, indicator de ajustare) este folosit n aritmetica
zecimal i semnific un transport sau un mprumut n, respectiv din
bitul 4 (cel mai semnificativ bit al jumtii celei mai puin
semnificative) al rezultatului.
ZF (Zero Flag, indicator de zero) indic dac rezultatul unei operaii a
fost sau nu zero.
SF (Sign Flag, indicator de semn) are aceeai valoare ca bitul cel mai
semnificativ al rezultatului (bitul de semn): 0 - pozitiv, 1 - negativ.
TF (Trap Flag, indicator de urmrire a execuiei) este folosit la
depanarea programelor prin execuia lor pas cu pas - dac este setat,
procesorul foreaz automat o excepie dup execuia fiecrei
instruciuni.

444

IF (Interrupt Flag, indicator de ntreruperi) precizeaz dac procesorul


ia n considerare sau nu ntreruperile externe.
DF (Direction Flag, indicator de direcie) precizeaz sensul (0 cresctor sau 1 - descresctor) n care este modificat contorul de adrese
la operaiile cu iruri.
OF (Overflow Flag, indicator de depire) semnific depirea
domeniului admisibil la reprezentarea rezultatului unei operaii
aritmetice cu sau fr semn. Practic, este poziionat pe 1 dac apare un
transport nspre bitul cel mai semnificativ al rezultatului din bitul vecin,
dar nu i din bitul cel mai semnificativ spre CF sau invers, dinspre bitul
cel mai semnificativ spre CF, dar nu i spre bitul cel mai semnificativ
din bitul vecin. Similar, la mprumut, este poziionat pe 1 dac apare un
transport de la bitul cel mai semnificativ la bitul vecin, dar nu i nspre
bitul cel mai semnificativ dinspre CF sau invers, dinspre CF spre
b.c.m.s., dar nu i dinspre bitul cel mai semnificativ spre bitul vecin.

Indicatorii CF, PF, AF, SF, ZF, TF i OF se mai numesc indicatori de stare;
DF este indicator de control, iar IF indicator de sistem.
Odat cu evoluia procesoarelor din gama x86, au fost introdui noi
indicatori. Astfel, la procesoarele 80386, registrul FLAGS este extins la 32 de bii,
formnd noul registru EFLAGS, a crui structur este reprezentat n figura 5.2.
<Registrul FLAGS pe 16 bii
->
31-18 17 16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
0
VM RF 0 NT IO PL OF DF IF TF SF ZF 0 AF 0 PF 1 CF

Figura 5.2 Registrul de indicatori de condiie al procesorului 80386


Noii indicatori au urmtoarele semnificaii:
IOPL (Input-Output Privilege Level, nivel de prioritate al operaiei de
intrare-ieire) indic nivelul de prioritate al operaiei de intrare-ieire.
NT (Nested Task, procese imbricate) este folosit pentru controlul
nlnuirii proceselor imbricate, influennd operaiile executate de
instruciunea IRET.
RF (Resume Flag, indicator de reluare) este folosit pentru a inhiba
temporar excepiile de depanare, permind reluarea execuiei unei
instruciuni fr a genera imediat o nou excepie.
VM (Virtual 8086 Mode, mod virtual 8086) indic execuia unui proces
n modul virtual 8086.
Toi indicatorii adugai sunt indicatori de sistem. Biii pe care apar valorile
0 sau 1 sunt rezervai de ctre productor i nu trebuiesc folosii.

445

Pentru relaia cu coprocesorul matematic exist de asemenea o alt serie de


indicatori, grupai n registrul de control CR0. Structura acestuia este reprezentat
n figura 5.3.
Semnificaia indicatorilor este urmtoarea:
PE (Protection Enabled, protecie activat) foreaz execuia
instruciunilor n mod real (0) sau protejat (1) de adresare.
MP (Math Present, coprocesor prezent) controleaz execuia
instruciunii WAIT, folosit pentru coordonarea coprocesorului
matematic.
EM (Emulation, emulare) indic dac trebuie sau nu emulat
coprocesorul matematic.
TS (Task Switch, schimbare de proces) este setat de procesor la fiecare
schimbare de proces i testat la interpretarea instruciunilor pentru
coprocesor.
ET (Extension Type, tip coprocesor) indic tipul de coprocesor prezent
n sistem (80287 sau 80387).
PG (PaGing, paginare) indic faptul c procesorul folosete tabele de
pagini pentru translatarea adreselor liniare n adrese fizice.

31
PG

30-05
--

04
ET

03
TS

02
EM

01
MP

00
PE

Figura 5.3 Registrul de control CR0.


Acest registru este accesibil pentru citire i modificare doar prin intermediul
instruciunii MOV, deci prin transferul coninutului su ntr-un sau dintr-un registru
de uz general.
5.2 Operaii cu indicatorii de condiie
Programatorii folosesc mai multe categorii de operaii cu indicatorii de
condiie:
operaii de setare / resetare a unor indicatori naintea unor instruciuni
cu scopul de a afecta modul de execuie a acestora.
operaii de setare / resetare a indicatorului CF naintea unor instruciuni
de rotaie, adunare cu transport sau scdere cu mprumut, pentru a
obine anumite rezultate.
operaii de evaluare a strii unor indicatori pentru a trage concluzii
asupra rezultatelor instruciunilor anterioare.
operaii de salvare / restaurare a registrului de indicatori, cu scopul
conservrii / modificrii strii reflectate de indicatori.

446

Instruciunile de control al indicatorilor sunt urmtoarele:


STC (SeT Carry flag, seteaz indicatorul de transport) are ca efect CF=1.
CLC (CLear Carry flag, reseteaz indicatorul de transport) are ca efect
CF=0.
CMC (CoMplement Carry flag, complementeaz indicatorul de transport)
are ca efect CF= NOT CF.
STD (SeT Direction flag, seteaz indicatorul de direcie) are ca efect DF=1
(contorul de adrese va fi decrementat n operaiile cu iruri).
CLD (CLear Direction flag, reseteaz indicatorul de direcie) are ca efect
DF=0 (contorul de adrese va fi incrementat n operaiile cu iruri).
STI (SeT Interrupt flag, seteaz indicatorul de ntreruperi) are ca efect
IF=1.
CLI (CLear Interrupt flag, reseteaz indicatorul de ntreruperi) are ca efect
IF=0.
LAHF (Load AH from Flags, ncarc AH din registrul de indicatori) are ca
efect transferul indicatorilor SF, ZF, AF, PF, CF n biii 7,6,4,2, respectiv 0 ai
registrului AH.
SAHF (Store AH into Flags, ncarc registrul de indicatori din AH) are ca
efect transferul biilor 7,6,4,2 i 0 ai registrului AH n indicatorii SF, ZF, AF, PF,
respectiv CF.
PUSHF i POPF stocheaz, respectiv refac registrul de indicatori n,
respectiv din vrful stivei. Aceste dou operaii sunt folosite att pentru
conservarea strii procesorului prin salvare, ct i pentru examinarea acesteia.
Variantele PUSHFD i POPFD lucreaz pe 32 de bii, dar nu afecteaz indicatorii
RF i VM, aflai n cuvntul mai semnificativ al registrului extins de indicatori.
5.3 Poziionarea indicatorilor de condiie la execuie
Pentru lucrul individual cu ceilali indicatori nu exist instruciuni specifice.
Rezultatele dorite se pot obine ns prin executarea unor secvene de operaii.
De exemplu, dac se dorete setarea indicatorului ZF, se execut o operaie
care s produc un rezultat nul i s nu afecteze regitrii cu care se lucreaz n acel
moment, ca de exemplu XOR CL,CL.
5.4 Interaciunea indicatori de condiie - instruciuni
Pentru o programare corect i o folosire eficient a efectelor interaciunii
indicatori de condiie - instruciuni este necesar cunoaterea efectelor pe care le au
unele asupra celorlalte.

447

Astfel, indicatorii de sistem au efect asupra modului de execuie a


instruciunilor, iar indicatorii de stare influeneaz operaiile matematice i salturile
i apelurile condiionate.
Interaciunea indicatori de stare - instruciuni este prezentat n tabelul 5.1.

Indicatorul
Instruciunea
AAA
AAS
AAD
AAM
DAA
DAS
ADC
ADD
SBB
SUB
CMP
CMPS
SCAS
NEG
DEC
INC
IMUL
MUL
RCL/RCR 1
RCL/RCR cont
ROL/ROR 1
ROL/ROR cont
SAL/SAR/SHL/SH
SAL/SAR/SHL/SH
SHLD/SHRD
BSF/BSR
BT/BTS/BTR/BTC
AND
OR
TEST
XOR

OF

SF ZF

------M
M
M
M
M
M
M
M
M
M
M
M
M
-M
-M
----0
0
0
0

--M
M
M
M
M
M
M
M
M
M
M
M
M
M
---

--M
M
M
M
M
M
M
M
M
M
M
M
M
M
---

M
M
M
--M
M
M
M

M
M
M
M
-M
M
M
M

Semnificaia simbolurilor este urmtoarea:


M - instruciunea modific indicatorul.

Tabelul 5.1
AF P CF
F
TM -- M
TM -- M
-- M --- M -TM M TM
TM M TM
M M TM
M M M
M M TM
M M M
M M M
M M M
M M M
M M M
M M
M M
-- -- M
-- -- M
TM
TM
M
M
-- M M
-- M M
-- M M
-- -- --- -- M
-- M 0
-- M 0
-- M 0
-- M 0

448

T - instruciunea testeaz indicatorul.


-- - efectul instruciunii asupra indicatorului este nedefinit.
0 - instruciunea reseteaz indicatorul.
Spaiu - instruciunea nu afecteaz indicatorul.
Pentru o list complet, care include att indicatorii de sistem, ct i alte
instruciuni dect cele aritmetice, de rotire i salt, se poate consulta tabelul 5.2.
Tabelul 5.2
Indicatorul
Instruciunea
AAA
AAD
AAM
AAS
ADC
ADD
AND
ARPL
BOUND
BSF/BSR
BT/BTS/BTR/
BTC
CALL
CBW
CLC
CLD
CLI
CLTS
CMC
CMP
CMPS
CWD
DAA
DAS
DEC
DIV
ENTER
ESC
HLT
IDIV
IMUL
IN
INC

OF SF ZF

AF

PF CF

----M
M
0

-M
M
-M
M
M

-M
M
-M
M
M
M

TM
--TM
M
M
--

-M
M
-M
M
M

M
--M
TM
M
0

---

---

M
--

---

---

-M

TF IF DF NT RF

0
0
0
M
M
M

M
M

M
M

M
M

M
M

M
M

--M
--

M
M
M
--

M
M
M
--

TM
TM
M
--

M
M
M
--

TM
TM

-M

---

---

---

---

-M

--

449
INS
INT
INTO

T
0
0

Indicatorul
OF SF ZF
Instruciunea
IRET
R
R R
Jcond
T
T
T
JCXZ
JMP
LAHF
LAR
M
LDS/LES/LSS/
LFS/LGS
LEA
LEAVE
LGDT/LIDT/LL
DT/LMSW
LOCK
LODS
LOOP
LOOPE/LOOP
T
NE
LSL
M
LTR
MOV
MOV control,
---debug
MOVS
MOVSX/MOV
ZX
MUL
NEG
NOP
NOT
OR
OUT
OUTS
POP/POPA
POPF
PUSH/PUSHA
/PUSHF
RCL/RCR 1
RCL/RCR
count
REP/REPE/R
EPNE
RET
ROL/ROR 1
ROL/ROR
count
SAHF

0
0

AF

PF CF

TF IF DF NT RF

R
T

R
T

--

--

-T

M
M

-M

-M

-M

-M

M
M

--

0
T

M
--

TM
TM

M
--

M
M
R

450
SAL/SAR/SHL
/SHR
1
SAL/SAR/SHL
/SHR count
SBB
SCAS
Indicatorul
Instruciunea
SET cond
SGDT/SIDT/S
LDT/SMSW
SHLD/SHRD
STC
STD
STI
STOS
STR
SUB
TEST
VERR/VERR
W
WAIT
XCHG
XLAT
XOR

M
-M
M

M
M
M
M

M
M
M
M

--M
M

M
M
M
M

OF SF ZF

AF

PF CF

--

--

M
M
TM
M

M
1

T
TF IF DF NT RF

1
1
T
M
0

M
M

M
M
M

M
--

M
M

M
0

--

Semnificaia simbolurilor este urmtoarea:


M - instruciunea modific indicatorul.
T - instruciunea testeaz indicatorul.
R - instruciunea reface valoarea anterioar a indicatorului.
-- - efectul instruciunii asupra indicatorului este nedefinit.
0 - instruciunea reseteaz indicatorul.
1 - instruciunea seteaz indicatorul.
Spaiu - instruciunea nu afecteaz indicatorul.
La execuia instruciunilor de salt condiionat se evalueaz expresii
relaionale logice ce conin indicatorii ca operanzi. Dac rezultatul evalurii este 0
nu se execut saltul, iar dac este 1 se execut saltul.

451

6
INSTRUCIUNI
6.1 Clasificarea instruciunilor
Exist numeroase criterii de clasificare a instruciunilor, care nu se exclud.
Aceeai instruciune este identificat ca aparinnd unei grupe cel puin din fiecare
mprire a oricrui criteriu.
Dup numrul operanzilor instruciunile limbajului de asamblare se
grupeaz n:
instruciuni fr operanzi;
instruciuni cu un operand;
instruciuni cu doi operanzi;
instruciuni cu mai muli operanzi.
n mod uzual, instruciunile sunt proiectate cu un numr redus de operanzi,
ntruct creterea numrului de operanzi atrage mrirea gradului de complexitate al
instruciunii. n limbajul de asamblare o instruciune execut o operaie elementar,
cu nivel de complexitate redus.
Natura operanzilor grupeaz instruciunile n:
instruciuni de tip R-R, operanzii sunt registre;
instruciuni de tip R-M, un operand este registru, destinaia, iar
operandul surs, este n memorie;
instruciuni de tip M-R, operandul destinaie se afl n memorie,
operandul surs este un registru;
instruciuni de tip R-I, operandul surs este o constant imediat, iar
operandul destinaie este registru;
instruciuni de tip M-I, sursa este constant imediat, iar destinaia este
zon de memorie;
instruciuni de tip M-M, operanzii se afl n memorie.
Limbajele de asamblare se proiecteaz cu structuri de instruciuni care s
gestioneze numai o zon de memorie, deci instruciunile de tip M-M sunt rar
ntlnite sau excluse.
Lungimea zonei de memorie ocupat clasific instruciunile astfel:
instruciuni pe un bait, n care operanzii au poziie fixat, efectul este
unic;
instruciuni definite pe doi baii, de regul au ca operanzi registre;

452

instruciuni cu trei baii, n care un operand este un registru, iar cellalt


poate fi definit ca valoare sau ca deplasare pe un bait;
instruciuni pe patru baii, un operand este un registru, iar cellalt este
definit ca valoare sau deplasare pe doi baii.
Se pot defini instruciuni i pe un numr superior de baii, de fiecare dat
alocarea fiind determinat de natura operanzilor din expresiile de evaluare a
adreselor sursei / destinaiei.
n raport cu modul n care sunt prelucrate de ctre asamblor,
instruciunile sunt:
instruciuni executabile, crora asamblorul le dezvolt un cod pe unul,
doi, sau mai muli baii, la execuia programului efectueaz transformri
de coninut asupra registrelor sau zonelor de memorie, selecteaz alte
instruciuni sau testeaz indicatorii de condiie;
instruciuni neexecutabile sau directive destinate alocrii de memorie,
definirii de constante, gestionrii contorului de locaii, delimitrii de
segmente, de proceduri, de macrodefiniii, punerii n corespondena a
constantelor cu nume simbolice, a registrelor cu numele de segment,
stabilete tipul unei etichete, alinieri pentru adrese.
Instruciunile executabile sunt foarte diverse, puterea limbajului de
asamblare fiind asigurat de ortogonalitatea lor. Instruciunile neexecutabile
contribuie la implementarea tuturor structurilor de date, la realizarea tuturor
combinaiilor de structuri de programe i la gestionarea riguroas a resurselor
(registre i memorie).
Instruciunile executabile se clasific dup tipul operaiei n:
instruciuni de transfer de date sau adrese numite surse, spre registre sau
zone de memorie, numite destinaie;
instruciuni aritmetice, pentru adunri, nmuliri, scderi, mpriri i
pentru ajustri;
instruciuni de manipulare la nivel de bii, efectueaz deplasri, rotiri,
operaii logice pe bii;
instruciuni de manipulare a irurilor de caractere efectueaz copierea a
dou zone de memorie, compararea de iruri, ncrcare i memorare de
caractere sau cuvinte cu sau fr testare;
instruciuni de control destinate apelului i revenirii din procedur,
salturi condiionate i salt necondiionat, repetri secven sub controlul
unui registru;
instruciuni de poziionare a indicatorilor de condiie.
Dup numrul ciclurilor main instruciunile se grupeaz n:
instruciuni cu numr fix de cicluri main din care fac parte
instruciunile n care operanzii fie lipsesc, fie sunt numai registre;

453

instruciuni cu numr variabil de cicluri main; pentru fiecare


instruciune este dat numrul de cicluri specific la care se adaug
ciclurile necesare evalurii i localizrii adresei operandului.

6.2 Descrierea instruciunilor


Programatorul trebuie s cunoasc exact semnificaia instruciunilor pe care
le utilizeaz i mai ales efectele secundare, concretizate prin poziionarea
indicatorilor de condiie. Prezentarea instruciunilor prin intermediul unui limbaj de
programare evoluat are avantajul ordonrii clare a operaiilor elementare n
totalitatea lor.
De exemplu, instruciunea SAL (Shift Arithmetic Left) este descris cu
instruciunile limbajului C astfel:
temp=CONTOR;
while(temp){
CF=High_Bit(Operand);
Operand*=2;
temp--;
if(CONTOR= =1)
if(High_Bit(Operand)!=CF)
OF=1;
else
OF=0;
else
OF=CF;
}

unde:
- variabil de lucru;
- indic numrul de poziii cu care se face deplasarea spre
stnga; pentru valori diferite de 1, stocarea se va efectua n
registrul CL;
CF, OF
- indicatori de condiie;
High_Bit
- funcie care returneaz valoarea bitului cel mai
semnificativ al operandului.
Aceast instruciune are efectul nmulirii operandului cu 2 la puterea
CONTOR.
Reprezentarea sub form grafic a mecanismului unei instruciuni este
sugestiv, avnd ns pierderi de informaii de detaliu asupra modului n care
decurge realizarea operaiei. Pentru instruciunea
temp
CONTOR

shl operand, contor

n care Operand este registrul AL, reprezentarea grafic este dat n figura 6.1.

454

7
C
CF

AL
Figura 6.1. Deplasare spre stnga

Dac registrul CL asociat variabilei CONTOR conform restriciilor de


implementare ale instruciunii conine valoarea 3, dup efectuarea deplasrii spre
stnga, registrul AL va conine 01001000.
Reprezentarea tabelar a instruciunilor ia n considerare variantele ce pot fi
utilizate de programator i numrul de cicluri necesar. O prezentare generalizat
ine seama i de tipul de microprocesor utilizat, pentru c diferenele pentru fiecare
se impun a fi specificate.
Astfel, pentru instruciunea SHL se va alctui tabelul 6.1.

Mod adresare Exemplu


Reg,1
Mem,1
Reg,CL
Mem,CL
Reg,imediat8
Mem,imediat8

SHL bx,1
SHL alfa,1
SHL ax,cl
SHL alfa,cl
SHL bx,5
SHL alfa,5

Tabelul 6.1.
Numr cicluri main
286
386
486
2
3
3
7
7
4
5+n
3
3
8+n
7
4
5+n
3
2
8+n
7
4

n tabelul 6.1. s-au utilizat notaii cu semnificaiile:


Reg - registru de lucru;
Mem - variabil definit n memorie;
CL
- registrul CL;
N
- numrul de poziii cu care se face deplasarea.
Pentru descrierea instruciunilor se construiesc limbaje care s aib
capacitatea de a reda exact semnificaia operaiei asociate fiecrui mnemonic.
Un registru este format din biii b0, b1, b2, , b15. Instruciunea de deplasare
shl bx,1 este descris folosind ecuaii recurente astfel:
CF=b15
bi+1=bi
b0=0
pentru i=0, 1, 2, , 14.
Dac apar unele condiionri i neregulariti de comportament pe mulimea
biilor sau se lucreaz cu anumite grupuri de bii, prezentarea devine mai dificil de
urmrit. n plus, pentru a marca deosebirea biilor dintr-un registru de biii dintr-o

455

zon de memorie se vor face notaii adecvate. Restriciile noului limbaj, de cele
mai multe ori nu se regsesc n descrierile altor limbaje de asamblare pentru a
uura nvarea sau compararea lor.
Se va putea vorbi de o descriere bun a instruciunilor dac:
este prezentat mnemonica i semnificaia fiecrei litere;
printr-un text se specific operaia pe care o execut fiecare instruciune;
se detaliaz fiecare form de adresare a operanzilor admis i se
exemplific efectele pe care execuia instruciunilor le are asupra
operanzilor;
se specific numrul de cicluri main necesare execuiei fiecrei
variante de definire a expresiei de adresare a operanzilor;
se dau reprezentrile la nivel de bit ale dispunerii informaiilor din linia
surs, dup asamblare;
se precizeaz poziionarea indicatorilor de condiie.
Manualele care descriu limbaje de asamblare mbin toate modurile de
prezentare pentru a asigura att rigurozitate, ct i de a face limbajul de asamblare
mai atractiv, mai uor de nvat i de a utiliza ct mai potrivit instruciunile.
6.3 Forma extern a instruciunilor
Programul scris n limbaj de asamblare este format dintr-o succesiune de
instruciuni. Ceea ce scrie programatorul sunt forme concrete de prezentare a
instruciunilor sau forme externe.
O linie surs conine:
eticheta instruciunii (opional);
codul operaiei;
lista de operanzi;
comentariu (opional).
Regulile de construire a etichetelor sunt comune i pentru identificatori.
Lungimea cuvntului asociat etichetei este strict legat de dorina programatorului
de a da lizibilitate programului.
Dac se construiesc etichete cu o destinaie special, reutilizate ntr-un
context anume, este folosit caracterul blanc subliniat (underscore). Astfel,
construciile __alfa__ , _beta, gama _ sunt etichete din categoria menionat. n
programe se ntlnesc variabile globale definite n fiierele unor produse program
de larg circulaie, n expresii de adres.
n mod curent se definesc etichete precum: ciclu, start, final, adun, alege.
Pentru a mri lizibilitatea se fac concatenri de nume i delimitarea este obinut
prin utilizarea de litere mari. Astfel, etichetele AlegeMaxim, PretUnitar,
ExtrageBait, SirCifric, utilizate corespunztor mpreun cu comentariile de pe
fiecare linie ajut programatorul la depanarea sau la dezvoltarea programului.

456

Codul operaiei este de fapt o mnemonic. Programatorul care a lucrat ntrun limbaj de asamblare va observa c exist diferene minore la alctuirea
mnemonicelor. De aceea, cunoscnd un vocabular al operaiilor fundamentale,
generarea de mnemonice devine un proces natural.
n tabelul 6.2 sunt prezentate cteva din mnemonicele utilizate n timp
pentru operaiile cele mai frecvente din programe.
Tabelul 6.2.
Operaia
Addition
Move
Jump
Compare
Shift
Increment

Mnemonicele limbajelor
ASSEMBLERASSIRIS
IBM
A,AR,AD
AD4,AD8
MVC,MVI MVZ MVSR,MVSL
B
BRU
C,CD,CDR,CE
CP4,CP2
SLA,SRA
SLAx,SRAx
IC2,IC4

MACRO11
ADD
MOV
BR
CMP
ASL,ASR
INC

ASM
ADD
MOV
JMP
CMP
SAL,SAR
INC

Construirea mnemonicelor fr a include lungimi ale zonelor de memorie


deplaseaz informaiile spre cei doi operanzi; operandul cu lungimea cea mai mic
dac este receptor impune lungimea sursei. Dac operandul surs are o lungime
mai mic se va produce o preluare din zone nvecinate, cu alterarea rezultatelor. n
cazul limbajelor cu o diversitate restrns de tipuri de operanzi mnemonicele nu
conin date despre lungimile operanzilor.
Lista de operanzi este de fapt o list de expresii cu care se refer operanzii.
Faptul c registrele generale au asociate numele AX, BX, CX, DX sau AH, AL,
BH, BL, CH, CL nseamn c adrese anumite sunt puse n coresponden cu aceste
nume. i n cazul referirii registrelor este vorba de a evalua o expresie - expresia cu
un singur termen, numele asociat registrului.
Complexitatea expresiilor de evaluat pentru a obine adresa unui operand
difer n funcie de multitudinea i diversitatea operatorilor care pot fi utilizai.
Indiferent care este nivelul de complexitate al expresiilor, condiia impus este ca
evaluarea s se efectueze n procesul de asamblare. Toi operanzii trebuie s fie
complet definii ca valori atunci cnd intervin ntr-o expresie din lista de operanzi.
i generaiile mai vechi de limbaje de asamblare permiteau construirea de
expresii n care apreau operatorii aritmetici +, -, *, /, MOD (pentru obinerea
restului mpririi a doi termeni). Astfel, dac se definete secvena:
a
b
c

se va instruciunea:

equ
equ
equ

15
a + 4*6
a + b

457
mov

ax, 2*b+c+a mod 4

care este echivalent cu:


mov

ax, 135

pentru c lui B i se asociaz 15+24=39, lui C i se asociaz 54, iar A MOD 4


nseamn rest 3; 2*39+54+3=135.
Dac n expresii apar operatori care lucreaz cu iruri de bii, precum OR,
AND, XOR, NOT (OR sau logic, AND i logic, XOR sau exclusiv, NOT
complement fa de unu) expresiile cresc n complexitate. Astfel instruciunea:
add

ax, not 10011b and 10101b or 11000b

este echivalent cu instruciunea:


add

ax, 11100b

pentru c NOT 10011b este egal cu 01100b, 01100b AND 10101b este egal cu
00100b, iar 00100b OR 11000b este egal cu 11100b.
La introducerea operatorilor relaionali este important s se cunoasc
valorile numerice cu care sunt puse n coresponden valoarea logic adevrat i,
respectiv, valoarea logic fals. n cazul asamblorului pentru limbaj ASM
adevrat nseamn (-1), iar fals nseamn (0). Operatorii relaionali sunt: GT (mai
mare ca), GE (mai mare sau egal), EQ (egal cu), NE (neegal), LT (mai mic dect),
LE (mai mic sau egal).
Instruciunea:
mov

bx,(7 gt 5)and(8 le 3)

are ca efect ncrcarea n registrul BX a valorii zero pentru c la evaluare, 7 GT 5


nseamn adevrat, adic (-1), 8 LE 3 nseamn fals, adic 0. Operatorul logic
AND pe bii cnd un termen este cu toi biii zero conduce la obinerea unui ir de
aisprezece zerouri n registrul BX.
Operatorul TYPE aplicat unei variabile returneaz un numr care indic
lungimea ca numr de baii ai unui element care alctuiete variabila respectiv.
Dac se consider definiiile:
a
b
str
x
y

db
dw
struc
dw
db

?
l0 dup (0)
?
8 dup (?)

458
str
alfa

ends
str 20 dup (<>)

aplicnd operatorul TYPE unora dintre ele n secvena:


mov al, type a
; al =1 (db este 1 bait)
mov bl, type b
; bl =2 (dw are 2 baii)
mov cl, type alfa ; cl =10 (x are 2 baii, y are 8)

Operatorul SIZE returneaz lungimea zonei de memorie ocupat de o


variabil n totalitate.
Dac se consider definirea:
st
xx
yy
zz
st
mat

struc
db
dw
dt
ends
st 10

?
?
?

; lungime 1
; lungime 2
; lungime 10

dup (5 dup (<>))

aplicnd operatorii TYPE, SIZE i LENGTH (acest operator returneaz numrul de


componente care alctuiesc masivul), n secvena:
mov
mov
mov

ax, type
bx, length
cx, size

mat ; ax=1+2+10
mat ; bx=50 (10*5 componente)
mat ; cx=50*13 baii rezervai.

Aceti operatori permit o cretere a capacitii de mentenan a textului la


modificrile de structur ale datelor, tiut fiind faptul c n multe situaii trebuie
contorizate elementele i trebuie traversate zone de memorie ale cror lungimi
rezult din calcul. Dac se cunoate adresa de nceput i lungimea zonei poate fi
calculat adresa ultimului bait, pentru a face traversarea de la acesta ctre primul
bait, mod de lucru des ntrebuinat.
Operatorii HIGH i LOW returneaz baitul cel mai semnificativ, respectiv,
baitul cel mai puin semnificativ al unei date cu un tip specificat.
Din secvena:
numr

mov
mov
mov

dd

12345678h

ax, word high numr


bx, word low numr
al, byte high word low numr

; ax=1234
; bx=5678
; al=56

se observ capacitatea de a selecta pri dintr-un ntreg, specificate cu atributele


BYTE i WORD, ce corespund tipurilor fundamentale de date ale limbajului de
asamblare, alturi de DWORD, QWORD, TBYTE. Cnd se definete o variabil se

459

specific numele, tipul i eventual valoarea cu care este iniializat zona de


memorie.
n secvena:
a
b
c
d
x
c
w

dw
7
db
abcd
struc
db
?
dd
11 dup (?)
ends
c
10 dup ()

a este o variabil de tip cuvnt, b este variabil de tip bait, w este variabil de tip c.
Utilizarea numelui unei variabile nseamn asocierea cu ntreaga zon de memorie
alocat, 2 baii pentru variabila a, 1*4 baii pentru variabila b i 450 baii pentru
variabila w. Totui, orice variabil chiar dac are un tip, este privit ca zon de
memorie. Exist posibilitatea de a face conversii de tip aa fel nct variabila a
definit iniial ca un cuvnt s poat fi tratat ca un ir de 2 baii aa cum este
variabila b. Tot astfel se pune problema de a face o conversie ca variabila w s fie
privit fie ca un ir de cuvinte, fie ca un ir de baii. Conversia de tip presupune
utilizarea operatorului PTR ntr-o construcie de forma:
expresie_1

ptr

expresie_2

care realizeaz conversia de la tipul dat dup evaluarea expresiei-2 la tipul cerut de
expresia-1.
Dac se consider definirea:
aa

dd

12345678h

secvena:
mov
and
and

al, byte ptr aa


;al:=78h
byte ptr [si], 0fah
;operaie pe 8 bii
byte ptr aa, 0aah ;operaie 8 bii, deplasare 16 bii

pune n eviden c dei variabila aa este definit dublu cuvnt se exploreaz din ea
numai un bait, presupunnd c registrul SI conine deplasamentul lui aa.
Operatorii SEG i OFFSET returneaz adresa de nceput a segmentului
unde se afl operandul, respectiv, deplasarea pe care o are operandul fa de
nceputul segmentului.
Dac o variabil xx este definit n segmentul de date SEGDAT,
iniializarea registrului de segment DS se efectueaz prin:

460
mov ax, seg xx
mov ds, ax

n cadrul expresiilor apar operatorii (, ), [, ] i operatorul punct, utilizat


pentru referirea membrilor unor structuri de date de tip articol. Secvena:
add ax, (5+3)*(7-2)
mov bx, [bx+si+4*5]
mov

cx, xxx.alfa

;parantezele modific prioritile


;ca n algebr
;[, ] se folosesc pentru evaluare
;i extragere coninut
;alfa e membru n structura xxx

exemplific utilizarea acestor operatori.


n tabelul 6.3. este prezentat mulimea operatorilor, grupai pe prioriti.

Prioriti
1
2
3
4
5
6
7
8
9
10
11
12
13

Tabelul 6.3.
Operatori
() [] LENGTH, MASK, WIDTH
. (operatorul de referire membri din structuri)
HIGH, LOW
+,- (operatori unari)
: (specificare segment:offset)
OFFSET, PTR, SEG, THIS, TYPE
*, /, MOD, SHL, SHR
+,- (operatori binari)
EQ, NE, GT, GE, LT, LE
NOT
AND
OR, XOR
LARGE, SHORT, SMALL

Unii dintre operatori sunt prezentai n capitolele urmtoare pe msur ce


sunt definite tipuri de date i directive care impun evaluri de expresii cu
includerea lor.
Se observ c asamblorul este un program extrem de complex din moment
ce permite evaluarea unor expresii de complexitate ridicat, mulimea operatorilor
fiind comparabil cu operatorii din limbajul C. Comentariile, ultimul element al
liniei surs, sunt opionale. Scrierea de comentarii va uura munca de dezvoltare a
programului, oferind programatorului explicaii la sensul operaiilor, o formul sau
o valoare care are o semnificaie particular pentru program.

461

6.4 Forma intern a instruciunilor


Asamblorul evalueaz expresiile n msura n care acest lucru este posibil,
identific operandul registru sau operandul imediat, stabilete codul operaiei. n
final toate elementele formei externe a instruciunii se vor codifica. Rezult un
numr de baii ocupai cu configuraii care la execuia programului se interpreteaz
i determin prelucrrile dorite de programator.
Codul operaiei i unele informaii n continuare vor indica numrul de baii
din care este alctuit codificarea instruciunii. Structura intern a instruciunii
conine informaii privind:
codul operaiei;
modul de adresare;
registrele utilizate i semnificaia lor;
lungimea n baii a descrierii operandului memorie;
rolul pe care l are registrul (surs sau destinaie);
lungimile operanzilor;
sensul de efectuare a traversrii.
n cazul unor limbaje de asamblare n care mnemonica definete tipul
operanzilor, lungimea, deci numrul de mnemonice este ridicat, codul asociat
mnemonicelor ocup un bait. Limbajele de asamblare de acest tip vehiculeaz cel
mult 256 de instruciuni diferite. Se creeaz n acest fel premisa structurii fixe a
poziiei cmpurilor din instruciune, ceea ce nseamn pe de o parte un mod simplu
de codificare i pe de alt parte risip de memorie. Se va prezenta n continuare
concepia limbajului de asamblare n care dispunerea informaiilor se face din
aproape n aproape i cmpurile se intercondiioneaz. Grupele de instruciuni se
difereniaz dup primele patru poziii ale codului operaiei.
Dac se construiete un tabel al frecvenelor de utilizare pentru instruciuni,
este posibil atribuirea unor coduri care sunt mai deosebite pentru instruciunile cu
frecvenele cele mai mari. Este posibil construirea unui tabel cu 16 linii i 16
coloane ce corespund combinaiilor biilor cei mai semnificativi din baitul codului
de operaie, respectiv, biilor mai puin semnificativi. Dispunnd pe liniile matricei
n continuare, codurile instruciunilor n ordinea descresctoare a frecvenelor de
utilizare mnemonice, se va obine o structur avantajoas i pentru constructorul de
asambloare eficiente.
Tabelul 6.4. prezint o dispunere a mnemonicelor, aa cum rezult din
codurile deja atribuite de designerul limbajului de asamblare, perfectibil dup
analiza statistic a unui lot reprezentativ de programe.

462

Instruciune

Tabelul 6.4.
Numrul de apariii

mov
pop
cmp
push
sub
ret
add
jmp
call
lea
xor

567
152
89
77
32
28
20
14
6
6
4

Structura intern a instruciunilor limbajului de asamblare variaz funcie de


modul de adresare, de numrul de operanzi i de natura operanzilor.
Instruciunile care se reprezint pe un bait i nu au operanzi sunt destinate
poziionrii pe zero sau pe unu a indicatorilor de condiie (CLC, STC, CLI, STI, CLD,
STD, CMC), controleaz execuia programului (HLT, NOP, WAIT). Cei 8 bii pe care
este reprezentat o astfel de instruciune sunt interpretai cod operaie, astfel:
bit

7
c

6
c

5
c

4
c

3
c

2
c

1
c

0
c

Figura 6.2 Forma intern a instruciunilor pe un bait fr operanzi


unde c reprezint o cifr binar 0 sau 1 care intr n componena codului
instruciunii.
Dac instruciunea admite o construcie de forma:
mnemonica

registru

ca de exemplu, instruciunile din secvena:


push
dec
inc

ax
cx
dx

fiind vorba, deci de instruciuni cu un singur operand i acesta fiind


registru, dispunerea informaiei pe un bait va conduce la structura intern de
instruciune din figura 6.3, unde c reprezint cifre binare asociate codului operaiei,
iar r reprezint cifre binare asociate codurilor registrelor generale. Codurile
asociate registrelor generale sunt date n tabelul 6.5.

463

bit

7
c

6
c

5
c

4
c

3
c

2
r

1
r

0
r

Figura 6.3 Forma intern a instruciunilor pe un bait cu un operand


Tabelul 6.5.
Registrul
Operaie pe cuvnt
Operaie pe bait
AX
AL
CX
CL
DX
DL
BX
BL
SP
AH
BP
CH
SI
DH
DI
BH

Cod
000
001
010
011
100
101
110
111

Pentru incrementare de exemplu, codul instruciunii INC (operaie pe


cuvnt) este 01000 dac operandul va fi de tip registru. Instruciunea:
inc si

se va codifica astfel:
bit

7
0
c

6
1
C

5
0
c

4
0
c

3
0
c

2
1
r

1
1
r

0
0
r

Figura 6.4 Forma intern a instruciunii inc si


Codificarea afiat de asamblor va fi 46h.
Exist unele limitri la folosirea operanzilor, n sensul fixrii acestora. De
exemplu, instruciunea de conversie de la un bait la cuvnt, CBW, presupune ca
baitul s fie memorat n registrul AL, iar rezultatul conversiei se va gsi n registrul
AX.
Instruciunile PUSHA, PUSHF, POPA, POPF se prezint pe un bait pentru c
operanzii lor sunt prefixai, toate registrele (PUSHA, POPA), respectiv, biii
indicatorilor de condiie (PUSHF, POPF).
Instruciunile de lucru cu iruri de caractere se reprezint de asemenea, pe
un bait pentru c adresele zonelor de memorie sunt stocate n registrele DS, SI
(zona de memorie destinaie) i registrul CX va conine lungimea zonei surs. Dei

464

execut operaii complexe, instruciuni ca LODSB, LODSW, STOSB, STOSW,


SCASB, SCASW, CMPSB, CMPSW, MOVSB, MOVSW, pentru c lucreaz cu iruri de
caractere, avnd registre prefixate pentru adrese, operanzi, asamblorul le codific
pe un bait.
Instruciunile de tip R-R, R-I, R-M, M-R, M-I presupun informaii privind
lucrul la nivel de bait sau la nivel de cuvnt. Bitul 0 din primul bait al instruciunii
codificat w, dac are valoarea 0 nseamn c operanzii sunt pe un bait, iar dac are
valoarea 1, operanzii sunt pe cuvnt.
Registrul operand poate fi surs (d=0) sau destinaie (d=1), unde cu d a fost
notat bitul unu din primul bait al instruciunii. Celelalte informaii necesit nc un
bait, numit MODRM de programatori datorit coninutului su. Dac operanzii
sunt de tip imediat sau sunt n memorie i se definesc cu deplasare, urmeaz la
codificarea instruciunii al treilea bait (d=0) sau al treilea i al patrulea (d=1).
Baitul codului de instruciune se structureaz pentru instruciunile cu doi
operanzi astfel:
bit

7
c

6
c

5
c

4
c

3
c

2
c

1
d

0
w

Figura 6.5 Forma intern a primului bait al instruciunilor pe doi baii


bit

7
m

6
m

5
R

4
R

3
R

1
r/m

Figura 6.6 Forma intern a baitului al doilea al instruciunilor pe doi baii


Al doilea bait asociat unei instruciuni dup asamblare are structura dat n
figura 6.6, unde:
m reprezint biii 7,6 asociai modului n care sunt interpretai biii 2, 1, 0
i cum este definit deplasarea operandului fa de nceputul
segmentului (pe un bait sau pe doi baii), tabelul 6.6;
R ocup biii 5 ,4 , 3 i indic registrul operand;
r/m stabilete formula de calcul a adresei operandului aflat n memorie.

465

Tabelul 6.6.
Biii 7, 6
Mm
00
01
10
11

Lipsete din instruciune


Este definit pe un bait
Este definit pe doi baii
Biii 2, 1, 0 se interpreteaz drept cod registru

Biii 2, 1, 0
000
001
010
011
100
101
110
111

Tabelul 6.7.
Formula de calcul a adresei
+
SI
+
deplasare
+
DI
+
deplasare
+
SI
+
deplasare
+
DI
+
deplasare
SI
+
deplasare
DI
+
deplasare
BP
+
deplasare
BX
+
deplasare

Deplasarea

BX
BX
BP
BP

Deplasarea intr n calcule pe 16 bii. Dac biii mm au valoarea 01 are loc


extensia pe 16 bii prin propagarea bitului de semn. Dac biii mm sunt 00 i biii
r/m sunt 110 deplasarea este pe 16 bii, deci nu lipsete.
Instruciunea:
mov dl, bx[si]

se codific prin:
ba10h
Cei doi baii se interpreteaz astfel:
7 6 5 4 3 2 1 0
c c c c c c d w
1 0 1 1 1 0 1 0

7 6 5 4 3 2 1 0
m m R R R
r/m
0 0 0 1 0 0 0 0

unde:

biii notai cccccc (101110) reprezint codul operaiei MOV registru,


memorie (R - M);
bitul de direcie (d=1) arat c registrul este destinaie;
bitul tipului de operand (w=0) arat c operandul este un bait;

466

biii mm prin codul 00 arat c deplasarea lipsete din instruciune;


biii RRR prin valoarea 010 arat c operandul destinaie registru este
DL (tabelul 6.5.) ;
biii r/m prin valoarea 000 pun n eviden (tabelul 6.7.) c expresia de
adres se calculeaz dup formula BX + SI + 0.
Dac se ia n considerare multitudinea de combinaii de expresii de
adresare, pentru o decodificare corect a instruciunilor se identific mai nti
apartenena la unul din tipurile:
T1 - cod operaie;
T2 - cod operaie (operanzii sunt prefixai);
T3 - cod operaie registru;
T4 - cod operaie constant imediat;
T5 - cod operaie registru, registru;
T6 - cod operaie registru, constant imediat;
T7 - cod operaie registru, expresie de adres;
T8 - cod operaie expresie de adres;
T9 - cod operaie expresie de adres, registru;
T10 - cod operaie expresie de adres, constant imediat.
Numai dup aceea se va face distincia ntre registrele generale i registrele
de segmente care au coduri asociate conform tabelului 6.8.

Cod
00
01
10
11

Tabelul 6.8.
Registru segment
ES
CS
SS
DS

Apariia codului registru segment determin ca o zon de trei bii s fie completat
0ss, unde ss reprezint codul registrului segment. Dac se impune, codul segment
poate ocupa i poziiile 4, 3 din baitul codului operaie.
Se observ c structura intern a instruciunii reprezint un mod
convenional de punere n coresponden a multitudinii de tipuri de instruciuni cu
coduri. Se urmrete realizarea de combinaii unice, neambigue, iar asamblorul i
dezasamblorul s fie aplicaii, una transformat a celeilalte.
Trecerea la microprocesorul 386 a condus la noi performane. Limbajul de
asamblare a rmas n mare parte nemodificat, iar programatorul poate realiza
construcii noi, putnd integra complet pe cele vechi.
n dinamicile hardware, structura intern a instruciunilor este afectat cel
mai frecvent. n cazul microprocesorului 386 se specific urmtoarele aspecte:

467

codul operaiei ocup doi baii, permind definirea unor noi variante de
prezentare dar i deschiznd posibilitatea definirii de noi instruciuni ca
operaii sau noi tipuri de instruciuni, ca structur de list de operanzi;
lungimile operanzilor sunt un bait, doi baii i patru baii, lucru ce se
reflect prin informaiile descriptorilor d i w;
registrele se codific pentru trei situai: registrele de un bait, registrele
pe 16 bii i registrele EAX, ECX, EDX, EBX, ESP. EBP, ESI, EDI pe
32 de bii, crora li se asociaz coduri tot de trei bii, pe poziiile din
baitul MODRM.
biii r/m iau n considerare toate structurile de expresii de adres n
varianta lucrului pe 16 bii, iar separat n varianta lucrului pe 32 de bii;
factorul de scal pentru adresarea indexat (biii 7, 6) din al treilea bait
de descriere a instruciunii;
registrul index (biii 5, 4, 3) din al treilea bait;
registrul de baz, urmtorii bii, 2, 1, 0;
deplasarea sau constanta imediat se reprezint n continuare pe zero
(dac lipsete) baii, pe un bait, pe doi baii sau pe patru baii;
n cazul instruciunilor de salt condiia de testare este nglobat pe patru
bii n instruciune, primii trei bii definesc combinaia, iar bitul al
patrulea cnd este unu determin complementarea fa de unu a primilor
trei bii.
Trecerea de la un procesor la altul devine pentru programatorul n limbaj de
asamblare un exerciiu de codificare cu amplasarea impus a cmpurilor ntr-o
succesiune dat de bii. Mai apare n plus o completare a listei de instruciuni ca
mnemonice, cu descrieri riguroase i eventual noi resurse (registre) sau noi
caracteristici ale resurselor (lucrul pe 32 de bii).
Prin studierea comparat a structurilor interne ale instruciunilor limbajelor
de asamblare, a frecvenei de utilizare a instruciunilor i a diversitii
instruciunilor i expresiilor de adresare, este posibil proiectare unei codificri
optime, care minimizeaz lungimea textului generat dup asamblare, ca numr de
baii.
6.5 Comentariile
Programele sunt scrise pentru a rezolva probleme dar i pentru a fi
dezvoltate n aa fel nct s continue rezolvarea problemelor, dup un numr de
ani, dup ce au intervenit modificri n algoritmi, prin efectuarea unor modificri n
definirea operanzilor i n secvenele de prelucrare.
Comentariile sunt mai necesare n programele scrise n limbajul de
asamblare pentru caracterul ermetic, codificat al mnemonicelor i al registrelor.
Este preferabil s se introduc numeroase comentarii ca linii surs distincte
dar i n continuarea instruciunilor.

468

Astfel, secvena:
; programul calculeaz suma
; a dou numere a i b
; rezultatul se va afla n c
mov
ax,a
;ax=a
add
ax, b
;ax=ax+b
mov
c,ax
;c=ax

va putea fi uor modificat de un alt programator dup civa ani de la


scrierea programului.
Secvena:
xor
add
and

bx, 1fach
bx, x[si] + 0cch
di 1dh, 0ff00h

n absena explicrii semnificaiei constantelor 1FACh, 0CCh, 1Dh,


0FF00h, va fi dificil pentru programator s interpreteze i mai ales s actualizeze
aceste constante.
Dei este un efort suplimentar s se includ ntr-un text comentarii,
introducerea obligativitii de a se autodocumenta programele va avea efecte
pozitive asupra procesului de mentenan a acestora.
6.6 Efectele execuiei instruciunilor
Instruciunile sunt simple sau complexe fie n raport cu modul n care sunt
scrise pe o linie program, fie n raport cu ceea ce efectueaz. Este interesant pentru
programator s cunoasc complexitatea n raport cu efectele de prelucrare i s
foloseasc eficient tot ceea ce ofer instruciunile.
Este cunoscut faptul c dup efectuarea de calcule are loc poziionarea
indicatorilor de condiie. Neglijarea acestui aspect va conduce la scrierea n mod
inutil a unei instruciuni de comparare.
Secvena:
mov
sub
cmp
jle

ax, a
ax, b
ax, 0
alfa

va fi scris, cunoscnd cum se poziioneaz indicatorii de condiie, astfel:


mov
sub
jle

ax, a
ax, b
alfa

469

n cazul utilizrii instruciunilor LOOP are loc modificarea coninutului


registrului contor CX prin decrementare, pentru a gestiona repetrile secvenelor.
Pentru construirea de secvene repetitive imbricate (incluse) este necesar salvarea
acestui registru nainte de a intra n secvena repetitiv inclus i restabilirea dup
ieirea din aceasta.
Instruciunile de lucru cu iruri de caractere sunt utilizate alturi de
instruciunea de repetare REP. Traversarea zonelor de memorie presupune
incrementarea automat a registrelor index SI i DI. La terminarea execuiei, aceste
registre permit accesarea primului bait din afara fiecrei zone. Lucrul cu zone de
memorie adiacente n aceste condiii nu mai necesit pregtirea registrelor, prin a
ncrca deplasamentul zonelor surs, respectiv, destinaie. Se va lucra folosind
efectul secundar al instruciunii REP.
Multe din instruciunile care presupun memorare n stiv (CALL, RET, DIV,
INT, IRET, INTO, PUSH, POP) modific mai nti coninutul registrului SP i
stocheaz anumite informaii. Prin incrementarea sau decrementarea registrului SP
programatorul va avea acces la informaii stocate automat ca parte din execuia
unei instruciuni.
De asemenea, programatorul are posibilitatea s defineasc noi combinaii
n care s se efectueze salturile, testnd n mod propriu prin expresiile sale cnd i
cum s se selecteze o anumit secven. Alegerea ntre a lucra pe un bait, pe doi
baii sau pe mai muli baii depinde de natura operanzilor i de magnitudinea
rezultatului. Pentru a efectua corect operaiile trebuie cunoscut ce se modific i ce
rmne nemodificat la execuia unei instruciuni.
Dac un operand are o lungime L1 i cellalt operand are lungimea L2, cnd
se efectueaz operaiile, rezultatul are o lungime dependent de acestea. n cazul
adunrii totalul va avea max (L1, L2) +1 cifre, la nmulire produsul va fi de L1 + L2
cifre, iar la mprire ctul va fi de L1-L2 cifre. Aceste calcule sunt fcute i
rezervrile de zone de memorie vor acoperi acest tip de cerine.
Studierea instruciunilor are rolul de a da mobilitate programatorului i de
a-i crete capacitatea de adaptare la toate cerinele realizrii de programe
performante, chiar dac lucrul n limbaj de asamblare e impus i nu dorit.

470

7
DEFINIREA STRUCTURILOR DE DATE
7.1 Date elementare
Datele elementare sunt asociate unor zone de memorie de lungime fixat
care opional sunt iniializate cu constante care impun att natura operanzilor, ct i
setul de instruciuni cu care se va lucra.
Directivele pentru descrierea datelor elementare determin modificarea
contorului cu o unitate dac tipul este DB (Define Byte), cu dou uniti dac tipul
este DW (DefineWord), cu patru uniti pentru tipul DD (Define Double), cu opt
uniti pentru tipul DQ (Define Quad Word) i cu zece uniti pentru tipul DT
(Define Ten).
Secvena:
a
b
c
d
e
f
g

db
dw
dd
dt
dq
dw
db

13
5
0fah
0
7
?
?

:
;
;
;
;
;
;

a
b
c
d
e
f
g

ocup
ocup
ocup
ocup
ocup
ocup
ocup

un bait iniializat cu 13
2 baii iniializai cu 5
4 baii iniializai cu 0fah
10 baii iniializai cu 0
8 baii iniializai cu 7
2 baii neiniializai
un bait neiniializat

exemplific definiri de variabile elementare cu sau fr iniializare. Alegerea


numelui de dat elementar va fi sugestiv i se va cuta s nu fie ntrebuinat
aceeai variabil pentru mai multe categorii de rezultate n acelai program.
Alegerea tipului DB este util dac datele au valori cuprinse ntre 0 i 255.
Descriptorul DW este preferat cnd variabila are valori cuprinse ntre 0 i 65535.
Tipul de dat DD este utilizat cnd datele sunt cuprinse ntre 0 i 232-1, iar tipul de
date DQ, atunci cnd plaja de valori este cuprins ntre 0 i 264-1. Organizarea
datelor cu semn determin identificarea corect a intervalelor. Astfel, se va defini o
variabil de tip DB dac plaja de valori este cuprins ntre 128 i 127. Se
utilizeaz tipul DW pentru plaja de valori 32768 i 32767. Pentru descriptorul DD
plaja de valori este cuprins ntre 232 i 2 31 1, iar pentru tipul DQ plaja este
definit prin -263 i 2263 1.
Cnd se alege un descriptor de tip, pentru omogenitate se va avea n vedere
ca rezultatele operaiilor s aparin aceluiai tip pentru a evita operaiile de
conversie.

471

7.2 Masive unidimensionale


Masivele unidimensionale se definesc prin:
nume

tip

dup (val_1, val_2,,val_m)

nume
tip
n
val_j

- identificator construit dup regulile limbajului;


- DB, DD, DQ, DT sau un tip definit de utilizator;
- numrul de componente ale masivului;
- valoarea obinut dup evaluarea unei expresii cu poziia j din lista
dac sunt iniializate componentele masivului.

unde:

n secvena:
x
y
z
w
u

db
dw
dd
db
dw

10 dup (a)
20 dup (0)
40 dup (?)
5
dup (3, 4, 5)
1, 2, 3, 4, 5, 6, 7, 8, 9, 10

se aloc memorie pentru:


masivul unidimensional x avnd elemente de un bait, n numr de zece,
fiecare fiind iniializat cu constanta caracter a;
masivul de 20 componente, numit y; fiecare component este iniializat
cu zero; zona de memorie alocat are o lungime de 40 baii;
z, masiv cu 40 componente, care ocup 160 baii, fr iniializare;
masivul w, care are 53 componente, iniializate cu w0 = 3, w1 = 4, w2 =
5, w3 = 3, w4 = 5, w5 = 5,, w12 = 3, w13 = 4, w14 = 5; masivul w ocup
15 baii;
masivul numit u, avnd 10 componente, iniializate una dup alta;
componentele sunt definite ca variabile elementare distincte, cu acelai
descriptor de tip, DW.
7.3 Masive bidimensionale
Se definesc prin compunerea vectorilor de vectori astfel:
nume

tip

dup

(m

dup

(val1-1, val1-2,,val-k))

unde:
nume - identificator cu care se refer matricea;
tip
- descriptor de tip DB, DW, DD, DQ, DT;
n
- numrul de linii ale matricei;

472

m
- numrul de coloane ale matricei;
val-j - valoarea cu care se evalueaz o anumit component.
Operatorul DUP este inclus n mod repetat, permind generalizarea ce
conduce la definirea de masive de masive multidimensionale.
Secvena:
a
b
c
d
e

dw
db
dd
dw
dd

10
3
2
4
4

dup
dup
dup
dup
dup

(10
dup
(3
dup
(7, 4 dup
(1, 2, 3,
(5, 2 dup

(0))
(8), (19))
(3))
4)
(0), 9)

definete matricele urmtoare:


a matrice cu 10 linii i l0 coloane, avnd toate elementele zero;
b matrice cu 3 linii i 4 coloane iniializat astfel:
8 8 8 19
8 8 8 19
8 8 8 19
c matrice cu dou linii i 5 coloane iniializat astfel:

7
7

3
3

3
3

3
3

3
3

d matrice cu 4 linii identic iniializate conducnd la:

1
1
1
1

2
2
2
2

3
3
3
3

4
4
4
4

e matrice cu 4 linii i 4 coloane, iniializat astfel:

5
5
5
5

0
0
0
0

0
0
0
0

9
9
9
9

Matricele fiind masive care presupun elemente de acelai tip, lungimile


zonelor de memorie ocupate se obin nmulind numrul de componente cu
lungimea zonei asociat fiecrui tip (elementul de tip DB are lungimea un bait,
elementul de tip DW are lungimea doi baii, tipul DD presupune alocare 4 baii,

473

tipul DT-10). De exemplu, masivul bidimensional ee, avnd tipul DD, cu 5 linii i
5 coloane, va ocupa o zon de memorie de 100 baii (4 5 5).
7.4 Articolul
Articolul este un conglomerat de membri, care sunt fie date elementare, fie
masive, fie alte articole. Tipurile membrilor sunt diferite.
Un articol se definete prin:
nume

nume

struc
membrul_1
membrul_2

membrul_n
ends

Masivele sunt cazuri particulare, n care membrii sunt de acelai tip.


Definirea unui articol nu presupune rezervare de zon de memorie. Pentru a rezerva
zon de memorie este necesar definirea de variabile de tip articol cu numele
articolului definit.
n secvena:
persoana
struc
nume
vrsta
salariu
nr_copii
reineri
persoana
ends

db
dw
dd
db
dw

30
?
?
?
?

dup

(?)

este definit tipul de date persoana, care este un articol care are n componen ase
membri avnd tipurile DB, DW, DD, DB, respectiv, DW. Lungimea zonei de
memorie ocupat de o variabil de tip STRUC este dat de lungimea membrilor
care intr n alctuirea ei. Astfel, o variabil de tip STRUC persoana va ocupa
30+2+4+1+2=39 baii.
n secvena:
pers persoana (?)
mat_pers persoana 10 dup (10 dup (?))
vect_pr persoana 20 dup (?)

se definesc:
o variabil cu numele de tip STRUC persoana, ce ocup 39 baii, i ai
crei membri se refer cu operatorul . (punct) ca de exemplu, pers.
nume, pers.vrsta, pers.salariu;

474

un masiv bidimensional, avnd 10 linii i 10 coloane, cu elemente de tip


persoana (matrice de articole);
un vector de articole cu 20 de componente.
n toate cazurile construcia <?> indic neiniializarea zonelor de memorie
asociate elementelor de tip persoan.
Pentru iniializarea valorilor pentru fiecare membru la definire sunt dispuse
valori prefixate sau sunt cuprinse ntr-o list de valori respectnd concordana
dintre tipul membrului i tipul constantei.
n cazul absenei unei valori, caracterul poziional al membrilor impune
pstrarea ordinii prin meninerea separatorilor (virgula), n lista de valori iniiale
putnd apare separatori consecutivi.
n secvena:
maina
struc
tip
db
culoare
db
vechime
dw
maina
ends
. . . . . . . .
opel
maina
dacia
maina
diverse
maina

20 dup (?)
roie
?

(berlina, ,15)
2 dup (break, , 0)
100 dup ( , , 20 )

se definete tipul de dat STRUC maina avnd un cmp cu valoare prefixat (care
poate fi modificat printr-o iniializare ntr-o variabil dac respectiva variabil
impune). Se definete variabila OPEL de tip STRUC maina ale crei cmpuri sunt
iniializate dup cum urmeaz: OPEL.nume = berlina, OPEL.culoare = ROIE,
OPEL.vechime OPEL.vechime=15.
DACIA este un masiv unidimensional cu dou componente de tip STRUC
maina. Prima component are membri iniializai astfel: DACIA.nume = brek,
DACIA.culoare = ROIE, DACIA. vechime=0. A doua component (lungimea
unui articol este 20+5+2=27 baii) are membri referii prin DACIA+27 cu valorile
iniializate urmtoare: DACIA+27.nume=brek, DACIA+27.culoare= ROIE,
DACIA+27.vechime=0.
Masivul unidimensional numit DIVERSE are 100 componente de tip STRUC
maina n care membri culoare i vechime se iniializeaz cu ROIE, respectiv,
valoarea 20.
Articole cu cmpuri definite la nivel de bii
Exist variabile care au un numr de valori restrnse i definirea cu tip DB
nseamn deja risip de memorie. n evidena populaiei, mediul din care provine
persoana este rural sau urban (1 sau 0), sexul individului este masculin sau feminin
(1 sau 0), persoana poate avea sau nu copii (1 sau 0), poate fi necstorit (00),

475

cstorit (01), divorat (10) sau vduv (11). Pregtirea profesional poate fi:
absolvent coal general (001), analfabet (000), absolvent liceu (010), absolvent
coal profesional (011), absolvent postliceal (100 ), liceniat (101), absolvent
colegiu (102), doctor n tiine (110), master in science (111). Persoana poate avea
sau nu carnet de conducere (1 sau 0) poate avea sau nu cazier (1 sau 0). Lucrnd la
nivel de cmpuri de bii cu lungime unu, doi sau trei, se va obine o important
economie de memorie la utilizarea de fiiere pentru colectiviti foarte mari.
Utilizarea de fiiere inverse vine s mreasc viteza de regsire dup combinaii de
caracteristici date sub forma cmpurilor de bii.
Articolele definite cu cmpuri de bii utilizeaz descriptorul RECORD
astfel:
nume record nume-1:n1, nume-2:n2,, nume-k:nk
unde:
nume reprezint numele tipului de dat RECORD ce se definete;
nume-j - numele cmpului j din structura de cmpuri de bii;
nj
- numrul de bii care formeaz cmpul j.
n cazul n care la definire apar construcii de forma:
nume-j:nj=expresie-j

expresie_j se evalueaz i este corect n raport cu lungimea cmpului, reprezintnd


valoarea ce se atribuie respectivului cmp la alocarea de memorie. Astfel,
definirea:
a
aa

record al:2, a2:4=11b, a3:2


a
3
dup (?)

construiete tipul de dat avnd cmpuri pe bii repartizai dup urmeaz: a1 ocup
2 bii, a2 ocup 4 bii, iar a3 ocup 2 bii.
Se creeaz vectorul aa cu trei componente, fiecare component fiind pe un
bait structurat conform tipului de dat RECORD a. Cele trei elemente ale masivului
unidimensional au iniializai biii ce corespund cmpului a2 cu valoarea 0011b.
Dac se lucreaz la nivel de cuvnt este important poziionarea cmpurilor
ntruct baiii rmn uniti de baz i cmpurile nu pot fi dispersate n doi baii
adiaceni. Fiecare asamblor poate impune restricii la lungimea n baii a tipului de
dat RECORD. De cele mai multe ori, lungimea cmpurilor n1+n2++nk nu poate
depi 16 bii.
Cnd se lucreaz cu astfel de structuri se utilizeaz operatorul WIDTH care
returneaz lungimea ca numr de bii a unui cmp cruia i-a fost aplicat.
Dac se construiete secvena:
aaa
record
b:5, c:1, d:2, e:4, f:2, g:2
bbb
aaa
(?)
. . . . . . . .

476
mov

a1, width

bbbb + width

bbb.e

instruciunea mov are ca efect ncrcarea n registrul AL a numrului 9 ntruct


operatorul WIDTH aplicat succesiv cmpurilor b i e, returneaz 5, respectiv, 4,
acestea fiind lungimile cu care au fost definite. Pentru a lucra cu biii cmpului
trebuie izolai folosind operatorul MASK. n definirea de mai sus a tipului RECORD
aaa, pentru a putea testa valoarea cmpului c acesta va fi ncrcat dup ce a fost
izolat de restul elementelor care formeaz primul bait, prin instruciunea:
mov h a1, mask bbb.c
cmp
a1,0

; a1:=000000x00

Bitul notat x reprezint cmpul izolat, care face obiectul testrii.


Cmpurile neinteresante ale variabilei RECORD bbb din primul bait sunt
puse pe zero. Cea mai mic unitate de memorie adresabil este baitul.
Programatorul nu poate avea acces n mod direct la iruri de bii. Operatorii WIDTH
i MASK permit meninerea nemodificat a secvenelor de prelucrare atunci cnd se
modific structura de definire a variabilelor RECORD.
Reuniunea de date
Se consider tipuri de date diferite care trebuie s ocupe o aceeai zon de
memorie. Pentru aceasta se utilizeaz descriptorul UNION astfel:
nume

nume

union
membrul-1
membrul-2
membrul-3
. . . . .
membrul-n
ends

unde:
nume - reprezint un identificator care se asociaz tipului de dat UNION;
membrul-j
- definire tipul de date j;
Lj
- lungimea n baii a variabilei de tipul j.
O variabil de tip UNION nume are o lungime egal cu maximul dintre
lungimile L1, L2, . . ., Ln.
Secvena:
salariu
union
sala dw
5 dup (0)
salb dw
?
nume db
20 dup ?
salariu ends

477
ss

salariu

dup

definete o variabil UNION salariu a crei lungime L=max (10,2,20)=20 i


masivul unidimensional ss cu 7 componente neiniializate. Modul de realizare a
suprapunerii baiilor este dat n figura 7.1.
baitul 0 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 . . 19
sala(i) 0 0 1 1 2 2 3 3 4 4
salb ? ?
nume(i)0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 19
Figura 7.1 Suprapunerea n structur de tip UNION
Cifrele din dreptul poziiilor baiilor corespund indicilor masivelor. Astfel,
cu poziia 9 aparine i elementul sala (4) din masivul unidimensional sala, dar i
elementul nume (9). Elementul salb ocup numai primii doi baii.
7.5 Variabile pointer
Spre deosebire de limbajul C n limbajul de asamblare, nu se fac declarri
speciale pentru variabilele pointer. n limbajul de asamblare toate tipurile de
variabile sunt reduse la zonele de memorie pe care le ocup. Variabilele pointer
memoreaz deplasamentele unor variabile sau ale unor etichete definite pentru
instruciuni executabile.
Secvena:
a
db
?
sir
db
abcdefgh
c
dw
?
e
dd
111
addr_a
dw
offset a
addr_sir
dw
offset sir
addr_c
dw
offset c
addr_e
dw
offset e
addr_x
dw
?
. . . . . . . . . . . . .
x:
mov
addr_x, offset

definete variabilele a, ir, c, e de tipuri diferite i variabilele addr a, addr_sir,


addr_c, addr_e care sunt iniializate la definire cu deplasamentele variabilelor, toate
avnd definirea cu descriptorul DW. Variabila addr x tot de tip DW va fi
iniializat la asamblarea programului, ea conine deplasamentul unei instruciuni
(deplasarea instruciunii fa de punctul de nceput al segmentului de cod program).
n programe se definesc vectori de pointeri prin:
vector_ptr

dw

offset adun

478
dw
dw
dw
dw

offset
offset
offset
offset

scade
produs
rest
ordine

unde: adun, scade, produs, rest i ordine sunt nume de proceduri ce pot fi apelate
prin instruciunea
call

vector_ptr + bx

ntr-o structur repetitiv, incrementnd registrul BX. Fa de limbajele evoluate,


vectorul de pointeri poate conine deplasamente att de proceduri ct i de variabile
sau de instruciuni.
7.6 Variabile enumerative
Dac o variabil parcurge un set de valori stabilit, aceste valori se pun n
coresponden cu coduri numere ntregi n ordine cresctoare. Programatorul
utilizeaz valorile, (uneori nenumerice) dar n program sunt vehiculate codurile.
Definiia:
nume enum

val_1, val_2, val_3, . . . ., val_n

unde:
nume - tipul de date enum definit de programator;
val_j - valoarea j pe care o poate avea o variabil de acest tip, care se pune
n coresponden cu j 1;
De exemplu, n secvena:
culoare
zile
calificat
boolean
unitate
a
b
c
d
e

enum rou, alb, verde, galben


enum luni, mari, miercuri, joi, vineri, smbta
enum satisfctor, bine, excelent
enum fals, adevrat
enum bucat, litri, metru, tona
culoare ( ? )
zile ( ? )
calificat 5 dup (bine)
boolean (fals)
unitate litri, buci, tona

s-au definit tipurile de date culoare enum, zile enum, calificat enum, boolean i
unitate tot enum. Variabila a este de tip culoare enum, c este un masiv
unidimensional cu 5 componente de tip califcat enum, variabilele d i e sunt i
iniializate.
Lungimea zonei de memorie asociat depinde de lungimea listei val-j i
poate fi un bait, doi baii, patru baii. De cele mai multe ori codurile sunt 0, 1, 2, . . .

479

. , 255, pentru c nivelele variabilelor sunt restrnse i se aloc pentru variabilele


enum un bait.
Dac se dorete alocarea altor coduri, acest lucru este posibil utiliznd
construcii de forma val_j = expresie.
Definirea:
pre

enum

pre_mic=1000, pre_bun=2000, pre mare=5000

realizeaz o alt punere n coresponden. Dac nu se mai continu iniializare,


valorile sunt puse n coresponden cu coduri generate n continuare. De exemplu:
termin
ccc

enum start=100, continuare, avansare, final


termin
?

pune n eviden c variabila ccc de tip termin ENUM poate lua numai valorile
100, 101 i 102 i 103.
7.7 Tabele de date
Ca n cazul lucrului cu iruri de bii exist posibilitatea de a defini articole
cu cmpuri formate din baii, cuvinte, cuvinte duble, 8 sau 10 baii folosind
descriptorii BYTE, WORD, DWORD, QWORD?. TBYTE SAU PWORD /
FWORD (cmpuri de 6 baii).
Construcia:
nume

TABLE

num_1: tip_1, num_2: tip_2, ....,num_k: tip_k

definete tipul de date tabel unde:


nume - numele tipului de dat tabel definit de programator;
num_j - numele membrului j al tabelei;
tip_j - tipul membrului j al tabelei, n cazul n care tipul este nespecificat
se consider WORD (DWORD dac se lucreaz pe 32 bii).
n cazul n care se utilizeaz construcia:
num_j: tip_j: nr_j
se va asocia membrului num_j un masiv unidimensional cu nr_j componente de
tip_j.
Secvena:
articol TABLE
aaa
articol

nume:BYTE:30, salariu:WORD,reineri:WORD:4

480

definete tipul de dat articol TABLE i variabila de tip articol, numit aaa, care
ocup 50 baii. Tipul de date articol TABLE conine masivele unidimensionale
nume i reineri.
7.8 Obiecte
Structura de date obiect este implementat i n limbajele de asamblare.
Aici se vd mai bine implementrile mecanismelor i proprietilor specifice
lucrului cu obiecte.
Un obiect este un conglomerat de membri mult mai neomogen ca structura
de tip articol ntruct accept ca membri proceduri sau pointeri spre proceduri.
nainte de a da regula general de definire a unei structuri de dat obiect, se va
considera exemplul urmtor de definire obiect.
Pentru rezolvarea unei probleme sunt necesare procedurile:
suma procedur NEAR destinat nsumrii elementelor unui vector;
alege procedura FAR destinat alegerii elementului minim dintr-un
masiv bidimensional;
calcul procedur FAR pentru calculul expresiei A/B unde A este suma
returnat de prima procedur, iar B este minimul returnat de procedura
alege.
Datele cu care se vehiculeaz sunt:
vector
matrice
total
minim
raport

dw
dd
dw
dd
dd

100
10
0
?
?

dup
dup

( ? )
( 20 )

Definirea obiectului de tip calcul_min trebuie s includ ntr-o tabel


metodele (procedurile asociate) i separat variabilele cu care se va lucra.
Pointerii spre procedurile NEAR se definesc WORD, iar pointerii
procedurilor FAR se definesc DWORD.
Tabela metodelor conine pentru fiecare metod numele variabilei pointer
asociat procedurii, tipul i numele procedurii.
Obiectul calcul_min se definete astfel:
calcul_min

struc global
method
ptr_suma:word=suma
ptr_alege:dword=alege
ptr_calcul:dword=calcul
vector
dw
100 dup (?)
matrice
dd
10
dup (20 dup (?))
total
dw
0
minim
dd
?
raport
dd
?

481
calcul_min

ends

n general, pentru a defini complet un obiect n lista metodelor se vor


include procedurile constructor i destructor care returneaz tipul FAR, necesitnd
descriptorul DWORD.
Pentru metode se utilizeaz atributele GLOBAL (pentru a da caracter global
tabelei de metode) virtuale NEAR i FAR (pentru a determina conversiile specifice
lucrului cu 16, respectiv, 32 bii). Aceste atribute vor fi numite modificatori.
n programarea orientat obiect motenirea este o proprietate important,
care presupune un obiect de baz sau obiect printe. Legtura ntre obiectul de baz
i obiectul descendent se efectueaz specificnd la definirea acestuia din urm,
numele printelui.
Toi operanzii cu care se vehiculeaz ntr-un obiect se definesc sub forma
unor membri dintr-un articol.
Pentru definirea unui obiect se folosete definirea:
struc modificator obiect_printe
method
ptr-1: tip-1=nume-proc-1
ptr-2: tip-2=nume_proc-2
. . . . . .
ptr-n:tip-n=nume_proc-n
membrul-1
membrul-2
. . . . . . . .
membrul-k
nume ends
nume

Definirea unei variabile obiect se efectueaz ca i n cazul articolelor, ns


prin utilizarea constructorilor se face alocarea i iniializarea acestor structuri
complexe, care preiau adresele de nceput ale instruciunilor executabile din
procedurile membre.
Apelarea metodelor definite static sau virtual necesit o serie de informaii
care s permit localizarea segmentului unde se afl variabila obiect din care
metoda este membru, numele pointerului care refer metoda precum i cuvintele
cheie CALL i METHOD.
Bibliotecile standard conin definiri de obiecte pentru lucrul cu liste, cozi,
stive i arbori binari. Metodele vizeaz operaiile uzuale cu structurile de date
dinamice, precum: creare, inserare, traversare i tergere.
Diversitatea tipurilor de structuri de date este dat de modul n care este
construit asamblorul. De aceea, este foarte important ca nainte de al lucra cu un
asamblor s se vad care sunt tipurile de date i ce structuri de date pot fi utilizate
i cum. Nu toate asambloarele opereaz cu obiecte, cu tipuri de date sinonime
(typedef) cu tabele sau cu date de tip ENUM. n toate cazurile este necesar s se
urmreasc modul de definire a tipului, definirea variabilelor de tipul respectiv,

482

iniializarea lor la definire i cum se refer n program variabilele sau componente


ale acestora.

8
IMPLEMENTAREA STRUCTURILOR
FUNDAMENTALE
8.1 Programarea structurat
Programarea structurat trebuie privit ca o modalitate de disciplinare a
programatorilor i de introducere a unui stil unic n scrierea de texte surs.
Eliminarea instruciunii GO TO din programe este numai aparent deoarece
apelurile de proceduri, instruciunile PERFORM, conin n mod mascat instruciuni
de salt necondiionat n modulele obiect rezultate la compilare.
Limbajele de asamblare conin dezvoltri care implementeaz aproape
perfect cerinele programrii structurate. La nivel de baz implementarea
structurilor fundamentale este o traducere cu posibilitile specifice ale schemelor
asociate acestor structuri.
Obiectivul implementrii structurilor folosind construcii tipizate este de a
obine programe lizibile, cu un nivel de liniaritate mai ridicat i mai simple, chiar
dac lungimea lor ca numr de instruciuni este mare.
8.2 Structura liniar
Structura liniar apare ca o secven de instruciuni ce nu conine salturi
condiionate sau necondiionate, instruciuni de revenire n procedura apelatoare.
Dei instruciunea CALL este nsoit i de un salt necondiionat, ca factor de
liniarizare a programelor se include n mulimea instruciunilor care contribuie la
realizarea de structuri liniare.
Structura liniar conine instruciuni care se execut una dup cealalt,
exact n ordinea n care apar n secven.
Secvena:
mov
add
add
sub
mul
mov

ax,0
ax, b
ax, c
ax, d
ax, e
prod, ax

;
;
;
;
;

ax:=ax+b
ax:=ax+c
ax:=ax-d
dx:ax:=ax e
prod:=ax

483
mov

prod+2,dx ; prod+2:=dx

reprezint un exemplu tipic de structur liniar.


Secvena:
cld
mov
call
mov
mov
xor
call
mov
mov
int
int

cx, OFFSET VAR


prel
x, dx
y, c1
cx, cx
prel
ah, 9
dx, OFSET text2
21h
11h

corespunde de asemeni unei structuri liniare, instruciunile CALL i INT nsemnnd


mai nti integrarea unor secvene de instruciuni din proceduri, instruciunile de
salt spre ele fiind numai un mijloc.
n plus, ele se traduc prin execut procedura prel, respectiv, execut
ntreruperea 21h sau 11h, ca operaii mai complexe, tot aa cum se execut un
transfer prin instruciunea mov sau o poziionare a indicatorului de condiie DF
prin instruciunea CLD.
8.3 Structur alternativ
n limbajele evoluate, structura alternativ este asociat instruciunii IF
THEN ELSE.
Prin convenie, implementarea structurii alternative presupune evaluarea
unei expresii, poziionarea indicatorilor de condiie sau efectuarea unei comparri
cu poziionarea de indicatori de condiie.
Dac este adevrat condiia se execut secvena etichetat adevrat, iar
n caz contrar se execut secvena etichetat fals.
Compararea se realizeaz prin instruciunile CMP, CMPSB, CMPSW.
Poziionarea indicatorilor se efectueaz i prin operaii de scdere pentru a compara
sau prin alte operaii, excepia fcnd instruciunile MOV, CBW, CWD, LEA, CALL,
ESC, HLT, JXX, LDS, LOCK, LOOP, LES, NOP,
STOS, WAIT, XCHG, XALT.

Secvena:
mov
cmp
jg

ax, a
ax, b
adevrat

mov

maxim, b

fals:

CUT, POP, PUSH, RET,

484
jmp
adevrat :
mov
final:
nop

final
maxim, ax

pune n eviden faptul c secvena corespunztoare condiiei verificate se


afl dup secvena etichetat fals. Pentru a aduce secvena etichetat adevrat
ct mai aproape de instruciunea care poziioneaz indicatorii de condiie ca n
limbajele evoluate pentru IF, se schimb modul de efectuare a testelor.
Secvena:
mov
cmp
jle
adevrat:
mov
jmp
fals:
mov
final:
nop

ax, a
ax, b
fals
maxim, ax
final
maxim, b

este apropiat de instruciunea:


IF(a>b)
maxim:=a
ELSE
maxim:=b;

n cazul n care n program se cere implementarea structurii pseudoalternative IF THEN, este preferabil s se modifice de la nceput testul
indicatorilor de condiie pentru a obine o construcie natural, fr instruciuni de
salt necondiionat introduse n plus.
Secvena:
cmp
jge
mov
mov
int
final:
mov
int

ax,0
final
ah, 9
dx, OFFSET text
21h
;afiare text
ah, 4ch
21h

este preferat secvenei:

485
cmp
jl
jmp
negativ:
mov
mov
int
final:
mov
int

ax, 0
negativ
final
ah, 9
dx, OFFSET text
21h
ah, 4ch
21h

care are dou instruciuni de salt consecutive, greu de acceptat n programe scrise
n limbaj de asamblare eficiente.
Compunerea structurilor alternative impune realizarea unei liniarizri a
secvenelor fr a introduce multe instruciuni de salt.
Secvenei:
IF (condiie_1) THEN
IF (condiie_2) THEN
secvena_1
ELSE
secvena_2
ELSE
IF (condiie_3) THEN
secvena_3
ELSE
secvena_4;

scris ntr-un limbaj evoluat, i va corespunde liniarizarea:


condiie_1
salt fals_1
adevrat_1:
condiie_2
salt fals_2
secvena_1
salt final_1
fals_2:
secvena_2
salt final_2
fals_1:
condiie_3
salt fals_3
adevrat_3:
secvena_3
salt final_3
fals_3:
secvena_4
final_1:

486
nop
final_2:
nop
final_3:
nop

Dac se dorete o apropiere de limbaje evoluate se introduc comentarii n


care apar cuvintele IF, THEN, ELSE pe cte o linie a textului surs din programul
assembler.
Unele dintre etichete pot lipsi, cum secvenele de instruciuni consecutive
NOP pot fi reduse la o singur apariie. Se va urmri ca regul poziionarea
secvenelor aa fel nct instruciunile de salt s refere instruciuni ce vor fi scrise
n continuare.
8.4 Structura repetitiv standard
Se consider o variabil de control care ia valorile n, n-1, n-2,, 3, 2, 1, 0
i o secven care se repet att timp ct variabila de control este diferit de zero.
Testul asupra variabilei de control urmeaz decrementrii acesteia, iar secven de
repetat precede decrementarea variabilei de control (figura .8.1)
cx:=n

secvena
de repetat
cx:=cx-1

nu
cx=0

da
Figura 8.1- Structur repetitiv condiionat posterior

487

ntr-un program se implementeaz aceast structur standard, condiionat


posterior cu instruciunea loop. Instruciunea loop decrementeaz registrul CX, l
testeaz i efectueaz un salt necondiionat la instruciunea a crei etichet este
indicat pe aceeai linie cu ea.
Secvena:
xor
xor
xor
mov
ciclu:
add
add
loop
mov

si,
di,
ax,
cx,

si
di
ax
15

ax, x [si]
si, 2
ciclu
suma, ax

exemplific utilizarea structurii repetitive standard pentru nsumarea primelor


cincisprezece elemente ale unui masiv unidimensional.
Dac apare problema nsumrii elementelor fiecrei linii dintr-un masiv
bidimensional, separat, este necesar includerea unei structuri repetitive standard
ntr-o structur repetitiv standard, ca n secvena:
xor
mov

bx, bx
cx, NR_LINII

xor
xor
push
mov

ax, ax
si, si
cx
ax, NR_COL

ciclul1:

ciclul2:
add
add
loop
mov
add
add
pop
loop

ax, mat [bx][si]


si,2
ciclul2
sum [di], ax
di, 2
bx, NR_COL * 2
cx
ciclul1

Registrul BX este folosit ca baz, registrul CX are dublu rol (contorizeaz


numrul de elemente de pe linia matricei i, respectiv, numrul de linii al matricei).
Trecerea de la o linie la alta se asigur prin modificarea registrului BX. Registrele
index sunt SI (pentru accesarea elementelor de pe coloanele matricei) i DI (pentru
accesarea elementelor vectorului de sume care sunt calculate.
S-au definit constantele simbolice NR_LIN i NR_COL pentru a specifica
cte linii i cte coloane au matricea.

488

iniializri

expresia
condiie

secvena de
repetat

modificare
operanzi din
expresia
condiie

Structura repetitiv condiionat anterior este definit de secvena de


schem logic dat n figura 8.2.

Figura 8.2 Structura repetitiv condiionat anterior


n limbajul de asamblare lipsete instruciunea care implementeaz direct
aceast structur. Vor exista dou instruciuni de salt, una pentru ntreruperea
repetrilor i alta, la sfritul secvenei de repetat care va relua evaluarea expresiei
condiie i testarea ei. Implementarea este necesar n cazul n care nu se poate
obine o transformare a structurii repetitive ntr-o structur standard. De exemplu,
pentru nsumarea elementelor dintr-un vector pn cnd suma depete 1000 sau
sunt epuizate elementele vectorului, n secvena:
mov
mov
mov

ax, 0
si, 0
cx, 0

489
ciclu:
cmp
jg
cmp
je
add
add
inc
jmp
final:
mov
mov

ax, 1000
final
cx, n
final
ax, x[si]
si, 2
cx
ciclu
suma, ax
numr, cx

cele dou teste conduc spre instruciunea cu eticheta final, iar asigurarea repetrii
este dat de instruciunea jmp ciclu. Controlul numrului de repetri se asigur
att prin contorul CX ct i prin valoarea registrului AX. Dac testul este efectuat
asupra registrului CX i n secvena repetitiv nu se modific n mod corespunztor
(dac se pornete de la zero are loc incrementarea, iar dac se pornete de la limita
superioar a intervalului are loc decrementarea) efectul este ciclarea infinit.
n toate cazurile se urmrete stabilirea corect a numrului de repetri.
Testarea incorect a limitei intervalului va conduce fie la neincluderea n calcule a
unor elemente (primul element dac se va ncepe cu limita interioar unu), fie la
includerea unui element din afara intervalului (dac se ncepe cu elementul zero i
se numr n elemente n loc de n-1).
8.5 Structura repetitiv condiionat posterior
Forma nestandard este utilizat cnd numrul de repetri e dependent de
valoarea unei expresii sau de semnul acesteia sau cnd variabila de control
genereaz termenii unei progresii, alta dect progresia aritmetic cu primul termen
n, al doilea termen n-1, iar ultimii termeni nu sunt 3,2,1,0.
Se utilizeaz condiionarea posterioar pentru a nu mai repeta unele
instruciuni. De exemplu, pentru afiarea unor texte introduse de la terminal se
procedeaz astfel:
se afieaz mesajul: INTRODUCEI TEXTUL:;
se introduce textul de ctre utilizator;
se afieaz mesajul: DORII S CONTINUAI? (d/n);
se tasteaz d sau n i dialogul continu sau e terminat.
Dac se utilizeaz structura repetitiv condiionat anterior este necesar ca
nainte de testul de continuare, n mod artificial s se iniializeze variabila
RSPUNS (definit RSPUNS EQU al) cu constanta n. Structura repetitiv
condiionat posterior evit acest impediment, aa cum se poate vedea n secvena:
ciclu:
mov

ah,9

490
mov
int
mov
mov
int
mov
mov
int
mov
int
cmp
jz
cmp
jz
mov
int

dx, OFFSET
21h
ah, 0ah
dx, OFFSET
21h
ah,9
dx, OFFSET
21h
ah,1
21h
a1,d
ciclu
a1, D
ciclu
ah, 4Ch
21h

textl ;text
;text

invitaie
ir caractere

text2 ;text

introdus

text3 ;text

de continuare

;funcia de
;introducere caractere:

S-a optat pe posibilitatea de a considera corect tastarea pentru continuare a


caracterului d sau a lui D. Variabila textl este iniializat cu irul de caractere
INTRODUCEI TEXTUL:, variabila text3 este iniializat cu irul DORII S
CONTINUAI? (d/n), iar variabila text2 este definit prin DB 100 DUP (?) ceea
ce nseamn c textele introduse n cadrul dialogului nu pot depi 100 de
caractere. Se are n vedere posibilitatea de a defini i caracterele de control care s
asigure finalul irurilor i returul de car.
8.6 Structura alternativ multipl
Are corespondent n limbajul C instruciunea switch i n limbajul
PASCAL instruciunea case. n limbajele FORTRAN i COBOL se utilizeaz
forme generale ale instruciunii GO TO cu mai multe etichete i cu o variabil de
indicare a etichetei selectate, prin poziie. Se consider o variabil de control care
poate lua una din valorile VAL1,.,VALn, pentru fiecare din valori se ia cte o
secven de instruciuni, respectiv, secvena_1, secvena_2,,secvena_n.
Dac variabila de control are o valoare diferit de cele specificate se va
executa secvena-0. Fiecare secven are o etichet de nceput i se termin cu o
instruciune de salt necondiionat spre un punct comun de continuare a
programului. Eticheta de nceput a secvenei I este etich_i, iar eticheta punctului de
continuare este etich_m. Variabila de control are numele var. Structura alternativ
multipl va fi implementat prin construcia:
cmp
je
cmp
je

cmp

var, VALI
etich_1
var, VAL2
etich_2
var, VAL_n

491
jz

etich_n

etich_0:
secvena_0
jmp
etich_m
etich_1
secvena_1
jmp
etich_m

etich_n:
etiche
secvena_n
etich_m:
nop

Structura alternativ multipl este caracteristic meniurilor n care


utilizatorul poate tasta un caracter i permite s selecteze o anumit opiune. Dac,
de exemplu se cere evaluarea expresiei:

a b
a b

a * b
e
b 1
a 1

daca x 1
daca x 2
daca x 3
daca x 4
daca x 5
in celelalte cazuri

se definesc i se iniializeaz variabilele a i b i se definete variabila e.


Diversitatea expresiilor conduce la imposibilitatea includerii unei structuri
repetitive n care x s fie variabil de control.
Secvena:
cmp
je
cmp
je
cmp
je
cmp
je
cmp
je

x,1
aduna
x,2
scade
x, 3
produs
x, 4
decrement
x,5
increment

mov
jmp

e, 0
final

zero:

aduna:

492
mov
add
mov
jmp

ax, a
ax, b
e, ax
final

mov
sub
mov
jmp

ax, a
ax, b
e, ax
final

mov
mov
mul
mov
jmp

ax, a
bx, b
bx
e, ax
final

mov
dec
mov

ax, a
ax
e, ax

scade:

produs:

decrement:

final:
nop

implementeaz structura alternativ multipl. Se poate vedea c s-a obinut o


construcie uor de interpretat, n care variabilele a i b nu sunt modificate. Printr-o
alt concepie, instruciunea mov e, ax poate fi integrat secvenei etichetate final.
O alt form de implementare a structurii alternative multiple este legat de
includerea secvenelor n vecintatea instruciunilor de test, seleciile efectundu-se
din aproape n aproape. Evaluarea expresiei e se realizeaz prin secvena:
cmp
jne

x, 1
salt_1

mov
add
jmp

ax, a
ax, b
final

cmp
jne

ax, 2
salt_2

mov
sub
jmp

ax, a
ax, b
final

cmp
jne

x, 3
salt_3

mov
mul
jmp

ax, a
b1
final

adun:

salt_1:

scade:

salt_2:

produs:

salt_3:

493
cmp
jne

x, 4
salt_4

mov
dec
jmp

ax, b
ax
final

cmp
jne

x ,5
salt_5

mov
inc
jmp

ax, a
ax
final

mov

ax, 0

mov

e, ax

decrement:

salt_4:

increment:

salt_5:
final:

Toate structurile descrise pot fi mbuntite sau ignorate dac se urmrete


construirea de secvene ct mai concentrate. Totui, pentru realizarea unui stil de
programe specific lucrului n echip sunt preferate convenii de tipul celor
prezentate ca implementri ale structurilor fundamentale de programe. Designul
limbajului de programare ia n considerare i acurateea limbajului de a reflecta
proprietile structurate.

9
ARITMETICI BINARE
9.1 Aritmetica binar pe 8 bii
Aritmetica pe 8 bii presupune definirea operanzilor surs ai expresiilor cu
descriptorul DB.
Pentru efectuarea adunrii se utilizeaz instruciunea add. De exemplu,
pentru evaluarea expresiei:
e = a + b

se utilizeaz secvena:

494
a
b
e

db
db
db

mov
add
mov

al, a
al, b
e, al

20
13
?

Regitrii care particip la aritmetica pe 8 bii sunt AH, AL, BH, BL, CH, CL, DH
i DL.
Iniializarea cu zero a unui registru se efectueaz prin instruciuni precum:
mov
sub

ah, 0
bl, bl

xor
mov

cl, cl
ch, cl

Scderea pe 8 bii se efectueaz cu instruciunea sub. Secvena:


x
y
z

db
db
db

25
7
?

mov
mov
sub
mov

ch, x
dl, y
ch, dl
z, ch

evalueaz expresia:
z=x-y
nmulirea pe 8 bii utilizeaz instruciunea mul. Denmulitul se
memoreaz n registrul AL, iar rezultatul se va gsi n registrul AH : AL.
Secvena:
a
b
c
e
f
g

db
db
db
dw
dw
dw

mov
mov
mul

al, a
bl, b
bl

7
5
8
?
?
?

495
mov
mov
mul
mov
mov
mul
mov

e, ax
al, a
c
f, ax
al, a
3
g, ax

evalueaz expresiile :
e = a * b
f = a * c
g = 3 * a

Instruciunea mul realizeaz operaia de nmulire considernd operanzii ca


numere fr semn (folosete bitul de semn ca fcnd parte din numrul respectiv i
nu ca semnul acestuia). Atunci cnd operatorii sunt considerai ca avnd semn (din
8 bii, cel mai semnificativ arat semnul) trebuie s se foloseasc instruciunea
imul, aceasta folosind bitul de semn n mod corespunztor. Rezultatul este
considerat numr cu semn. Modul de folosire al acesteia este identic cu cel al
instruciunii mul.
Operaia de mprire utilizeaz instruciunea div. Secvena:
a
b
cat
rest

db
db
db
db

mov
cbw
div
mov
mov

al, a

32
4
?
?

b
cat, ah
rest, al

evalueaz expresia:
cat = [a/b]
rest = a cat * b

unde parantezele [ ] reprezint operatorul de extragere a prii ntregi.


Pentru efectuarea mpririi este obligatoriu ca dempritul s se afle n
registrul AX, dup efectuarea conversiei de la dat de tip DB la dat de tip DW. Ctul
mpririi se afl n registrul AH. Restul mpririi se afl n registrul AL.
mpritorul se refer fie ca nume de variabil:
div b

496

fie ca registru:
div cl

sau
div dh

sau
div bl

fie sub form de operand imediat:


div 7

sau
div 2

n mod asemntor nmulirii, mprirea cu semn nu se mai realizeaz cu


instruciunea div, ci cu idiv. Aceasta recunoate bitul de semn i l folosete
corespunztor, ntr-o sintax identic cu cea a instruciunii div.
9.2 Aritmetica binar pe 16 bii
Aritmetica pe 16 bii presupune definirea operanzilor surs ai expresiilor cu
descriptorul DW.
Pentru efectuarea adunrii se utilizeaz instruciunea add. De exemplu,
pentru evaluarea expresiei:
e=a+b
se utilizeaz secvena:
a
b
e

dw
dw
dw

mov
add
mov

ax, a
ax, b
e, ax

20
13
?

Regitrii care particip la aritmetica pe 16 bii sunt AX, BX, CX I DX


Iniializarea cu zero a unui registru se realizeaz prin instruciuni precum:
mov

ax, 0

sub

bx, bx

497
xor

cx, cx

Scderea pe 16 bii se efectueaz cu instruciunea sub. Secvena:


x
y
z

dw
dw
dw

25
7
?

mov
mov
sub
mov

cx, x
dx, y
cx, dx
z, cx

evalueaz expresia:
z = x-y
nmulirea pe 16 bii utilizeaz instruciunea mul. In timp ce denmulitul se
memoreaz n registrul AX, rezultatul se va gsi n perechea de regitrii DX:AX.
Secvena urmtoare:
a
b
c
e
f
g

dw
dw
dw
dd
dd
dd

mov
mov
mul
mov
mov
mov
mul
mov
mov
mov
mul
mov
mov

ax, a
bx, b
bx
e, ax
e+2, dx
ax, a
c
f, ax
f+2, dx
ax, a
3
g, ax
g+2, dx

evalueaz expresiile :
e = a * b
f = a * c
g = 3 * a

7
5
8
?
?
?

498

Pentru o nmulire n care operanzii sunt considerai ca avnd semn, se va


folosi, la fel ca i pe 8 bii, instruciunea imul. Operaia de mprire se realizeaz
prin instruciunea div.
Secvena:
a
b
cat
rest

dw
dw
dw
dw

mov
cwd
div
mov
mov

ax, a

32
4
?
?

b
cat, ax
rest, dx

evalueaz expresia:
cat = [a/b]
rest = a cat * b

unde parantezele [ ] reprezint operatorul de extragere a prii ntregi.


Pentru efectuarea mpririi dempritul se afl n registrul AX, iar ctul
mpririi se afl n registrul AX. Restul mpririi se gsete n registrul DX.
mpritorul se refer fie ca nume de variabil:
div b

fie ca registru:
div cx

sau
div bx

fie sub form de operand indexat:


div 7

sau
div 2

n cazul n care operanzii sunt cu semn, situaia se repet: se va folosi


instruciunea idiv.

499

9.3 Aritmetica binar pe 32 bii


Atunci cnd se lucreaz cu un procesor cu regitri de pn la 16 bii i fr
coprocesor, aritmetica binar pe 32 bii se realizeaz prin folosirea concomitent a
doi regitri pe 16 bii.
Adunarea pe 32 bii se face cu ajutorul instruciunii adc (adunare cu
transport). Astfel, secvena:
dp1
dd
dp2
dd
dpsum dd
mov
add
mov
mov
adc
mov

A92Fh
49837h
?

ax, dp1
ax, dp2
dpsum, ax
ax, dp1+2
ax, dp2+2
dpsum+2, ax

evalueaz expresia:
dpsum = dp1 + dp2

0 0 0 6 A 9 2 F +
0 0 0 4 9 8 3 7
0 0 0 B 4 1 6 6

sau detaliat:
carry 1+
0 0 0 6+
0004

A92F+
9837

000B

4166

Scderea pe 32 de bii se face cu ajutorul instruciunii sbb (scderea cu


mprumut). Secvena:
a
b
c

dd
dd
dd

6A92Fh
4B837h
?

mov
sub
mov

ax, b
ax, a
bx, b+2

500
sbb
mov
mov

bx, a+2
c, ax
c+2, bx

evalueaz expresia:
c = a - b

0006A92F0004B837
0001F0F8
sau detaliat:
0 0 0 60 0 0 4carry 1

A92FB837

0001

F0F8

n continuare se prezint un exemplu de calcul ce folosete combinat


adunarea i scderea pe 32 de bii. Astfel, dac se dorete calcularea unei expresii
de forma:
W = x + y +24 z

se folosete o secvena de cod de genul:


x
y
z
w

dd
dd
dd
dd

<valoare oarecare>
<valoare oarecare>
<valoare oarecare>
?

mov
mov
add
adc
add
adc
sbb
sbb
mov
mov

ax, x
dx, x+2
ax, y
dx, y+2
ax, 24
dx, 0
ax, z
dx, z+2
w, ax
w+2, dx

nmulirea pe 32 de bii, atunci cnd doar registre pe 16 bii sunt


disponibile, se face prin desprirea fiecrui operand n dou numere. Astfel, dac

501

avem de nmulit dou numere, A i B, fiecare cu o valoarea ce depete


capacitatea de memorare a 16 bii, acestea se pot scrie i sub forma:
A = a1 216 + a2
B = b1 216 + b2
Prin urmare, nmulirea acestor dou numere se descompune astfel:
a1 216 + a2 X
b1 216 + b2
a1 b1 2

32

a1 b2 216 + a2 b2 +
+ a2 b1 216

a1 b1 232 + (a1 b2 + a2 b1 ) 216 + a2 b2


Acestei descompuneri i corespunde urmtoarea secven de cod:
mov
mul
mov
mov
mov
mul
mov
add
adc
mov
mul
add
adc
mov
mov
adc
mov
mul
add
adc
mov
mov

ax, a
b
rez, ax
cx, dx
ax, a + 2
b
bx, dx
cx, ax
bx, 0
ax, a
b + 2
cx, ax
bx, dx
rez + 2, cx
cx, 0
cx, 0
ax, a + 2
b + 2
ax, bx
dx, cx
rez + 4, ax
rez + 6, dx

Pentru mprirea pe 32 de bii nu putem aplica aceeai metod de


descompunere a numerelor pe 32 de bii n cte dou numere pe 16 bii.
Pentru a mpri pe A la B, cu aflarea ctului C i a restului R, recurgem la
o metod simpl: adunarea repetat a lui B pn la depirea numrului A. n
pseudocod, aceast metod arat astfel:

502

S=B
C=0
ct timp ( S <= A )
{
C=C+1
S=S+B
}
R=A(SB)
Aceast metod este relativ rapid, deoarece nu folosete dect operaii de
adunare i de scdere pe 32 de bii. n limbaj de asamblare, transpunerea
pseudocodului de mai sus arat astfel:
a
dd
<valoare>
b
dd
<valoare>
c
dd
?
r
dd
?
s
dd
?
. . . . . . . . .
mov
ax, offset s
mov
word ptr [ax], b
mov
word ptr [ax+2], b+2
mov
ax, offset c
mov
word ptr [ax], 0
mov
word ptr [ax+2], 1
iar:
cmp32
jg
add32
add32
jmp

s, a
et
c, 1
s, b
iar

sub32
mov
mov
mov
sub32

s, b
ax, offset r
word ptr [ax], a
word ptr [ax+2], a+2
r, s

et:

unde cmp32, add32, sub32 sunt macrodefiniii pentru compararea, adunarea i


scderea numerelor pe 32 de bii. Pentru construirea macrodefiniiilor, add32 si
sub32, s-au descris mai sus blocurile de instruciuni, n timp ce pentru cmp32,
codul macrodefiniiei este urmtorul:
cmp32 MACRO va1, val2
mov
ax, val
cmp
ax, val2
jnz
iesire

503
mov
cmp
iesire:

ax, val + 2
ax, val2 + 2

ENDM

Se compar mai nti prile mai semnificative ale celor dou valori. Numai
dac acestea sunt egale se trece la compararea parilor mai puin semnificative. n
final indicatorii de condiie vor fi setai corespunztor.
Aceste structuri de cod pot fi folosite atunci cnd nu se poate face uz de un
coprocesor matematic, iar microprocesorul nu posed regitri pe mai mult de 16
bii. Odat cu apariia microprocesoarelor pe 32 de bii, se pot folosi registrele
generale EAX, EBX, ECX, EDX. Aceste metode nc prezint importan pentru
operaii cu numere de peste 64 de bii, ele putnd fi extinse foarte uor pe orice
numr de bii, atunci cnd se lucreaz cu numere foarte mari.

10
ARITMETICI ZECIMALE

10.1 Ajustri
Aritmetica zecimal presupune efectuarea operaiilor bait cu bait n cazul
reprezentrii despachetate sau nibble cu nibble pentru reprezentarea mpachetat.
Pentru a menine la nivelul fiecrui bait reprezentri ale cifrelor de la 0 la 9
se impune efectuarea de ajustri care se fac n mod diferit n funcie de operaiile
efectuate asupra operanzilor.
De exemplu, ajustarea pentru adunarea zecimal despachetat nseamn
corectarea fiecrui nibble mai puin semnificativ a fiecrui octet n cazul unei
depiri la adunare. Rezultatul adunrii numerelor:
0
0
0

1
6
7

0
0
0

3
6
9

0
0
0

5
1
6

0
0
0

8
0
8

nu necesit ajustri pentru c toate cifrele corespund alfabetului pe care se definete


reprezentarea zecimal despachetat. n schimb, rezultatul adunrii numerelor:
0

504

0
0

8
F

0
0

7
C

0
0

9
F

conine elemente care nu sunt n alfabetul reprezentrii zecimal despachetate (C,


F). Aplicnd instruciuni de ajustare aaa bait de bait de la dreapta la stnga se
realizeaz corecia i rezultatul acestei adunri va fi: 01060305.
Efectul unei instruciuni de ajustare asupra unui bait stocat n AL se exprim
n pseudocod astfel:
dac ((AL) & 0Fh)>9 sau (AF)=1 atunci
{
(AL)(AL)+6
(AH)(AH)+1
(AF)1
(CF)(AF)
(AL)(AL) & 0Fh
}
Ajustarea pentru adunarea zecimal mpachetat realizeaz corecia fiecrui
nibble a octetului unde a fost semnalat depirea. Astfel pentru adunarea
numerelor:
0
0
0

3
7
A

7
8
F

8
5
D

5
8
D

4
7
B

aplicnd ajustarea bait de bait se va obine numrul: 11 64 41.


Exist urmtoarele instruciuni pentru efectuarea de ajustri:
Pentru reprezentri ale numerelor n format zecimal despachetat:
AAA (ASCII Adjust for Addition) care face o ajustare a registrului
acumulator pentru adunare (descris mai sus);
AAD (ASCII Adjust for Division): ajustare pentru mprire. Aceast
instruciune face o nmulire a registrului AH cu 10, rezultatul este adunat cu
registrul AL, iar rezultatul final este depus n AL, registrul AH fiind iniializat cu 0.
AAM (ASCII Adjust for Multiply): ajustare pentru nmulire. Coninutul
registrului AH este nlocuit cu ctul mpririi registrului AL la 10, apoi coninutul
registrului AL este nlocuit cu restul mpririi.
AAS ((ASCII Adjust for Subtraction): ajustare pentru scdere. Modificrile
asupra registrului acumulator efectuate de aceast instruciune sunt exemplificate
cu ajutorul limbajului pseudocod:
dac ((AL) & 0Fh)>9 sau (AF)=1 atunci

505

{
(AL)(AL)-6
(AH)(AH)-1
(AF)1
(CF)(AF)
(AL)(AL) & 0Fh
}
Pentru reprezentri ale numerelor n format zecimal mpachetat:
DAA (Decimal Adjust for Addition): ajustare pentru adunare: dac cel mai
puin semnificativ nibble al registrului AL este mai mare dect 9 sau dac AF este
setat pe 1, atunci la registrul AL se adun 6 si AF este setat pe 1. Dac AL este mai
mare dect 9Fh sau dac AF este setat pe 1, atunci la registrul AL se adun 60h i
AF este setat pe 1.
DAS (Decimal Adjust for Subtraction): ajustare pentru scdere: dac cel
mai puin semnificativ nibble al registrului AL este mai mare dect 9 sau dac AF
este setat pe 1, atunci din registrul AL se scade 6 si AF este setat pe 1. Dac AL
este mai mare dect 9Fh sau dac AF este setat pe 1, atunci din registrul AL se
scade 60h i AF este setat pe 1.
10.2 Adunarea i scderea
ADD - Arithmetic Addition (Adunare)

Folosire: ADD dest, src


Flag-uri modificate: AF CF OF PF SF ZF
Adun operandul src la operandul dest i memoreaz
operandul dest. Ambii operanzi au reprezentare binar.

Operatori
reg,reg
mem,reg
reg,mem
reg,immed
mem,immed
accum,immed

Timpi
808x 286
3
2
16+EA 7
9+EA 7
4
3
17+EA 7
4
3

De exemplu, secvena:
termen1
termen2

dw
dw

11
23

386
2
7
6
2
7
2

486
1
3
2
1
3
1

rezultatul n

Lungime
Bytes
2
2-4 (W88=24+EA)
2-4 (W88=13+EA)
3-4
3-6 (W88=23+EA)
2-3

506
total
dw
..
mov ax, termen1
add ax, termen2
mov total, ax

realizeaz adunarea valorii variabilei termen2 la coninutul registrului AX, n care


fusese mutat valoarea variabilei termen1. Rezultatul adunrii este depus n
registrul AX, iar apoi este mutat n variabila total.
SUB Subtract (scdere)

Folosire: SUB dest, src


Flag-uri modificate: AF CF OF PF SF ZF
Sursa este sczut din destinaie i rezultatul este copiat n destinaie.
Timpi
Operatori
808x 286
reg,reg
3
2
mem,reg
16+EA 7
reg,mem
9+EA 7
reg,immed
4
3
mem,immed 17+EA 7
accum,immed 4
3

386
2
6
7
2
7
2

486
1
3
2
1
3
1

Lungime
Bytes
2
2-4 (W88=24+EA)
2-4 (W88=13+EA)
3-4
3-6 (W88=25+EA)
2-3

Astfel, secvena:
termen1
dw
termen2
dw
dif
dw

mov ax, termen2


sub ax, termen1
mov dif, ax

7
15
?

realizeaz scderea valorii variabilei termen1 din coninutul registrului AX, n


care fusese mutat valoarea variabilei termen2. Rezultatul scderii este copiat n
registrul AX, iar apoi este mutat n variabila dif.
10.3 nmulirea i mprirea
MUL - Unsigned Multiply (nmulire fr semn)

507

Folosire: MUL src


Flag-uri modificate: CF OF (AF,PF,SF,ZF nedefinii)
nmulete fr semn acumulatorul cu operandul surs. Dac operandul surs
src este o valoare pe un octet, atunci AL este folosit ca denmulit i rezultatul se
memoreaz n AX. Dac operandul src este un cuvnt, atunci AX este nmulit cu
sursa i DX:AX primete rezultatul. Dac sursa este un dublu-cuvnt atunci EAX
este nmulit cu sursa i rezultatul este pus n EDX:EAX.

Operatori
reg8
reg16
reg32
mem8
mem16
mem32

Timpi
808x
286 386
70-77
13
9-14
118-113
21
9-22
9-38
(76-83)+EA 16
12-17
(124-139)+EA 24
-

486
13-18
13-26
13-42
13-18
12-25
12-21

Lungime
Bytes
2
2
2-4
2-4
13-26 2-4
13-42 2-4

Astfel, secvena:
factor1
dw
factor2
dw
produs
dd ?
..
mov ax, factor1
mul ax, factor2
mov produs, ax
mov produs+2, dx

41
15

realizeaz nmulirea valorii variabilei factor2 cu coninutul registrului AX, n


care fusese mutat valoarea variabilei factor 1. Produsul se obine n registrul
dublu DX:AX. Rezultatul nmulirii este apoi mutat n variabila produs definit
pe dublu cuvnt.
Aceast operaie presupune obligativitatea folosirii registrului AX pentru
denmulit i a registrului dublu DX:AX pentru rezultat. nmulitorul se gsete
ntr-un registru, ntr-o zon de memorie sau este o constant imediat.
DIV Divide (mprire)

Folosire: DIV src


Flag-uri modificate: (AF,CF,OF,PF,SF,ZF nedefinii)

508

Acumulatorul este mprit la surs binar fr semn. Dac operatorul surs


este un octet atunci AX este mprit de surs (DX trebuie s fie 0); ctul mpririi
este pus n AL, iar restul n AH. Dac operatorul surs este un cuvnt, atunci
DX:AX este mprit la surs; ctul mpririi este pus n AX, iar restul este pus n
DX.
Timpi
Lungime
Operatori
808x
286 386 486 Bytes
reg8
80-90
14
14
16
2
reg16
144-162
22
22
24
2
reg32
38
40
2
mem8
(86-96)+EA 17
17
16
2-4
mem16
(150-168)+EA 25
25
24
2-4 (W88=158176+EA)
mem32
41
40
2-4
De exemplu, n secvena:
deimpartit dw
41
impartitor dw
15
cat
dw
?
rest
dw
?
..
mov ax, deimpartit
cwd
div impartitor
mov cat, ax
mov rest, dx

se realizeaz mprirea valorii variabilei deimpartit aflat n registrul DX:AX la


coninutul variabilei impartitor. Ctul se obine n registrul AX, iar restul se
obine n registrul DX. Rezultatele mpririi sunt apoi mutate n variabilele cat,
respectiv rest.
Dempritul este obligatoriu s fie memorat n registrul dublu DX:AX,
extensia semnului se obine cu instruciunea cwd.
10.4 Proceduri de calcul
Necesitatea aritmeticii zecimale este dat de manipularea numerelor foarte
mari n condiiile asigurrii preciziei. Lucrul n aritmetica binar pe doi baii
asigur precizie operanzilor care dup evaluarea expresiei conduc la un rezultat
cuprins ntre [-3276832767].
n tabel sunt prezentate preciziile pentru rezultatele evalurilor n cazul
celorlaltor tipuri de date.

509

Tabelul 10.1.
-128127
0255
-3276832767
065535
-2^312^31-1
02^32-1

1 octet cu semn
1 octet fr semn
2 octei cu semn
2 octei fr semn
4 octei cu semn
4 octei fr semn

Ideea aritmeticii zecimale const n dezvoltarea unor proceduri de


manipulare a irurilor de caractere formate din elementele 00h, 01h, 02h, 03h, 04h,
05h, 06h, 07h, 08h, 09h n cazul aritmeticii zecimale despachetate sau din 0000b,
0001b, 0010b, 0011b, 0100b, 0101b, 0110b, 0111b, 1000b, 1001b n cazul
aritmeticii zecimale mpachetate.
De la tastatur se iniializeaz irul x cu 7245893106 care obine imaginea
memorie (hexazecimal):
37

32

34

35

38

39

33

31

30

36

x
Figura 10.1 Imaginea zonei de memorie ocupat de irul x
folosind codurile ASCII pentru simbolurile cifrice.
Dac se traverseaz masivul unidimensional x (de la stnga la dreapta) i
din fiecare bait se scade constanta 30h (care corespunde caracterului 0) se va
obine irul x modificat a crui imagine este:
07

02

04

05

08

09

03

01

00

06

Figura 10.2 Imaginea zonei de memorie ocupat de irul x dup modificare


Aceasta este forma zecimal despachetat a numrului foarte mare
7245893106 introdus de la tastatur, i cu care se dorete gsirea unei modaliti de
a face calcule.
Intereseaz faptul c se cunoate numele zonei de memorie (x) i folosind o
procedur de stabilire a lungimii unui ir a crui delimitator de sfrit este
caracterul $ se va cunoate cte cifre are numrul. Restricia lungimii numrului
este dat de ct de mare este spaiul contiguu de memorie cu care se poate opera
ntr-un program scris n limbaj de asamblare.
Se observ c dac un bait conine o cifr a numrului primii patru bii
(high nibble) conin zerouri iar ceilali patru bii (low nibble) conin combinaia
corespunztoare cifrei.

510

Exist posibilitatea de a elimina zerourile (din high nibble) i de a aduce


acolo combinaia de bii pentru o cifr. Deci pe un bait se vor reprezenta dou cifre
ale numrului. Aceast reprezentare se numete zecimal mpachetat.
Zona de memorie ce conine numrul introdus de la tastatur este (n forma
zecimal mpachetat):
72

45

89

31

06

y
Figura 10.3 Imaginea zonei de memorie ocupat de variabila y
mpachetarea se face de la dreapta la stnga i dac numrul de cifre este
impar se completeaz baitul cel mai din stnga n partea mai semnificativ cu bii
de 0. Astfel numrul 72541 introdus de la tastatur va ocupa o zon de memorie a
cu coninutul:
37

32

35

34

31

a
Figura 10.4 Imaginea zonei de memorie ocupat de variabila a
Transformarea sa n numr zecimal despachetat n zona de memorie b este:
07

02

05

04

01

b
Figura 10.5 Imaginea zonei de memorie ocupat de variabila b
mpachetarea numrului coninut de zona de memorie b n zona de memorie
c este:
07

25

41

c
Figura 10.6 Imaginea zonei de memorie ocupat de variabila c
n continuare sunt prezentate exemple de proceduri pentru operaii n
aritmetica zecimal:
.data
buf db 255,255 dup(?)
null equ 0ffh

511
.code
; procedura de citire de la tastatur a unui ir de caractere
cifrice :
; adresa destinaiei este es:[di]
getnumber proc
cld
mov ah, 0ah
mov dx, seg buf
mov ds, dx
mov dx, offset buf
mov [dx], 255
int 21h
mov si, offset buf
inc si
xor cx, cx
mov cl, byte ptr [si]
inc si
@@01:
lodsb
cmp al, 0
jb @@02
cmp al, 9
ja @@02
stosb
loop @@01
@@02:
mov byte ptr [di], null
ret
getnumber endp
; procedura de aflare a numrului de octei
; adresa irului n es:[di] i rezultat n ax
ndigit proc
cld
mov bx, di
mov al, null
xor cx, cx
not cx
repne scasb
mov ax, di
sub ax, bx
dec ax
ret
ndigit endp
; procedura de conversie ir de cifre zecimal despachetat
; sursa ds:[si], destinaia es:[di]
asctobcd proc
cld
mov ah, null
@@03:
lodsb

512
cmp al, ah
je @@04
sub al, 0
stosb
jmp @@03
@@04:
stosb
ret
asctobcd endp
; procedura de conversie zecimal despachetat ir de cifre
; sursa ds:[si], destinaia es:[di]
bcdtoasc proc
cld
mov ah, null
@@05:
lodsb
cmp al, ah
je @@06
add al, 0
stosb
jmp @@05
@@06:
stosb
ret
bcdtoasc endp
; procedura de conversie despachetat mpachetat
; sursa ds:[si], destinaia es:[di]
unpackedtopacked proc
cld
push es
push di
mov di, si
mov ax, ds
mov es, ax
call ndigit
mov cx, ax
pop di
pop es
shr cx, 1
jnc @@07
movsb
@@07:
lodsw
shl ah, 1
shl ah, 1
shl ah, 1
shl ah, 1
or al, ah
stosb
loop @@07

513
movsb
ret
unpackedtopacked endp
; procedura de conversie mpachetat despachetat
; sursa ds:[si], destinaia es:[di]
packedtounpacked proc
cld
@@07:
lodsb
cmp ah, null
je @@08
mov ah, al
shr ah, 1
shr ah, 1
shr ah, 1
shr ah, 1
and al, 0fh
stosw
jmp @@07
@@08:
stosb
ret
packedtounpacked endp
; procedura de copiere a unui ir terminat cu caracterul
special (null)
; sursa ds:[si], destinaia es:[di]
bcdcopy proc
cld
@@09:
mov ah, null
lodsb
cmp al, ah
stosb
je @@09
bcdcopy endp
; procedura de redimensionare a unui numr zecimal mpachetat
; sursa ds:[si], destinaia es:[di], dimensiune ir nou n
ax
bcdnorm proc
cld
push ax
push es
push di
mov ax, ds
mov es, ds
mov di, si
mov al, null
xor cx, cx
neg cx

514
repne scasb
mov cx, di
sub cx, si
mov si, di
dec si
pop di
pop es
pop ax
add di, ax
sub ax, cx
std
rep movsb
mov cx, ax
mov al, 0
rep stosb
ret
bcdnorm endp
; procedura de adunare zecimal mpachetat
; sursa ds:[si], destinaia es:[di] (dest=dest+sursa)
; considerm numerele normalizate la un numr dat de octei
dat ;n cx
bcdadd proc
cld
clc
@@10:
lodsb
adc al, byte ptr es:[di]
daa
stosb
loop @@10
ret
bcdadd endp
; procedura de scdere zecimal mpachetat
; sursa ds:[si], destinaia es:[di] (dest=destsursa)
; considerm numerele normalizate la un numr dat de octei
dat n cx
bcdsub proc
cld
clc
@@11:
lodsb
abb al, byte ptr es:[di]
das
stosb
loop @@11
ret
bcdsub endp
; exemplu de apelare proceduri
.data

515
s1 db 12632, null
; ascii
s11 db 11 dup(?)
; unpacked bcd
s12 db 11 dup(?)
; packed bcd
s13 db 11 dup(?)
; normalized packed bcd
s2 db 0, 0, 0, 0, 0, 0, 0, 22, 31, 69
; normalized
packed bcd
.code
start:
mov ax, seg s1
mov es, ax
mov ds, ax
lea si, s1
lea di, s11
call asctobcd
lea si, s11
lea di, s12
call unpackedtopacked
lea si, s12
lea di, s13
mov ax, 10
call bcdnorm
lea di, s13
lea si, s2
mov ax, 10
call bcdadd
end

10.5 Determinarea lungimii rezultatului evaluri unei expresii aritmetice


Se consider expresia:
e=(a*b+c)/da
Pentru evaluarea acestei expresii n aritmetica zecimal este necesar efectuarea
unor calcule privind lungimea zonelor de memorie cu care se lucreaz. Operanzii a,
b, c , d, e ocup zone de memorie, respectiv de lungimile la, lb, lc, ld, le.
Rezultatul nmulirii a*b necesit o zon de memorie la = la + lb + 1.
Rezultatul adunrii necesit o zon de memorie de lungime
ly = max { lx, lc } + 1
Rezultatul mpririi necesit o zon de memorie de lungime ly = ly - ld iar
rezultatul scderii necesit o zon de memorie de lungime le = max { lz, la }.

516

11
NTRERUPERI
11.1 ntreruperi interne i externe
O ntrerupere este un eveniment care duce la ntreruperea temporar a
execuiei unui program, executnd o subrutina numit serviciul ntreruperii
(Interrupt Service Routine ISR), dup care reia programul oprit din acelai punct,
ca i cnd nu s-ar fi ntmplat nimic. ntreruperile au fost realizate ca alternativ la
examinarea repetat a perifericelor pentru detectarea unei operaii de intrare/ieire
(polling). Astfel, n locul acestei interogri repetate i costisitoare, perifericele
genereaz semnale de ntrerupere, apelnd serviciul corespunztor.
Dei momentul de declanare este oarecare, semnalele de ntrerupere nu
sunt recunoscute de ctre procesor dect ntre doua apeluri de instruciuni. Astfel,
dac se execut o instruciune ce necesit multe cicluri maina (cum este, spre
exemplu, o nmulire, care poate necesita pn la 139 de cicluri procesor), iar un
apel de ntrerupere are loc n timpul acesta, el este pus n ateptare pn la
terminarea instruciunii. Excepie de la aceast regula o fac instruciunile cu
repetare, cum sunt instruciunile de lucru cu iruri (de exemplu rep movsb), care
sunt ntrerupte.
n cadrul programrii procesoarelor din familia 8086, ntreruperile se mpart
n dou clase:
ntreruperi externe
ntreruperi interne
ntreruperile externe au loc n momentul generrii unui semnal de ctre
diferitele dispozitive spre procesor. Pe de alt parte, ntreruperile interne sunt
declanate n dou moduri: ca urmare a apelului unei instruciuni int sau ca urmare
a unei excepii generate de o condiie de eroare (cum ar fi spre exemplu mprirea
la zero). ntreruperile interne generate prin apeluri int se mai numesc ntreruperi
software.
11.2 Modul de funcionare a ntreruperilor
Un serviciu oferit de o ntrerupere nu este altceva dect un tip special de
subprogram. Subprogramele implicite pot fi nlocuite cu rutine construite de ctre
programator. Datorit faptului c aceste servicii nu sunt proceduri obinuite, cteva
msuri trebuiesc luate n cadrul lor:

517

salvarea tuturor regitrilor la nceputul rutinei


apelul instruciunii sti pentru procesarea altor ntreruperi n cadrul
serviciului
restaurarea regitrilor la sfritul rutinei
apelul iret ca ultim instruciune
Salvarea i restaurarea regitrilor folosii este necesar datorit incertitudinii
n ceea ce privete momentul n care au loc ntreruperile externe. Astfel,
ntreruperile de acest tip pot avea loc n orice moment, ntrerupnd execuia unui
bloc de instruciuni, iar modificarea fr restaurare a regitrilor folosii n acest bloc
duce la rezultate catastrofale pentru program. Pe de alt parte, ntreruperile
software au un control mai mare relativ la momentul lor de execuie i se pot
sustrage de la aceast regul.
Dac se dorete ca i alte ntreruperi s fie capabile de activare n timpul
execuie serviciului, ntrerupnd astfel execuia acestuia, se realizeaz apelul
instruciunii sti, care are ca efect setarea indicatorului de condiie IF (interruptenable flag). Dac nu se realizeaz acest apel, iar dac if nu este setat, ntreruperile
ce au loc n timpul rezolvrii ntreruperii curente, nu vor fi recunoscute de ctre
procesor. Pentru resetarea (punerea pe zero) a acestui flag se folosete instruciunea
cli. De remarcat, c aceste dou instruciuni, nu au nici un efect asupra
ntreruperilor interne, software sau generate de o condiie de eroare, ci numai
asupra acceptrii sau nu a ntreruperilor externe.
Familia de procesoare 8086 are doi pini de intrare de la dispozitivele
generatoare de ntreruperi:
pentru ntreruperi mascabile (Maskable Interrupts) INTR
pentru ntreruperi nemascabile (Nonmaskable Interrupts) NMI
Majoritatea dispozitivelor ce genereaz ntreruperi folosesc linia INTR
pentru semnalarea evenimentelor. Instruciunile cli i sti afecteaz ntreruperile
ce sosesc pe acest pin: cli realizeaz o mascare a ntreruperilor, prevenind
recunoaterea lor de ctre procesor, n timp ce sti permite intervenia acestora n
codul executat de ctre procesor. Nici una dintre aceste instruciuni nu are efect
asupra liniei NMI, pe care circul semnale importante, ce nu pot fi mascate, cum ar
fi cele ce declaneaz execuia codul n cazul cderii tensiunii. n cadrul arhitecturii
IMB PC originale, linia NMI era folosit pentru erorile de paritate a memorie
RAM, cauzate de defectarea unuia sau mai multor bii. Arhitecturile actuale ofer
multe alte servicii noi pentru situaii critice, fcnd programarea serviciilor NMI
complicat.
Dei linia NMI pare de neblocat n sarcina sa de a trimite semnale de
ntrerupere ctre procesor, ea poate fi totui blocat prin diferite trucuri ce difer de
la o arhitectur la alta. Astfel, pentru IBM XT, se poate masca i debloca aceast
linie prin scrierea valorii 00h (pentru mascare) i a valorii 080h (pentru deblocare)
pe portul 0A0h.

518

Pentru ntoarcerea n mod corect n programul ntrerupt, se va folosi


instruciunea iret n locul instruciunilor obinuite de revenire n aplicaie.
Aceast instruciune, pe lng sarcina de refacere a punctului de execuie (refacerea
din stiv a perechii CS:IP), realizeaz i sarcini suplimentare specifice
ntreruperilor, cum ar fi refacerea flagurilor IF i TF (trap flag). Pe lng cele doua
linii de transmitere a ntreruperilor mai sus amintite, arhitectura IBM vine n
ajutorul programatorilor cu un cip, numit Intel 8259 Programmable Interrupt
Controller (PIC), care servete pn la opt dispozitive ce genereaz ntreruperi.
Arhitecturile mai noi au n dotare i alte cipuri de tip PIC pentru mai multe
dispozitive. Pentru arhitecturile IBM AT cu dou cipuri PIC lista ntreruperilor
externe se prezint astfel:

Nivelul PIC
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
NMI

Numarul Intreruperi
08h
09h
0Ah
0Bh
0Ch
0Dh
0Eh
0Fh
070h
071h
072h
073h
074h
075h
076h
077h
02h

Tabel 11.1.
Dispozitiv
Timer (ceasul software)
Tastatura
Slave 8259
Portul serial secundar (COM2)
Protul serial primar (COM1)
Hard Disk (Fix)
Floppy Disk
Imprimanta pe port paralel
Ceasul hardware
Master 8259 Nivel 2
Coprocesorul numeric
Hard Disk (Fix)
Paritate Memorie

*datorita faptului c ntreruperile NMI sunt tot externe, aceasta linie


a fost inclusa in tabel dei nu este ataat controller-ului 8259

Prima coloana a tabelului anterior, nivelul PIC, arat prioritatea serviciului:


dac dou ntreruperi au loc simultan, cotroller-ul 8259 d prioritate celei cu acest
numr mai mic.
A doua coloan, numit numrul ntreruperii (tipul sau nivelul
ntreruperii), identific ISR-ul (serviciul) ce ruleaz la declanarea acesteia. Acesta
este un index folosit de procesor pentru determinarea adresei rutinei, n timp ce
nivelul PIC arat pinul din cadrul cipului 8259. Acest numr se regsete i n
cadrul ntreruperilor software, el fiind folosit n instruciunile int ca argument.

519

Prin intermediul numrul instruciunii, procesorul afl un pointer pe patru


baii, numit vectorul ntreruperii, care puncteaz rutina de tratare a ntreruperii. n
acest pointer, segmentul i deplasamentul, sunt memorate la adresa mai mica, cu
valori ntre 0000:0000 si 0000:30FF pentru arhitectura PC AT. n momentul n care
un semnal de ntrerupere este generat de unul de dispozitivele periferice, cipul 9259
activeaz linia INTR, ateptnd ncuviinarea procesorului pentru primirea
ntreruperii. La primirea ncuviinrii, procesorul primete numrul ntreruperii i l
folosete pentru aflarea adresei rutinei de tratare pe care o apeleaz.
n mod asemntor au loc operaiile pentru apelul rutinei de tratare a unei
ntreruperi interne ca urmare a unei instruciuni int sau ca urmare a unei condiii
de eroare. Att n cazul ntreruperilor externe, ct i n cel al celor interne,
procesorul realizeaz urmtoarele operaii cnd primete un numr de ntrerupere:
indicatorii de condiie sunt salvai pe stiv
indicatorii de condiie IF si TF sunt setai pe zero
regitrii IP i CS sunt salvai pe stiv
vectorul ntreruperii (adresa serviciului) este copiat n CS:IP
Odat cu iniializarea regitrilor CS:IP cu valoarea vectorului ntreruperii,
se trece la execuia rutinei aflat la acea adres. Programatorul poate modifica unul
sau mai muli vectori de ntreruperi i, astfel, s i introduc propriile rutine de
tratare. La terminarea unei rutine de tratare, se apeleaz instruciunea iret care
realizeaz urmtoarele operaii:
regitrii CS i IP sunt restaurai din stiv
indicatorii de condiie sunt refcui, de asemenea, din stiv
Prima operaie este operaia obinuit de refacere a adresei de revenire, pe
care i o instruciune obinuit de retur o realizeaz. Dup care urmeaz refacerea
indicatorilor de condiie. Se observ c indicatorii de condiie IF i TF sunt resetai,
la intrarea n rutin, dup ce au fost salvate mpreun cu celelalte flaguri. Astfel, pe
parcursul execuiei serviciului ele vor avea valoarea zero, nepermind ntreruperea
rutinei de alte ntreruperi (indicatorul de condiie IF) i nici suport de ntrerupere a
instruciunilor pentru debuggere (indicatorul de condiie TF trap flag). Pentru
permiterea ntreruperii temporare a serviciului (setarea indicatorului de condiie IF)
se apeleaz instruciunea sti.
11.3 Tipuri de ntreruperi
O prim clasificare a ntreruperilor este cea realizat n primul subcapitol:
externe i interne. ntreruperile se mai pot clasifica si dup locul pe care l ocup
rutinele de tratare implicite. Astfel, unele rutine de tratare se gsesc n BIOS, n
timp ce altele sunt oferite de sistemul de operare.
n cazul sistemului de operare MS-DOS, pe lng shell-ul, ce interpreteaz
comenzile, se gsesc doua straturi numite BDOS (Basic Disk Operating System) i
BIOS (Basic Input Output System). Pe disc acestea se gasesc n fiierele

520

MSDOS.SYS si IOSYS.SYS. Aceste straturi cuprind rutine de tratare a


ntreruperilor, primul oferind rutine din partea sistemului de operare, n timp ce al
doilea strat, BDOS, ofer o legtur spre ntreruperile oferite de BIOS. Astfel, o
alta clasificare a ntreruperilor, pentru MS-DOS, este:
ntreruperi BIOS
ntreruperi DOS
11.3.1 ntreruperi BIOS
Rolul BIOS-ul este acela de a aciona ca o interfa ntre software si
hardware, impunnd un standard ce trebuie respectat de toi manufacturierii de
calculatoare. O parte din rutinele BIOS, cum ar fi cele ce realizeaz testele de
verificare a resurselor hardware (POST Power On-Line Self Test) se gsesc n
memoria ROM, n timp ce partea de BIOS cuprins n fiierul IOSYS.SYS se
ncarc n partea inferioar a memorie RAM. Modul de mapare a memorie este
standardizat, existnd mai multe versiuni de BIOS: Award, Phoenix etc. Dac n
primele versiuni, BIOS-ul oferea ntreruperi cu numere cuprinse ntre 00h i 1Fh,
arhitecturile moderne ofer seturi extinse de ntreruperi, tabelul 11.2.
Numrul serviciilor oferite de BIOS este foarte mare, de aceea n tabel sau
omis multe dintre acestea. Dup cum se observ, unele dintre acestea ofer un mod
de ntrerupere a procesorului de ctre dispozitivele ataate la acesta, aa numitele
IRQ-uri (Interrupt Request), prezentate, n mare majoritate, n tabelul 11.1, n timp
ce altele ofer o modalitate de accesare a dispozitivelor de ctre programator prin
intermediul instruciunii int.
Modul de ntrebuinare a ntreruperilor de acces la dispozitive, este comun
att serviciilor BIOS ct i celor DOS. Pe lng numrul de ntrerupere, care indic
dispozitivul ce se vrea accesat, programatorul trebuie s specifice i funcia pe care
o dorete realizat. Aceasta se specific prin registrul ah (cteodat, n funcie de
serviciu i funcie, se folosete i AL, BX i DX), dup cum se observ n exemplu
urmtor:
;pozitionare cursor:
;pregatire parametrii
mov
ah, 02h
;functia 02h
mov
bh, 00h
;pagina video
mov
dh, 10
;linia
mov
dl, 12
;coloana
;apel intrerupere
int
10h
;serviciu video
;nu se intoarce nici un rezultat

Acest exemplu poziioneaz cursorul pe linia 10, coloana 12, pe prima pagina
video, apelnd funcia 02h a serviciului 10h. Modul de folosire al ntreruperilor

521

este acelai, ceea ce difer fiind doar modul de transmitere al parametrilor i de


primire a rezultatelor, acolo unde cazul.

Tabel 11.2
Numr ntrerupere
00h
01h
02h
03h
04h
05h
06h
07h
08h
09h
0Ah
0Bh
.....
10h
11h
12h
13h
14h
.....
40h
41h
43h
46h
4ah
67h
70h
.....
76h
77h

Semnificaie (serviciu)
Divizare la zero
Modul single-step (vezi flag tf)
Nemascabil (NMI)
Breakpoint
Depsire (overflow) (vezi flaguri of si ov)
Tiprire ecran
Cod de operaie nevalid
Nu exist coprocesor matematic
IRQ0 Timer
IRQ1 Tastatur
IRQ2 cascade (trecerea pe controllerul 2 de
ntreruperi)
IRQ3 COM 2/4
.....
Serviciul video
Lista echipamentelor
Mrimea memoriei convenionale
Disk I/O
Port serial
.....
Vector ctre funciile int 13h referitoare la
dischet
Vectori ctre structurile referitoare la hard
discuri
Tabela de caractere EGA si VGA
Vectori ctre structurile referitoare la hard
discuri
Alarm utilizator
Funcii ale managerului de memorie expandat
IRQ8 Real Time Clock
.....
IRQ14 hard disk
IRQ15 (rezervat)

11.3.2 ntreruperi DOS


ntreruperile oferite de stratul BDOS, oferind n special rutine de acces la
disc, fac invariant interfaa n raport cu diferitele particulariti hardware din

522

modelele de PC-uri oferite de fabricani. Dei mai puine la numr, ntreruperile


DOS ofer un mare numr de funcii, tabelul 11.3.
Tabel 11.3
Numr ntrerupere
20h*
21h
22h
23h
24h
25h/26h
27h*
28h
29h
2Eh
2Fh
31h
33h
67h

Semnificaie (serviciu)
Terminare program
Servicii DOS
Adresa de revenire din program dup terminarea
acestuia
Adresa de revenire dup terminare cu Control-Break
Adresa de revenire dup o eroare critic
Acces direct la disc
Terminare program cu rmnere rezindent n memorie
Procesor neocupat (idle)
Acces rapid la ecran
Executare comand DOS
Multiserviciu (DoubleSpace, spooler, control TSR, etc.)
Servicii DPMI (folosite sub modul Windows 386Enh)
Suport mouse
Servicii ale managerului de memorie expandat
(HIMEM.SYS)

*Aceste servicii sunt rmase de la versiunile iniiale de DOS, existnd


servicii DOS mai noi i mai uor de folosit care le nlocuiesc.

n continuare se prezint un exemplu de folosire a serviciului DOS 21h:


mov
mov
int

ah, 09h
dx, sir
21h

;functia de afisare sir


;in ds:dx se pune adresa sirului
;numarul serviciului

Secvena anterioar realizeaz afiarea unui sir terminat cu caracterul $ prin


apelul funciei 09h a serviciului 21h. Acest cod demonstreaz modul similar de
folosire al ntreruperilor att pentru stratul BIOS ct i pentru stratul DOS. Pentru
accesarea resurselor hardware n limbaj de asamblare exist trei niveluri de
programare:
la nivel DOS
la nivel BIOS
la nivel de baz.
Aceste modaliti au fost aezate n ordinea cresctoare a complexitii
programrii. Astfel, nivelul DOS ofer servicii de un nivel mai nalt dect nivelul
BIOS, n timp ce programarea la nivel de baz este cea mai grea folosind
instruciunile in i out de lucru cu porturi. Aceast modalitate de accesare a
resurselor necesit cunotine avansate si o documentaie pe msur, pe cnd n
programarea cu ntreruperi, cunoscnd modul general de utilizare al acestora,
programatorul trebuie doar s aib la dispoziie documentaia pentru fiecare funcie

523

referitoare la modul de transmitere al parametrilor i de preluare a rezultatelor. Cu


toate acestea, unele sarcini realizate cu ajutorul ntreruperilor necesit cunotine
profunde hardware, precum i folosirea concomitent cu instruciunile in i out,
dup cum se va observa n exemplu urmtor.
11.4 Exemplu de folosire al ntreruperilor
Folosirea ntreruperilor necesit cunotine despre efectele colaterale ale
acestora. Programatorul, n funcie de ntreruperea folosit, trebuie s tie
mecanismele ce se afl n spatele serviciului. Pentru a scrie un program care s nu
afecteze buna funcionare a sistemului, el trebuie s in cont att de buna
funcionare a propriului program, luat separat, ct i de funcionarea a celorlaltor
programe executate n paralel cu acesta, precum i a dispozitivelor periferice care
folosesc ntreruperi. Toate aceste probleme pe care le are de nfruntat un
programator nu au o forma general, ele sunt specifice fiecrui tip de ntrerupere,
neputndu-se pune un diagnostic concret unei erori date dect inndu-se cont de
ntreruperile folosite.
n continuare, pentru exemplificarea problemelor ce apar la folosirea unei
ntreruperi, se prezint un exemplu, devenit clasic, preluat din cartea Mastering
Turbo Assembler a lui Tom Swan, cunoscut autor de cri de programare. Acest
exemplu, relativ simplu la prima vedere, i propune s foloseasc ntreruperea IRQ
0h, cu numrul 08h (Timer), pentru executarea unui cod la intervale regulate de
timp. Acest cod nu face altceva dect s ncetineasc programul prin adugarea de
pauze mici, fiind folositor n cazul n care se dorete depanarea unui program care
se dovedete a fi prea rapid pentru observarea operaiilor pe care le realizeaz,
depanarea pas-cu-pas fiind o alternativ greoaie de folosit.
n toate calculatoarele compatibile IBM PC, exist un timer hardware, care
genereaz, la intervale egale de timp (de 18.2 ori pe secund), un semnal de
ntrerupere pe linia 0h ctre controllerul 8259, producnd o ntrerupere cu numrul
08h, de maxim prioritate. Serviciul cu acest numr are dou sarcini. Prima const
n incrementarea unei variabile pe 32 de bii, care indic numrul de cicluri ale
timerului de la pornirea calculatorului, folositoare pentru diferite funcii ce indic
timpul de rulare. A doua sarcin controleaz modul de funcionare al motorului
unitii de dischet. Aceast sarcin este datorat timpului necesar motoraului
pentru a ajunge la turaia necesar. Dac acesta ar fi oprit dup fiecare
citire/scriere, ntre aceste operaii exist timpi mori necesari rotorului pentru a
ajunge la turaia optim, lucru care ar duce la o ncetinire mare a operaiilor cu
discheta. Soluia a constat n meninerea n turaie a motoraului atta timp ct un
cronometru, controlat de ntreruperea 08h, nu ajunge la zero.
n scrierea unui program care folosete ntreruperea, trebuie inut cont de
aceste sarcini suplimentare. Codul programatorului, care este apelat la intervale
regulate de timp, nu trebuie s dureze mult. n cadrul acestuia nu trebuie s se

524

opreasc primirea ntreruperilor de ctre procesor (instruciunea cli) pentru mai


mult de 1/18,2 secunde, pentru a nu se afecta buna funcionare a unor componente
eseniale ale sistemului. Dup cum se observ, folosirea unei ntreruperi relativ
banale, ridic n mod neateptat, pentru necunosctori, probleme mari n
funcionarea unor periferice i a unor programe relativ independente.
Pe lng aceste doua sarcini, serviciul timer execut o ntrerupere software
cu numrul 01Ch (User timer interrupt), care d posibilitatea programatorului de a
executa codul su. Prin instalarea propriei rutine de tratare a ntreruperii 01Ch,
aceasta este apelat de aproximativ 18.2 ori pe secund. Regularitatea apelrii
acesteia nu este garantat. Dup cum s-a afirmat deja, ntreruperile nu pot s
ntrerup instruciunea curent. Dac aceasta necesit multe cicluri procesor,
executarea ntreruperii se amn nedorit de mult, astfel nct premisa executrii de
18.2 ori pe secund a codului s fie neadevrat.
n continuare se prezint codul programului surs, urmnd ca fiecare grup
de instruciuni s fie prezentat n amnunt:
;****************************************
%TITLE Exemplu de folosire a intreruperii 01Ch"
;****************************************
IDEAL
.MODEL
small
.STACK
256
delay
EQU
0010h ; pauza
BIOSData
EQU
040h ; adresa segmentului de
;date BIOS
LowTimer
EQU
006Ch ; valoarea timerului (partea mai
; putin semnificativa)
PIC8259
EQU
0020h ; adresa de port a
;cipului 8259 PIC
EOI
EQU
0020h
valuarea End of
;interrupt
DATASEG
codIesire
DB
0
timerSeg
DW
?
; adresa serviciului initial
timerOfs
DW
?
; Int 1Ch ISR
CODESEG
Start:
mov ax, @data
;initializare
mov ds, ax
;
mov es, ax
;
mov [word cs:difference],delay
push es
mov ax, 351Ch
; intrerupere 1C
int 21h
mov [timerSeg], es

registru
de date
es = ds
; stabilire pauza

;salvare registru es
;obtinerea vectorului de
; apel serviciu DOS
; salvare segment

525
mov [timerOfs], bx
; salvare offset
pop es
; restaurare es
push ds
; salvare registru ds
mov ax, 251Ch
; setarea serviciului 1C
push cs
; ds = cs
pop ds
mov dx, offset Incetinire ; adresa de inlocuire
int 21h
; setare adresa
pop ds
; restaurare ds
@@10:
call KeyWaiting
jz @@10
push ds
mov ax, 251Ch
mov dx, [timerOfs]
initiala
mov ds, [timerSeg]
int 21h
pop ds
Exit:
mov ah, 04Ch
mov al, [codIesire]
int 21h

; asteptare apasare tasta


; salvare ds
; setare vector 1C
;adresa
de
segment
;offset-ul initial
; restaurare serviciu initial
; restaurare ds

;****************************************
; Incetinire - Procedura apelata de aprox. 18,2/sec
; ****************************************
inProgress DB
0
; flag
difference DW
0
; timpul de incetinire
PROC

Incetinire

;testare flag inProgress pentru a vedea daca o copie


;anterioara a procedurii ruleaza
cmp [byte cs:inProgress], 0
; verificare
jne @@99
;
ruleaza,
terminare
; procedura
inc [byte cs:inProgress]
; nu ruleaza,
; incrementare flag
sti
push ax

;
;
;
;

pot sa aiba loc alte


intreruperi
salvare registrii
folositi

push ds
push dx
mov al, EOI
out PIC8259, al

; al = end-of-interrupt

526
mov
mov
mov
@@10:
mov

ax, BIOSData
ds, ax
ax, [word LowTimer]

; adresa de date BIOS


; folosire ds
; valuare timer

dx, [word LowTimer]

; incarcare valoare
; timer in dx
; scadere valoare
; noua - veche
; comparare cu
; pauza
; cicleaza pana la
; depasire
; dezactivare intreruperi
; in timpul restaurarii
; flag pe zero

sub dx, ax
cmp dx, [cs:difference]
jb @@10
cli

dec [byte cs:inProgress]


pop dx ; restaurare registri
pop ds
pop ax
@@99:
iret
; retur intrerupere
ENDP Incetinire
PROC

KeyWaiting
push ax
mov ah, 1
int 16h

pop ax
ret
ENDP
KeyWaiting
END

Start

;
;
;
;
;
;
;

salvare ax
functia de
verificare buffer
serviciu tastatura
BIOS
restaurare ax
retur

; sfarsit program

La rularea programului se instaleaz procedura Incetinire ca serviciu al


ntreruperii 1Ch, urmnd ca, la apsarea unei taste, programul s se termine.
Listing-ul ncepe prin definirea unor simboluri. Pe lng definirea pauzei (delay),
se definesc o serie de simboluri, care presupun cunoaterea modului de mapare al
variabilelor BIOS n memoria RAM. Astfel, adresa 40h semnific nceputul zonei
de mapare BIOS, pe cnd 40h::6Ch este locaia de memorie unde valoarea curent
a timerului se afl. Urmeaz segmentul de date, cu definirea unor variabile ce vor fi
folosite pentru reinerea adresei vechii rutine de tratare a ntreruperii 1Ch
(timerSeg: timerOfs).
Dup liniile de nceput a segmentului de cod, urmeaz obinerea rutinei de
tratare a ntreruperii 1Ch. Se folosete ntreruperea DOS 21h (int 21h), funcia 35
(registrul ah = 35, registrul al = 1Ch). Vectorul obinut se salveaz n
timerSeg:timerOfs. Urmeaz setarea ca serviciu a rutinei Incetinere prin funcia 25
a ntreruperii 21h. Dup stabilirea noului serviciu, se trece la executarea unei bucle
din a crei repetare se iese prin apsarea unei taste. Pe parcursul acesteia, dei

527

aparent nimic nu se ntmpl, procedura Incetinere este apelat n mod repetat de


ctre serviciul ntreruperii 08h (timer). La ieirea din ciclu, se reface vechea rutin
de tratare a ntreruperii 1Ch. Acest lucru este necesar, deoarece, odat cu terminare
programului, adresa, spre care Incetinire puncta, devine invalid, iar apelul realizat
la aceast adres de ctre serviciul timer duce, inevitabil, la o cdere de sistem.
Se trece acum la rutina de tratare a ntreruperii, Incetinire. Deoarece aceast
rutin poate fi apelat n orice moment, ntre dou apeluri de instruciuni din
programul principal, n timpul unui apel ctre sistemul de operare, sau n timpul
unei alte ntreruperi, valoarea segmentelor ES i DS nu puncteaz ntotdeauna ctre
segmentele de date. Pentru accesarea unor variabile din cadrul segmentelor de date,
trebuie s fim siguri c aceste registre identific n mod corect aceste segmente. O
soluie este executarea unei secvene de cod care n mod uzual se gsete la
nceputul programului principal:
push
mov
mov
. . .

ds
ax, @data
ds, ax
. .

urmat, la sfritul ntreruperii, de refacerea segmentului ds:


. . . . .
pop
ds
iret

O alt soluie, mai elegant i mai simpl, este declararea variabilelor n


cadru segmentului de cod. Acest lucru se realizeaz n procedura Incetinire prin:
inProgress
difference

DB
DW

0
0

; flag
; timpul de incetinire

Pentru accesarea variabilelor se indic n mod explicit folosirea registrului


CS, ca n cazul instruciunii:
cmp

[byte cs:inProgress], 0

Dac nu se specific registrul CS, asamblorul consider ca registru segment


registrul DS, iar adresa de memorie accesat, n cel mai bun caz, dac este valid,
nu este cea dorit.
Dup cum artat deja, ntreruperea 08h joac un rol important n
funcionarea unui sistem de calcul. Rutina apelat de timer nu trebuie s dureze
mult, iar pe parcursul acesteia celelalte ntreruperi nu trebuiesc blocate. Aceast
situaie face posibil apariia apelului rutinei Incetinire chiar n timpul rulrii
acesteia. Nimic nu mpiedic procesorul s primeasc nc o ntrerupere 1Ch din

528

partea timerului n timpul execuiei procedurii Incetinire, dac aceasta dureaz prea
mult. Astfel, acest rutin devine reentrant. Din pcate scrierea unei funcii
reentrante ridic probleme sulpimentare, chiar rutinele din cadrul BIOS-ului si
DOS-ului nefiind reentrante. Posibilitatea reapelrii procedurii Incetinire poate s
duc la depirea stivei dac procedura dureaz prea mult, iar lanul de reapelrii
continu fr oprire. Mai mult, folosirea unor variabile globale face ca execuia s
ia o ntorstur neprevzut, o singur instan a acestora fiind folosit la toate
apelurile. Dup cum se observ folosirea variabilei difference, face imposibil
folosirea rutinei Incetinire n mod reentrant. Soluia la aceast problem (soluie pe
care o folosesc i unele funcii BIOS/DOS, cum ar fi Print Screen) este folosirea
unui flag (n cazul de mai sus inProgress), care s indice dac o instan a rutinei
este deja apelat:
cmp

[byte cs:inProgress], 0

Dac inProgress este mai mare ca zero, instana curent a aprut ca urmare
a blocrii altui apel al rutinei, i se sare la sfritul procedurii. Dac este zero,
instana curent este singura apelat n acest moment i se poate continua execuia
ei. Urmeaz incrementarea flagului pentru indicarea acestui lucru.
Dup luarea acestor msuri, urmeaz altele: permiterea altor ntreruperi (sti)
i salvarea regitrilor folosii n stiv. Dei, la prima vedere, instruciunea sti pare
suficient pentru activarea ntreruperilor, datorit faptului c ntreruperile timerului
sosesc prin intermediul cipului 8259, acest lucru nu este adevrat. Dei
instruciunea sti seteaz flagul if, permind indicarea ctre procesor a semnalelor
de ntrerupere, primirea de ctre acesta a ntreruperilor necesit trimiterea ctre
portul 8259 (cu valoarea 20h) a unei comenzi end-of-interrupt (EOI):
PIC8259
EOI

EQU
EQU
. . . .
mov
out
. . . .

0020h ; adresa de port a cipului 8259 PIC


0020h ; valuarea End of interrupt
. .
al, EOI
; al = end-of-interrupt
PIC8259, al
. .

Urmeaz citirea valorii curente a timerului i folosirea acesteia n cadrul


unei bucle pan la depirea pauzei (variabila difference cu valoarea luat din
delay). Dei la o simpl privire pare c variabila punctat de adresa LowTimer are o
valoarea constant, ea este actualizat automat de ctre serviciul timer, iar simpla
recitire a acesteia preia o valoare actualizat.
Ultima parte a procedurii conine o restaurare a regitrilor folosii, precum
i o resetare a flagului inProgress, precedate de o mascare necesar a ntreruperilor
(instruciunea cli). O atenie deosebit trebuie avut n vedere n legtur cu
variabilele salvate pe stiv atunci cnd se scrie o rutin de tratare a unei ntreruperi.
Singurul registru de segment cu valoare corect pe tot parcursul execuiei rutinei

529

este CS, n timp ce ES, DS i SS au valori incerte, n funcie de codul n curs de


execui nainte de ntrerupere. n exemplul anterior se salveaz trei regitri n stiv.
Dar, n care stiv? n stiva proprie DOS-ului, n stiva programului principal sau n
stiva local altei rutine de tratare a unei ntreruperi? Este aceast stiv suficient de
mare? De obicei, se consider sigur salvarea unei mici cantiti de date ntr-o
astfel de stiv necunoscut. Referine de programare prevd rezervarea pentru
spaiul de stiv a unei memorii mai mari dect strictul necesar, deci presupunnd ca
exist spaiu de salvare pentru aceti regitrii pare rezonabil. Totui, rutine, care
necesit salvri mari de date pe stiv, trebuie s apeleze la o stiv local. De fiecare
dat cnd se schimb segmentul de stiv, trebuie inut cont de particularitile
specifice procesoarelor din familia 8086. Astfel, 8086 dezactiveaz n mod
temporar ntreruperile pentru urmtoarea instruciune de fiecare dat cnd se
asociaz nou valoare unui registru segment. Deci, n secvena de cod:
mov
mov
mov

ax, offset segmStiva


ss, ax
sp, offset sfarsitStiva

ntreruperile nu pot opri execuia codului ntre instruciunile mov ss, ax i mov
sp, offset sfarsitStiva. Dac acest lucru nu s-ar realiza n mod automat, iar o
ntrerupere ar avea loc chiar ntre cele doua instruciuni, codul de tratare apelat va
folosi vechea valoare a deplasamentului mpreun cu noua valoare a segmentului
de stiva, o situaie cu urmri catastrofale. Prin urmare, pentru folosirea acestei
metode de protecie, orice modificare a unui segment, trebuie urmat de
actualizarea deplasamentului.
Pentru o rutin de tratare a unei ntreruperi, declararea unui segment de
stiv local de 512 baii face astfel:
ALIGN
stivaLocala DB
sfarsitStiva

512 dub (0)


=
$

unde directiva ALIGN este necesar pentru alinierea stivei la un multiplu de cuvnt
procesor. Se declar, apoi, o serie de variabile pentru reinerea vechilor regitri:
ssVechi
spVechi
axVechi

DW
DW
DW

0
0
0

n cadrul rutinei se salveaz vechile valori ale regitrilor i se stabilete


noua stiv:
mov
mov
mov

[cs:ssVechi], ss
[cs:spVechi], ss
[cs:axVechi], ax

530
mov
mov
mov

ax, cs
ss, ax
sp, offset sfarsitStiva

Urmnd ca la terminarea rutinei s se revin la vechile valori:


mov
mov
mov

ss, [cs:ssVechi]
sp, [cs:spVechi]
ax, [cs:axVechi]

;aceasta este ordinea de setare


;a registrilor segment:offset !!!

Dup cum se observ, o sarcin aparent simpl, cum este cea de folosire a
timer-ului, necesit cunoaterea profund a implicaiilor pe care le implic
utilizarea ntreruperilor, nerespectarea regulilor mai sus amintite ducnd inevitabil
la terminarea anormal a programului sau, chiar, la o cdere de sistem.
11. 5 Concluzii
Folosirea ntreruperilor nu este o sarcin uoar. De multe ori soluia cea
mai simpl este folosirea unui limbaj de nivel nalt. Dar, de i mai multe ori, ceea
ce ofer aceste limbaje, referitor la folosirea direct a hardware-ului, nu este de
ajuns. Prin urmare, folosirea limbajului de asamblare i a ntreruperilor devine
inevitabil. Sistemele de operare noi (Windows NT, Windows 2000) nu permit
accesarea direct de hardware, oferind soluii de nivel nalt pentru accesarea
acestuia. Totui, scrierea de programe specifice i dedicate unor sarcini precis
determinate, cum este scrierea unor drivere, accesarea unor echipamente noi,
necesit realizarea unui cod care s ruleze n mod nucleu i care s acceseze
resursele direct. Astfel, programarea cu ntreruperi i pstreaz actualitatea.

531

12
MACRODEFINIII
12.1 Structura macrodefiniiei
Macrodefiniia este o secven de program scris n limbaj de asamblare care
corespunde unei prelucrri cu caracter repetat.
Se construiesc macrodefiniii pentru prelucrri precum:
mprirea a dou numere cu obinerea ctului i restului precum i a
unei informaii asupra modului n care s-a efectuat mprirea (de
exemplu mpritor zero);
preluarea unui caracter sau a unui ir de la tastatur;
afiarea unui caracter sau a unui ir pe ecranul monitorului;
diverse operaii de formatare a ecranului, ca de exemplu tergerea
ecranului, poziionarea cursorului;
operaii cu fiiere: deschiderea, crearea, citirea, tergerea, nchiderea
fiierelor, poziionarea cursorului;
aflarea minimului sau maximului dintre elementele unui vector sau a
unei matrice.
Pentru a construi o macrodefiniie se impune:
definirea datelor de intrare;
specificarea schemei logice de prelucrare a datelor de intrare;
definirea rezultatelor.
Se constituie lista de parametri finali format din:
parametrii care corespund datelor de intrare;
parametrii n care se vor gsi rezultatele;
parametrii n care se regsesc informaii privind modul n care s-au
efectuat prelucrrile.
Macrodefiniia pentru adunarea a dou matrice conine lista de parametrii
formali format din:
numele primei matrice (de fapt adresa zonei unde este memorat
matricea);
numele celei de-a dou matrice;
numrul de linii al matricelor;
numrul de coloane;
numele matricei de rezultat;

532

variabila boolean care are valoarea zero Dac prelucrarea s-a efectuat
corect, respectiv unu n caz contrar.
Parametrii p1, p2, .. pn sunt descrii n prima linie surs a macrodefiniiei,
n care se mai specifica numele macrodefiniiei, cuvntul cheie MACRO, linie cu
structura:
nume_macrodefinitie

macro [ lista de parametrii ]

Macrodefiniia conine definiri de etichete cu caracter local, precum i


variabile de lucru. Se mai definesc:
instruciunile de salvare a regitrilor;
instruciunile de prelucrare specifice operaiei;
instruciunile de restaurare a regitrilor;
Delimitatorul de sfrit al macrodefiniiilor este cuvntul cheie ENDM.
Numele macrodefiniiilor trebuie s fie ales n aa fel nct s permit
identificarea cu uurin a acestora. Pentru mprirea a dou numere, antetul
macrodefiniie arat n felul urmtor:
divide

macro

deimpartit, impartit, cat, rest, stare

Pentru adunarea a dou numere a, b cu obinerea rezultatului n s, prima


linie a macrodefiniiei va fi:sal
aduna

macro

a, b, s, stare

Pentru salvarea tuturor regitrilor, se poate construi o macrodefiniie avnd


prima linie
salvreg

macro

n acest caz absena parametrilor se impune pentru c regitrii sunt


cunoscui.
Cnd se construiete o macrodefiniie se are n vedere obinerea unui grad
de generalitate foarte mare. De asemenea, este necesar ca parametrilor de intrare s
nu li se modifice valorile, regitrii s fie salvai, respectiv restaurai pentru a nu
influena celelalte operaii din afara secvenei care definete macrodefiniia.
De exemplu, pentru efectuarea adunrii numerelor a, b se construiete
macrodefiniia:
aduna macro a, b, s
push ax
mov ax, a
add
ax, b

533
mov s,
pop ax
endm

ax

12.2 Macroapelul i macroexpandarea


Dac procedurile se apeleaz prin instruciunea call,
macrodefiniiilor se efectueaz prin nume.
Macroapelul macrodefiniiei avnd prima linie de definire:
nume_macro macro

referirea

pf1, pf2, .. pfn

se face prin linia sursa:


nume_macro

pr1, pr2, .. prn

unde:
nume_macro numele macrodefiniiei
pfi parametrul formal i
pri parametrul real i
Dac se consider macrodefiniia aduna, definit anterior n subcapitolul
12.1 i expresia:
e = a + b + c + d

se fac macroapelurile:
aduna a, b, e
aduna e, c, e
aduna e, d, e

n cazul apelului de proceduri prin instruciunea call se efectueaz salturi


necondiionate spre secvene de program. n cazul macroapelului intr-o etap a
asamblrii programului are loc generarea de secvene de instruciuni
corespunztoare macrodefiniiei. Se nlocuiesc parametri formali cu parametri reali.
Programul astfel asamblat are o lungime mai mare dect programul iniial.
Se considera macrodefiniia:
aduna3 macro term1, term2, term3, rez
push ax
mov ax, term1
add ax, term2
add ax, term3
mov rez, ax
pop ax

534
endm

Programul principal arat n felul urmtor:


..
mov a,
mov b,
mov c,
mov x,
mov y,
mov z,
aduna3
aduna3
aduna3
..

1
3
7
13
2
32
a, b, c, rez1
x, y, z, rez2
0, rez1, rez2, e

ntr-o etap de asamblare are loc macroexpandarea. Aceast operaie const


n nlocuirea liniei surs de macroapel cu instruciunile actualizate ale
macrodefiniiei.
Actualizarea const n nlocuirea parametrilor formali cu parametri reali.
Programul principal dup macroexpandare este:
...
mov a, 1
mov b, 3
mov c, 7
mov x, 13
mov y, 2
mov z, 32
push ax
mov ax, a
add ax, b
add ax, c
mov rez1, ax
pop ax
push ax
mov ax, x
add ax, y
add ax, z
mov rez2, ax
pop ax
push ax
mov ax, 0
add ax, rez1
add ax, rez2
mov e, ax
pop ax
..

535

Textul surs obinut este mai lung avnd un numr de instruciuni mai mare
dect textul iniial. Dac programul asamblor este nzestrat cu componente de
optimizare, atunci se obine eliminarea din programul macroexpandat a secvenelor
de instruciuni
pop ax
push ax

prima anulnd efectul celeilalte. Dezavantajul principal const n creterea lungimii


programului prin includerea de secvene repetate care difer numai prin numele
unor variabile. Este rezultatul nlocuirii parametrilor formali, cu parametri reali.
12.3 Etichete locale
Macrodefiniiile conin instruciuni de salt condiionat, de salt necondiionat
si instruciuni pentru implementarea structurilor repetitive. Aceste instruciuni
presupun definirea si referirea de etichete.
Pentru a elimina ambiguitile dup efectuarea macroexpandrii se
consider soluia care presupune parcurgerea urmtorilor pai:
etichete utilizate n corpul macrodefiniiei se definesc cu atributul LOCAL;
la prima macroexpandare numelui etichetei i se asociaz un numr format
din patru cifre compus intre 0000 si 9999; se obine numele extins al
etichetei;
referirile etichetelor n instruciunile de salt si de ciclare se efectueaz cu
numele extins al etichetei.
Macrodefiniia de alegere a elementului minim dintre trei numere are textul
surs:
minim

macro a, b, c, min
local et1, et2
push ax
mov ax, a
cmp ax, b
jlz et1
mov ax, b

et1:
cmp ax, c
jlz et2
mov ax, c
et2:
mov min, ax
pop ax
endm

Programul principal:

536
...
minim
minim
minim
minim
...

x, y,
w, v,
i, j,
min1,

z, min1
u, min2
k, min3
min2, min3, min

determin minimul dintr-un ir format din nou elemente. Dup macroexpandare,


secvena de program va arta astfel:
...
push ax
mov ax, x
cmp ax, y
jlz et10000
mov ax, y
et10000:
cmp ax, z
jlz et20000
mov ax, z
et20000:
mov min1, ax
pop ax
push ax
mov ax, w
cmp ax, v
jlz et10001
mov ax, v
et10001:
cmp ax, u
jlz et20001
mov ax, u
et20001:
mov min2, ax
pop ax
push ax
mov ax, i
cmp ax, j
jlz et10002
mov ax, j
et10002:
cmp ax, k
jlz et20002
mov ax, k
et20002:
mov min3, ax
pop ax
push ax
mov ax, min1
cmp ax, min2

537
jlz et10003
mov ax, min2
et10003:
cmp ax, min3
jlz et20003
mov ax, min3
et20003:
mov min, ax
pop ax
...

Cele patru cifre ataate etichetei locale limiteaz macroapelurile la cel mult
10000 ntr-un program.
12.4 Variabile locale
Variabilele locale sunt variabile care sunt cunoscute doar n blocul n care
au fost definite. Se pune problema zonelor de memorie, n care s fie alocate aceste
variabile locale:
segmentul de date global
segmentul de date propriu
stiva
n primul caz se profit de faptul c directivele simplificate de definire a
datelor (.date) i a codului (.code) pot alterna n cadrul programului. Variabilele
locale sunt mai nti definite cu directiva LOCAL, pentru a nu fi duplicate n apeluri
succesive, apoi declarate n cadrul segmentului de date .data.
Astfel se definete o constant local, care poate fi aplicat diferitelor date
transmise ca parametri. Fie aceasta constant
masca

equ

00001111b.

Dac se pune n relaie cu o variabil (definit pe un octet), prin operatorul


and, biii cei mai semnificativi ai rezultatului vor avea valoarea 0, iar biii mai
puin semnificativi vor fi asemntori primilor patru bii ai variabilei .
mask

macro x
local masca
.data
masca equ 00001111b
.code
push ax
mov al, x
and
al, masca
mov x, al
pop ax
endm

538

n cazul al doilea se creeaz segmente de date proprii cu ajutorul directivei


SEGMENT, cea ce previne gruparea acestui segment cu alte segmente.
n cazul memorrii variabilelor n stiv, trebuie s se parcurg urmtorii
pai:
se salveaz registrul BP n stiv;
se decrementeaz registrul SP cu numrul necesar de octei pentru
variabilele locale;
se copiaz SP n BP;
se salveaz ceilali regitri folosii n program;
se acceseaz variabilele locale conform ablonului stivei.
La terminarea macroapelului trebuie avut vedere:
restaurarea regitrilor;
incrementarea registrului SP cu acelai numr de octei cu care a fost
decrementat la nceput;
refacerea registrului BP.
Fie variabilele a,b,c,d,e,f definite pe un octet. Se calculeaz expresia:
( a*b ) ( c*d ) + ( e*f )
Se salveaz n stiva registrul BP, rezervm loc n stiva variabilelor var_1 si
var_2, decrementnd SP cu patru. ablonul variabilelor locale arat n felul
urmtor:
ablon struc
var_1 dw
var_2 dw
ablon ends

?
?

Imaginea stivei, figura 12.1.


var_1
var_2
BP
Figura 12.1 Coninutul stivei
Se calculeaz mai nti e*f, iar rezultatul este depus n var_1 (accesul se
face prin [bp].var_1 ). Rezultatul c*d este depus n var_2 ( acces prin [bp].var_2 ).

539

Dup ce se face nmulirea dintre a si b, se scade din ax var_2, dup care se adun
la ax var_1.
calc

macro a, b, c, d, e, f, rez
push bp
sub sp,4
mov bp,sp
push ax
xor ax,ax
mov al, e
mul f ;;s-a presupus nmulire fr semn
mov [bp].var_1, ax
xor ax, ax
mov al, c
mul d
mov [bp].var_2, ax
xor ax, ax
mov al, a
mul b
sub ax, [bp].var_2
add ax, [bp].var_1
mov rez, ax
pop ax
add sp, 4
pop bp
endm

12.5 Macrodefiniii derivate


Se consider macrodefiniii derivate m1, m2, .. mk care formeaz mulimea
M a macrodefiniiilor de baz, ce realizeaz funcii elementare. Macrodefiniii
derivate conin macroapeluri ale elementelor din mulimea M.
Macrodefiniia pentru adunarea a patru numere se construiete astfel:
aduna4 macro a1, a2, a3, a4, s
push ax
mov ax, a1
add ax, a2
add ax, a3
add ax, a4
mov s, ax
pop ax
endm

Dac n mulimea M a macrodefiniiilor de baz este definit macrodefiniia


pentru adunarea a dou elemente:
aduna2 macro
push ax

a1, a2, sum

540
mov ax, a1
add ax, a2
mov sum, ax
pop ax
endm

Pentru adunarea a patru numere se construiete macrodefiniia derivat:


aduna4 macro a1, a2, a3, a4, s
aduna2 a1, a2, s
aduna2 s, a3, s
aduna2 s, a4, s
endm

sau se apeleaz la variabile locale:


aduna4 macro a1, a2, a3, a4, s
local t1,t2
.data
t1 dw ?
t2
dw
?
.code
aduna2 a1, a2, t1
aduna2 a3, a4, t2
aduna2 t1, t2, s
endm

12.6 Macrodefiniii recursive


Macrodefiniiile se pot autoapela. Un aspect important este oprirea
recursivitii. O modalitate pentru aceasta este controlul parametrilor actuali prin
directivele IFNB ( If Not Blank ) si IFB ( If Blank ) care testeaz existenta sau nonexistena unui parametru actual.
pushreg macro r1, r2, r3, r4, r5, r6
ifnb <r1>
push r1
pushreg r2, r3, r4, r5, r6
endif
endm

Dac primul parametru nu este vid, macrodefiniia se autoapeleaz, cu


restul de parametri.

541

12.7 Redefinirea macrodefiniiilor


Asamblorul MASM permite redefinirea macroapelurilor. Se consider
macrodefiniia aduna4. Dac se folosete redefinirea, se ajunge la macroapelul:
aduna4 macro a1, a2, a3, a4, s
local t1,t2
.data
t1 dw ?
t2
dw
?
.code
aduna2 a1, a2, t1
aduna2 a3, a4, t2
aduna2 t1, t2, s
aduna4 macro a1, a2, a3, a4, s
aduna2 a1, a2, t1
aduna2 a3, a4, t2
aduna2 t1, t2, s
endm
endm

Se observ c o macrodefiniie s-a redefinit n corpul celeilalte. La primul


apel, macrodefiniia va aloca spaiu pentru celelalte date, apoi se redefinete, astfel
nct nu va ncerca s realoce datele la apelurile ulterioare. Cu instruciunea
PURGE se terge macroapelul naintea redefinirii ei.
12.8 Macrodefiniii uzuale
Pentru nmulirea unui numr cu 10 este folosit macrodefiniia imul10.
Macrodefiniia este apelat cu doi parametrii, unul surs i unul destinaie, operaia
efectuat fiind:
destinaie surs * 10.

Tipul parametrilor este ntreg pe 16 bii.


Se vor folosi n corpul macrodefiniiei deplasrile pe bii, care sunt mult
mai rapide dect nmulirea propriu-zis.
Regitrii folosii vor fi salvai pe stiv i restaurai dup execuia rutinei.
; implementarea macrodefiniiei pentru nmulirea
imul10 macro dst,src
push ax
; salvarea regitrilor folosii
push bx
mov ax,src ; ax va conine sursa operaiei
sal ax,1
; axax*2
mov bx,ax
; axax
sal ax,1
; axax*2

542
sal ax,1

;
;
add ax,bx
;
mov dest,ax ;
pop bx
;
pop ax

axax*2
avem ax=src*8 i bx=src*2
ax src*10
dstax
refacerea regitrilor folosii

endm

Dup cum se observ, macrodefiniia poate fi folosit cu succes pentru


operanzi care se gsesc n memorie sau regitri care sunt diferii n general de AX
i BX. Dac de exemplu destinaia este BX, acesta nu va fi modificat de rutin,
pentru c este salvat la nceput i restaurat apoi. Pentru a fi mai clar, AX i BX pot
fi surse dar nu pot fi destinaii ale operaiei de mai sus.
Pentru extragerea bitului de pe poziia k se folosete macrodefiniia xbit.
Aceast macrodefiniie va extrage bitul de pe poziia k a sursei n indicatorul de
zero (ZF) lsnd de asemenea n ax sursa din care s-au mascat toi biii mai puin
cel cutat.
Operaia se face prin generarea unei mti care se aplic apoi prin I bit cu
bit. Masca este generat prin deplasri succesive la stnga a unui cuvnt care iniia
avea valoarea 1.
Poziia corespunde numrului bitului, adic 0 pentru bitul 0,1 pentru bitul 1
etc.
; implementarea macrodefiniie de extragere a bitului
xbit macro src,k
push bx
; salvarea regitrilor
push cx
mov bx,src ; bxsursa
mov cl,k
; cxnumrul bitului
mov ax,1
; se creaz masca
shl ax,cl
; ax=1 shl k
and ax,bx
; se aplic masca asupra cuvntului
pop bx
; se refac regitrii
pop cx
; rezultatul este n ax i cx
endm

Meniunile referitoare la parametrii de apel de la precedenta macrodefiniie


se aplic i aici, n sensul c avem restricia c BX nu poate conine valoarea k.
Valoarea k i sursa pot fi date i ca valori imediate.
Pentru ridicarea la puterea a treia se folosete macrodefiniia pow3.
Ridicarea la puterea a 3-a se va face prin dou nmuliri.
Operanzi ntregi pe 16 bii cu semn.
; implementarea macrodefiniiei de ridicare la puterea a 3-a
pow3 macro dst,src
push ax
; salvarea regitrilor

543
push bx
mov ax,src
mov bx,ax
imul ax,bx
imul ax,bx
mov dst,ax
pop bx
pop ax

;
;
;
;
;
;

axsrc
bxax (bcsrc)
axax*bx (ax=src^2)
axax*bx (ax=src^3)
dstax
refacerea regitrilor

endm

Sursa poate fi valoare imediat, registru sau zon de memorie, iar destinaia
poate fi registru sau memorie, dar nu poate fi AX sau BX (care vor avea valorile
dinainte de intrarea n blocul respectiv).
mpririi a dou numere i corespunde macrdefiniia xdiv. Aceast
macrodefiniie ca avea patru parametrii:
x - demprit
(surs)
y - mpritor
(surs)
c - ct
(destinaie)
r - rest
(destinaie)
k - test
(destinaie)
Parametrul test va conine dup apelul macrodefiniiei 0 dac mprirea se
putea efectua (mpritorul diferit de 0) i 1 dac mpritorul este 0 (mprirea ar fi
invalid).
; Implementarea macrodefiniiei x/y c,r
xdiv macro x,y,c,r,k
local xdiv_1,xdiv_2
push cx
; salveaz cx
mov cx,y
; cx y
test cx,cx ; test dac bx=0
jnz xdiv_1 ; dac nu atunci se continu
inc cx
; dac da atunci k 1 (eroare)
mov k,cx
jmp xdiv_2 ; salt la sfrit
xdiv_1:
push dx
; salveaz dx
push ax
; salveaz ax
mov ax,x
; ax x
cwd
;axdx,ax(extensia de semn de la 16 la 32
bii)
idiv cx
; mprirea (axct, dxrest)
mov c,ax
; c ax (ctul)
mov r,dx
; r dx (restul)
xor dx,dx
; k 0 (totul e OK)
mov k,dx
pop ax
; refacerea regitrilor
pop dx

544
xdiv_2:
pop cx
endm

; refacerea lui cx

Se va analiza n cele ce urmeaz gradul de generalitate a definiiei,


parcurgnd codul acesteia.
Operanzii surs pot fi imediai sau prin adresare direct i indirect, iar cei
destinaie pot fi adresai direct sau indirect fr limitri. n cazul n care se transmit
ca parametrii regitri apar unele restricii.
Instruciunea:
mov cx,y

face ca registrul CX s nu poat fi parametrul x.


Instruciunea:
mov c,ax

face ca registrul DX s nu poat fi parametrul c (el este accesat mai trziu).


Instruciunile:
pop reg

de la sfrit determin ca regitrii AX, CX, DX s nu poat fi folosii pentru


operanzii destinaie (ct, rest, eroare) ai macrodefiniiei, ei recptnd valorile
dinaintea apelului.
Deci restriciile sunt:
CX nu poate fi dempritul (parametrul x);
AX, CX, DX nu pot fi ctul, restul sau parametrul de test (c, r, k).
S-au definit cele dou etichete ca local pentru c avem de-a face cu o
macrodefiniie i orice expandare a acesteia n program va genera noi definiri ale
acestor etichete. Directiva local specific asamblorului c referirile la acestea se
vor face ct ine corpul macroinstruciunii.
Macrodefiniia pentru iniializarea cu 0 a regitrilor de lucru este:
Setzeroall
xor
xor
xor
xor
xor
xor
endm

ax,
bx,
cx,
dx,
si,
di,

Macro
ax
bx
cx
dx
si
di

545

Macrodefiniia care evalueaz expresia din limbajul C


a1=a2=a3=a4=a5=0

sau expresia din limbajul COBOL


move

to

a1 a2 a3 a4 a5

este :
Setzero
macro a1, a2, a3, a4, a5
mov a1, 0
mov a2, 0
mov a3, 0
mov a4, 0
mov a5, 0
endm

Macrodefiniia care iniializeaz cmpurile a1, a2, a3, a4, a5 definite pe


un bait cu o valoare dat, val, este:
Setval
macro a1, a2, a3, a4, a5, val
push ax
mov ax, word ptr val
mov a1, ax
mov a2, ax
mov a3, ax
mov a4, ax
mov a5, ax
pop ax
endm

Macrodefiniia care interschimb coninutul a dou zone de memorie a i b


definite pe un octet este:
Swap1

macro a, b
push ax
mov al, a
mov ah, b
mov b, al
mov a, ah
pop ax

endm

Macrodefiniia care interschimb coninutul a dou zone de memorie


definite pe cte doi octei (un cuvnt) este:

546
Swap2

macro a, b
push ax
push bx
mov ax, a
mov bx, b
mov b, ax
mov a, bx
pop bx
pop ax

endm

Macrodefiniia care iniializeaz o zon de memorie definit pe un cuvnt


cu coninutul altei zone de memorie definite tot pe un cuvnt este:
Setmem
macro dest, sursa
push ax
mov ax, ds:[sursa]
mov ds:[dest], ax
pop ax
endm

Macrodefiniia Strcmp compar dou iruri s1, de lungime l1, si s2, de


lungime l2. Registrul AX conine deplasamentul primului ir, registrul DX conine
deplasamentul celui de-al doilea ir, iar BX conine min{ l1, l2 }. Rezultatul se
transmite prin registrul AX:
-1

ir1 < ir 2
AX =
0

ir 1 = ir 2
1

ir 1 > ir 2
Strcmp
macro
push cx
push di
push si
mov si,
mov di,
mov cx,
et1:
mov al,
mov dl,
cmp al,
jne et2
inc si
inc di
loop et1
mov ax,
jmp et4
et2:
jb et3
mov ax,

ax
dx
bx
byte ptr
byte ptr
dl

ds:[si]
ds:[di]

547
jmp

et4

mov

ax, -1

pop
pop
pop

si
di
cx

et3:
et4:

endm

Macrodefiniia care convertete o liter mic ntr-o liter mare este:


Lowtoupper macro char
local final
mov al, a
jb final
cmp al, z
ja final
sub al, 20h
final:
nop
endm

n acelai fel se definesc i alte macrodefiniii uzuale, care vor constitui


ntr-o bibliotec.
12.9 Concluzii
Se pune problema alegerii dintre macroapeluri sau proceduri. n cazul
macrodefiniiilor, texul surs scris de program devine mai clar i mai scurt. Un alt
aspect important este ctigul de vitez pe care l dobndim prin folosirea
macrodefiniiilor deoarece nu se mai pierde timpul cu memorarea adresei de
revenire n stiv, precum i cu descrcarea stivei la terminarea procedurii. Marele
dezavantaj este creterea dimensiunii programului, care dup cteva expandri,
poate atinge dimensiuni considerabile.

13

548

PROCEDURI
13.1 Reutilizabilitatea
Secvenele repetitive i secvenele repetabile sunt dou lucruri diferite. Dou secvene
repetitive sunt legate de implementarea structurii repetitive n una din forme (for, do-while, dountil) rezolvarea secvenelor repetabile i-a gsit diferite soluii dintre care se enumer:
plasarea secvenei n afara modulului principal si referirea ei n diferite puncte ale
acestuia; limbajul COBOL are soluia elegant prin utilizarea
instruciunii
PERFORM; reutilizabilitatea e legat numai de programul respectiv;
definirea de proceduri, ca uniti program distincte, cu grad de reutilizabilitate extins i
la alte programe; procedura are o list de parametri mprit n trei subliste: sublista
parametrilor ce conin datele iniiale care vor fi prelucrate n procedur, sublista ce
conine rezultatele prelucrrii i sublista de parametri care modul cum a decurs
prelucrarea (starea procedurii); procedura nu returneaz un rezultat, sau returneaz un
rezultat de tip vid;
definirea de funcii n care lista de parametri conine numai date de intrare i rezultatul
prelucrrii este unul singur i va fi returnat, putnd fi utilizat direct ca termen n
evaluarea de expresii; funciile se construiesc n vederea unei reutilizri foarte largi.

Procedurile i funciile se constituie n biblioteci i de aceea programatorul


trebuie s dea dovad de grij cnd le construiete pentru a le asigura
corectitudinea i un grad de generalizare ridicat. Fr aceste caracteristici nici o
bibliotec de subprograme nu este operaional.
Cu att mai mult soluiile n limbaje de asamblare care sunt mult mai diversificate, trebuie
realizate astfel nct gradul de reutilizabilitate s ating nivele care s justifice efortul de a construi
biblioteci de proceduri.
Pentru realizarea conversiilor att de frecvent utilizate n programe scrise n limbaj de
asamblare se construiesc proceduri. De asemenea, se construiesc proceduri pentru calcule
matriciale, pentru realizarea unor validri, pentru operaii de intrare/ieire pe disc, pentru
combinarea unei secvene de apeluri de ntreruperi. Tot ce se reutilizeaz n viitor, e preferabil s fie
proiectat ca o procedur.
13.2 Structura unei proceduri

O procedur se descrie prin:


Parametrii de intrare p1, p2, .., pn ;
Bloc de prelucrare S
Parametrii de ieire r1 ,r2, ..,rm
Parametrii de stare s1, s2, .., sk,.
Definirea procedurilor este prezentat n figura 13.1

549

p1
p2

r1 = f1 (p1, p2, , pn)


r2 = f2 (p1, p2, , pn, r1)

rm = fm(p1, p2, ,pn, r1, r2, ,rm-1)

r1
r2
...
rm

pn

s1 = 1
s2 = 2

sk = k

s1
...
s2

...
sk

Figura 13.1 Definirea unei proceduri


La definirea unei proceduri se are n vedere ca n s fie rezonabil, k s fie n
general 1, dac m=1 se va defini procedur, gestionnd cu atenie rezultatele
pentru a obine ceea ce caut, existnd multe riscuri n a se obine altceva.
n programul scris n limbaj de asamblare, procedura are structura din figura 13.2.

550

NumeProcedura

PROC

[{FAR,NEAR}]

Salvare registre

Bloc prelucrare cu referirea


parametrilor formali

Stocarea rezultatelor

Restaurare registre
ret [n]

NumeProcedura

ENDP

Figura 13.2 Structura unei proceduri


De exemplu, procedura PAR pentru criptarea unui text cu metoda lui Cezar dup o parol
este:
date segment
parola db 'parola'
n
db n-parola
;lungime parol
text db 'text secret '
db 12 dup(0)
m
db m-text
;lungime text
textcod db 24 dup(),'$'
date
ends
stiva
segment
db 512h dup(0)
stiva nds
cod
segment
ssume cs:cod,ds:date,ss:stiva
start:
mov ax, date
mov ds, ax
call par
mov ax,4c00h
int 21h

551
par

proc near
mov cl, m
xor ch, ch
lea di, text
lea si, parola

par1:
mov al, byte ptr[di]
caracterul din text n ax
add al, byte ptr[si]
caracterul din parol
add al, cl
caracterului
add al,100
mov [di+m], al
codificat
inc ah
cmp ah, n
jne par2
xor ax, ax
lea si, parola
dec si
par2:
inc di
inc si
loop par1
ret
par
endp
cod
ends
end start

;ncarc
;adun
;adun poziia
;adun o constant
descarc caracterul

13.3 Apelarea procedurilor


Apelarea unei proceduri presupune :
existena unui program apelator
existena procedurii apelate

Dac programul apelator nu este apelat la nivelul su, va fi numit program


principal, sau funcie rdcin intr-o structur arborescent sau nod iniial ntr-o
structur de tip reea asemnat unui program realizat modular.
nainte de efectuarea apelrii procedurii, n programul principal / procedura
apelatoare trebuie s se gseasc o secvena care stocheaz parametri care vor fi
prelucrai n procedur. Revenirea din procedur se efectueaz de regul la
instruciunea care urmeaz instruciunii call. Adresa instruciunii ce urmeaz
instruciunii call se gestioneaz prin intermediul registrului IP.
n procedura apelat exist secvena pentru salvarea regitrilor. Este o
regul de baz, aceea de a nu distruge coninutul resurselor la care nu are acces n
procedur.
Dac aceeai procedur este apelat n mai multe puncte din programul
principal schema fluxului de execuie este dat n figura 13.2.

552

call sume
sume PROC
call sume

ret

call sume

sume ENDP

Figura 13.2 Apelarea multipl a unei proceduri


Dac programul principal apeleaz procedura Suma, iar procedura aceasta
apeleaz procedura Compara, schema de execuie este dat n figura 13.3.
Suma PROC

Figura 13.3

Call suma

Compara PROC

Apelarea n cascad a procedurilor

Call compara

RET

RET

553
Program principal
Definire parametri reali
Procedur (PROC)

Pregtirea transmiterii
parametrilor reali
APEL PROCEDUR (call)

Prelucrarea rezultatelor
prelucrrii

Salvare registre

Prelucrare referind
parametri formali

Stocarea rezultatelor

Restaurare registre
Revenire (RET)

Figura 13.4 Schema standard de structurare/apel/revenire


Se observ apariia a dou concepte: parametri reali i parametri formali. Pentru
programatorul ce utilizeaz limbajul de asamblare se evideniaz semnificaia acestora.

n programul scris n limbajul de asamblare se lucreaz cu registre i cu


zone de memorie. Deci, dac parametri sunt operanzi, n mod obligatoriu sunt ori
registre, ori zone de memorie. Se lucrez cu: identificatori (registru sau zon de
memorie), adres, lungime i coninut.
Cazul 1:
parametri p1,p2, ...pn sunt n numr restrns i sunt stocai n registre;
rezultatele r1,r2, ...rm sunt n numr restrns i sunt stocai n registre;
informaia de stare se stocheaz ntr-un registru.
n aceast situaie, pregtirea transmiterii parametrilor nseamn iniializare de registre,
apelul procedurii nseamn salt ctre prima instruciune executabil din procedur. n procedur se
salveaz registre pe stiv. Referirea parametrilor formali, va nsemna utilizarea registrelor. Stocarea
rezultatelor se face n registre. Stocarea strii se va face ntr-un registru (CX = 0 dac prelucrarea sa efectuat corect, CX = -1 dac prelucrarea nu s-a efectuat corect, de exemplu). Se returneaz
registrele. Se are n vedere ca prin restaurare s nu se distrug din rezultatele obinute sau registru
de stare al procedurii.
Parametrii reali sunt registrele care se pregtesc n programul apelator.
Parametrii formali sunt aceleai registre pe care le utilizeaz procedura. Li se spune aa,
probabil pentru faptul c programatorul cnd scrie procedura nu are n aceti parametri valori
efective cu care s lucreze. El numai i imagineaz. Doar dup ce a fost apelat, n registru se

554
gsesc informaii care fac obiectul prelucrrii. Lucrul cu registre este cel mai simplu mod de
transmitere a parametrilor, listele de parametri formali, respectiv, reali, suprapunndu-se din toate
punctele de vedere.
Cazul 2:
Coninutul zonelor de memorie care formeaz parametri reali se transmit pe stiv,
numrul parametrilor fiind fix; parametri formali sunt zonele din stiv care la
procesarea listei au expresii de referire precis construite; aceasta este transmiterea
parametrilor prin valoare; n procedur se lucreaz cu copiile parametrilor reali, aflate
n stiv; rezultatele se depun fie n registre (preferabil), fie pe stiv.
Parametrii reali sunt zone de memorie diferite n programul apelator. Parametri formali
sunt zone ale stivei unde se afl copii ale valorilor parametrilor reali. Cele dou liste se refer la
zone de memorie diferite care au ns acelai coninut. Este cunoscut cazul procedurii de
interschimb a coninutului dintre dou zone de memorie a i b.
Parametrii reali

Procedur de interschimb

A - 15

Stiv

B - 20

[BP + 4] - 15
[BP + 6] - 20
Registrele AX i BX se folosesc pentru interschimb:
AX = [BP + 4]
BX = [BP + 6]
[BP + 4] = BX
[BP + 6] = AX

Cazul 3:
Zonele de memorie ale cror coninut urmeaz s fie prelucrat n proceduri sunt de
tipuri i lungimi foarte diferite; este convenabil pe stiv s se transmit adresele
zonelor de memorie care formeaz lista parametrilor reali se construiete n acest fel
list de adrese a parametrilor reali, n procedur, parametri formali sunt de fapt
variabile pointer care permit referirea din procedur a zonelor de memorie diferite n
programul apelator; acesta este transmitere prin adres.
Procedura de interschimb va realiza corect operaia dac pe stiv se vor gsi adresele
zonelor de memorie a i b; procedura va lucra direct pe ele si ntr-adevr va efectua
interschimbul.
Cazul 4:
Se definete un segment de date comune tuturor procedurilor si programului apelator.
Printr-o ncrcare corect a adresei acestui segment se va opera cu parametri reali
definii n el att din programul apelator, ct i din orice procedur segmentul de date
este comun ntregii operaii. Se realizeaz transmiterea prin referin, variabilele cu
anumii identificatori se afl n segmentul comun aplicaiei i de acolo se utilizeaz
coninutul zonei de memorie.
13.4 Locul procedurilor

555

Mecanismul de definire a procedurilor permit plasarea lor n diferite


moduri, figura 13.5.
.code
start:
a1
proc
...
ret
a1
endp
a2
proc
...
ret
a2
endp
...
call a1
...
call a2
...
mov ax, 4c00h
int 21h
end start

.code
start:
...
call b1
...
call b2
...
mov ax, 4c00h
int 21h
b1
proc
...

ret
b1
endp
b2
proc
...
ret
b2
endp

a)

b)

Figura 13.5 Poziii ale procedurilor


Astfel se observ c exist:

Proceduri definite n corpul programului principal, figura 13.5 a;


Proceduri definite dup secvena din segmentul de cod, figura 13.5 b:
mov ax, 4c00h
int 21h

13.5 Instruciuni specifice lucrului cu proceduri


Instruciunile specifice lucrului cu proceduri sunt :
call pentru apelul unei proceduri
ret pentru revenirea n programul apelator.
Semnificaia instruciunilor difer funcie de modul n care sunt poziionate cele dou
elemente:
Dac procedura se afl n acelai segment cu programul apelator i este apelat direct prin
nume, instruciunea call pune n stiv valoarea curent a lui IP iar apoi d controlul procedurii:
SP = SP 2
(SP) = IP
IP = IP + D16

;push IP

unde D16 reprezint deplasarea ntre destinaie i instruciunea ce urmeaz lui CALL n programul
apelator.

556
Instruciunea ret efectueaz:
IP = (SP)
SP = SP + 2

;salt la instruciunea urmtoare lui CALL


;revenirea la baza stivei (pop IP).

Se consider programul:
Parametri
a
b
c
d
s
Parametri

segment
dw
10
dw
15
dw
21
dw
37
dw
?
ends

Stiva

segment
Dw
100h dup (?)
label word
ends

varf
Stiva
Apelator

segment
ASSUME cs:code, ds:parametri, ss:stiva

start:
mov
mov
mov
mov
mov
mov
push
mov
push
mov
push
mov
push
call
mov
add
mov
mov
int

ax, parametri
ds, ax
ax, stiva
ss, ax
sp, offset varf
ax, offset a
ax
ax, offset b
ax
ax, offset c
ax
ax, offset s
ax
NEAR ptr suma
ax, s
ax, d
s, ax
ax, 4c00h
21h

;procedura n acelai segment cu programul apelator


suma
proc NEAR
push bp
mov
bp, sp
push ax
xor
ax, ax
add
ax, [bp+10]
add
ax, [bp+8]
add
ax, [bp+ 6]

557

Apelator

mov
pop
pop
ret
ends

[bp+ 4], ax
ax
bp
8h

Dinamica stivei pentru apelarea procedurii suma din program este:


Stiv
Offset a
Offset b
Offset c
Offset s
IP
BP
Ax
Ax
BP
IP
SP = SP +8h

Semnificaie
Plasare adresa (offset) a
Plasare adresa b
Plasare adresa c
Plasare adresa rezultat s
Ape procedura sum
Salveaz baza stivei
Salvare pe stiv valoare registru AX
Refacere registru AX
Refacere registru BP
Reface IP (se pregtete return)
Scoate parametri din stiv

Adresare
[BP+10]
[BP+8]
[BP+6]
[BP+4]
[BP+2]
[BP+0]
[BP-2]
-

Dac procedura se afl n acelai segment i este apelat indirect instruciunea call
realizeaz:
SP = SP 2
(SP) = IP
(IP) = EA
unde EA reprezint adresa efectiv (effective address).
Dac programul apelator se afl ntr-un registru i procedura apelat se afl n alt segment,
instruciunea call realizeaz:
SP = SP 2
(SP) = CS
SP = SP 2
(SP) = IP
Instruciunea ret pentru acest caz realizeaz:
IP = (SP)
SP = SP + 2
CS = (SP)
SP = SP + 2
Dinamica stivei cnd programul apelator se afl n segmentul apelului, iar procedura se afl
n segmentul procedurii este:
Parametri
a
b

segment
dw
10
dw
15

558
c
d
s
Parametri

dw
dw
dw
ends

Stiva

segment
Dw
100h dup (?)
label word
ends

varf
Stiva
Apelator

21
37
?

segment
ASSUME cs:code, ds:parametri, ss:stiva

start:

Apelator
Procedura
suma

suma
procedura
Stiv

mov
mov
mov
mov
mov
mov
push
mov
push
mov
push
mov
push
call
mov
add
mov
mov
int
ends

ax, parametri
ds, ax
ax, stiva
ss, ax
sp, offset varf
ax, offset a
ax
ax, offset b
ax
ax, offset c
ax
ax, offset s
ax
far ptr suma
ax, s
ax, d
s, ax
ax, 4c00h
21h

segment
ASSUME cs:procedura
proc FAR
push bp
mov
bp, sp
push ax
xor
ax, ax
add
ax, [bp+12]
add
ax, [bp+10]
add
ax, [bp+ 8]
mov
[bp+ 6], ax
pop
ax
pop
bp
ret
8h
endp
ends
semnificaie

Adresare

559
Offset a
Offset b
Offset c
Offset s
CS
IP
BP
Ax
Ax
BP
IP
CS
SP = SP +8h

Plasare adresa (offset) a


Plasare adresa b
Plasare adresa c
Plasare adresa rezultat s
Salvare registru de cod pe stiv (CALL)
Ape procedura sum
Salveaz baza stivei
Salvare pe stiv valoare registru ax
Refacere registru ax
Refacere registru BP
Reface IP (se pregtete return)
Reface segmentul de cod
Scoate parametri din stiv

[BP+12]
[BP+10]
[BP+8]
[BP+6]
[BP+4]
[BP+2]
[BP+0]
[BP-2]
-

Dac programul apelator i procedura se afl n segmente diferite, iar apelul este direct,
instruciunea CALL realizeaz:
SP = SP 2
(SP) = CS
SP = SP 2
(SP) = IP
(IP) = (EA)
(CS) = (EA) + 2
Instruciunea ret poate fi definit mpreun cu o expresie constant:
ret

expresie

care evalueaz i devine o valoare de adunare la registru de stiv (SP) ca parte din instruciune
determinnd executarea secvenei:
SP = SP + expresie
pentru revenire n programul apelator:
IP = (SP)
SP = SP + 2
CS = (SP)
SP = SP +2
SP = SP + expresie.
Aceasta este echivalent cu scoaterea din stiv a unui numr de baii specificat prin
expresie; se folosete la eliminare din stiv a parametrilor care au fost pui nainte de apelul
procedurii.
Fcnd modificri asupra coninutului stivei n procedura apelat este posibil revenirea n
programul apelator la alt instruciune i chiar la instruciuni aflate n segment de cod diferit
segmentului programului apelator. Se recomand folosirea acestei faciliti doar pentru protejarea
codului.

560

14
PRELUCRRI N VIRGUL MOBIL
14.1 Scurt istorie a prelucrrilor n virgul mobil
Procesoarele din familia 80x87 au fost construite cu scopul precis de a
crete viteza de lucru a calculatoarelor n operaiile matematice complexe. Pn la
versiunea 80387 coprocesoarele puteau sa existe sau nu n calculatoare. De
exemplu, un procesor 80386 lucreaz foarte bine cu coprocesorul 80287 sau cu
80387. Mai trziu, la apariia procesorului 80486, coprocesorul a fost nglobat n
procesor, pentru mbuntirea performanelor. Astfel, un procesor 80486 conine
un procesor 80387. Instruciunile procesorului 80486 sunt cele ale procesorului
80386, cele ale coprocesorului 80487 i cteva n plus.
Toate coprocesoarele lucreaz insa cu numere reprezentate pe 80 de bii.
Procesoarele nu trebuie sa se ocupe de conversia numerelor pe 8, 16, 32 sau 64 de
bii n cele pe 80 de bii, deoarece instruciunile care mut datele din regitrii
procesorului n cei ai coprocesorului convertesc automat numerele n formatul de
80 de bii.
Unele din numerele de 80 de bii au o semnificaie speciala, ele pot
reprezenta numrul infinit, un numr cu parte fracionar n perioad sau un NaN
(Not a Number). NaN este o valoare care se obine n momentul n care se ncearc
rezolvarea unor calcule de genul 0/0 sau /.
O alt caracteristica a coprocesoarelor este aceea a executrii secveniale a
instruciunilor. De exemplu, dac avem dou instruciuni, cea de-a doua nu este
executat pn cnd prima instruciune nu a fost terminat.
14.2 Resurse
Pentru efectuarea prelucrrilor n virgul mobil este utilizat un coprocesor
sau se construiesc proceduri care efectueaz conversii i calcule cu utilizarea
aritmeticii binare cu biii reprezentnd caracteristica i mantisa.
Astfel dac se aduna numerele
A = 0,37102
B = 0,123104
se parcurg urmtorii pai.
se omogenizeaz numerele, n aa fel nct sa aib acelai exponent:
A = 0,0037104
B = 0,123104

561

se efectueaz operaia de adunare:


C = A + B = 0,1267104
se procedeaz la normalizare, prin eliminarea zerourilor de dup virgul
i la diminuarea exponentului; ca n cazul scderii:
C=AB
unde:
A = 0,736104
B = 0,731104
C = A B = 0,005104 = 0,5102
Toate aceste operaii se obin prelucrnd biii din reprezentrile constantelor
n virgul mobil pe 4, 8, 10 baii, utiliznd instruciunile aritmeticii
binare. Procedurile emuleaz un coprocesor numai dac asigur
efectuarea gamei complete de operaii de prelucrare n virgula mobila.
De exemplu, o procedura de normalizare se efectueaz astfel:
000001101

se deplaseaz spre stnga K=5 poziii.


se scade din exponent cat nseamn K poziii, cu consecine asupra
semnului dac este cazul.
Pentru o procedura de adunare vor exista urmtoarele operaii:
E1

M1

E2

M2

dac E1 = E2 atunci M3 = M1 + M2
dac E1 1 vedem cu cat i mrim E3. Z1 reprezint partea ntreag a
mantisei, n acest caz a lui M3.
Dac este utilizat un coprocesor, resursele disponibile ale acestuia sunt:
opt registre ST0, ST1, ST2, ST3, ST4, ST5, ST6, ST7; fiecare registru
are o lungime de 10 baii;
o structura de baii, denumit status word, destinat indicatorilor de
condiie; astfel, coprocesorul 8087 are o structura de 16 bii cu
indicatorii de condiie specificai n figura 14.1.

562
Utilizare

Invalid
operation
exception
Denormalized
operand exception
Zerodivide exception
Overflow exception
Underflow exception
Precision exception
Interrupt exception
Condition code 0
Condition code 1
Condition code 2
Stack-top pointer

Condition code 3
Busy signal

Figura 14.1 Indicatorii de condiie ai coprocesorului


n caz de eroare biii 0, 1, 2, 3, 4, 5, 8, 9, 10, 14 sunt setai pe 1. Biii 13, 12,
11 arat care dintre cei 8 regitri este vrf de stiva. Aceti 3 bii
necesari gestionarii stivei vor fi numii n continuare PVST (pointer
pentru gestionarea vrfului de stiv).
PVST {0, 1, 2, 3, 4, 5, 6, 7}
Oricare dintre regitri poate fi vrf de stiv. Dac PVST este 6, o operaie
de incrementare conduce ca PVST sa devin 7. Dac PVST este 7, o
operaie de incrementare va face ca PVST sa devin 0. n cazul n care
PVST are valoarea 0 i se efectueaz o operaie de decrementare, PVST
va avea valoarea 7. Regitrii funcioneaz ca stiv circular.
Coprocesorul acceseaz operanzi definii n memorie cu descriptori
de tip DD, DT sau DQ. Regitrii coprocesorului sunt construii n stiv
(figura 14.2.), efectuarea operaiilor fiind precedat de operaii de

563

modificare a vrfului de stiv, operaii specifice introducerii n stiv


(push) sau extragerii din stiva (pop) a operanzilor.

Figura 14.2 Regitrii coprocesorului 8087


Operaiile de prelucrare a datelor efectuate de coprocesor sunt
mprite n mai multe clase:

RR
ceea ce nseamn c ambii operanzi se afl n regitri (pe
stiv) i prelucrrile se efectueaz n unul din urmtoarele doua moduri:
o un operand este conservat iar celalalt va conine rezultatul
prelucrrii ;
o ambii operanzi sunt conservai i rezultatul prelucrrii este
introdus la baza stivei; operanzii conservai, iar vrful stivei
gliseaz.

564

RM
ceea ce nseamn c un operand se afla n registru i altul se
afla n memorie; operandul din registru este copiat n alt registru i la
baza stivei se va gsi rezultatul, fie operandul este modificat i el
reprezint rezultatul prelucrrii; poziia operandului aflat n memorie
determina uneori ca rezultatul prelucrrii sa fie stocat n aceast zona, n
cazul instruciunilor de forma: cod_operatie M,R.
Structura terminal a mnemonicelor indica prin prezena literei p, efectuarea
de operaii de introducere n stiva (push), sau de extragere din aceasta
(pop). Utilitatea acestui mod de lucru este evideniat atunci cnd se
evalueaz expresii i regitrii conin rezultate pariale care se refera
direct, fr a mai fi nevoie de operaii de ncrcare (load) sau memorare
(store).
14.3 Setul de instruciuni
Instruciunile coprocesoarelor din familia 80x87 sunt clasificate n ase
grupe distincte:
instruciuni de transfer al datelor (de ncrcare) ;
instruciuni aritmetice ;
instruciuni de comparare ;
instruciuni transcedentale ;
constante ;
instruciuni de control al procesorului .
Pentru o gestionare corect a operaiilor care se desfoar n coprocesor a
fost implementat structura de control a operaiilor, denumit control word.
Comportamentul acestui registru este asemntor cu cel al registrului de stare.
Registrul de control are o lungime de 16 bii, valorile acestora fiind detaliate n
figura de mai jos:

Utilizare

Invalid operation exception


mask
Denormalized
operand
exception mask
Zerodivide exception mask
Overflow exception mask
Underflow exception mask

565
Precision exception mask
Reserved
Interrupt enable mask
0 = Interrupts enabled
1 = Interrupts disabled
Precision Control
00 = 24 bits
01 = reserved
10 = 53 bits
11 = 64 bits
Rounding Control
00 = round to nearest or even
01 = round down
10 = round up
11 = truncate
Infinity Control
0 = Projective
1 = Affine
Reserved

Figura 14.3 Indicatorii de control


Instruciunile de ncrcare au rolul de a copia coninutul unei zone de
memorie sau a unui registru numit sursa (SRS), intr-un registru specificat.
Instruciunea FLD SRS memoreaz n ST coninutul din SRS convertit de la tipul
real scurt sau real lung la tipul real cu reprezentare pe 10 baii.
Instruciunea FILD SRS memoreaz n ST coninutul din sursa SRS
convertit de la tipul ntreg (scurt sau lung) la tipul real pe 10 baii.
Instruciunea FDLD SRS convertete coninutul zecimal mpachetat din
SRS la tipul real reprezentat pe 10 baii i ncarc n ST.
Instruciunile FLD, FDLD i FDLD decrementeaz pointerul stivei format
din regitrii ST(I), cu I=1,..,7 permind rmnerea pe stiv i a celorlali operanzi.
Instruciunea FST DST efectueaz copierea din registrul ST n operandul
DST a coninutului convertit de la tipul real pe 10 baii la tipul real scurt sau real
lung.
Instruciunea FISI DST copiaz din registrul ST n operandul DST,
coninutul convertit la tipul ntreg.
Instruciunea FBSTP DST convertete la tipul zecimal mpachetat
coninutul registrului ST i l memoreaz n zona de memorie referit de DST.
Instruciunile FSTP i FISTP realizeaz aceleai prelucrri precum
instruciunile FST i FIST cu deosebirea ca n plus incrementeaz pointerul cu
care se gestioneaz vrful stivei.

566

Instruciunea FXCH STi schimb coninutul registrului STi cu ST. Dac


lipsete operandul interschimbul se efectueaz ntre regitrii ST i ST1.
Instruciunile aritmetice corespund operaiilor elementare (adunare,
scdere, nmulire, mprire, extragere modul, schimbare semn, extragere radical,
scalare, obinerea restului mpririi).
n cazul n care instruciunea are ca ultima litera a mnemonicii litera P,
aceasta are semnificaia operaiei de eliberare a stivei (pop) ceea ce corespunde
incrementrii pointerului de stiv.
De exemplu, instruciunile FADD i FADDP realizeaz operaia de
adunare. n plus, instruciunea FADDP incrementeaz pointerul de gestionare a
vrfului de stiv (PVST = PVST + 1).
Instruciunea de adunare a numerelor reale FADD DST,SRS corespunde
operaiei:
(DST) := (DST) + (SRS)
Instruciunea de adunare a numerelor reale FADDP DST,SRS corespunde
operaiilor:
(DST) := (DST) + (SRS)
PVST := PVST + 1
Instruciunile de scdere numere reale FSUB DST, SRS i FSUBP DST,SRS
corespund operaiilor:
(DST) := (DST) - (SRS), respectiv
(DST) := (DST) - (SRS)
PVST := PVST + 1
Instruciunea FISUB DST,SRS efectueaz operaia de scdere a datelor de
tip ntreg, scurt sau lung.
(DST) := (DST) + (SRS)
Instruciunile de nmulire FMUL DST,SRS i FMULP DST,SRS
efectueaz operaiile:
(DST) := (DST) * (SRS)
respectiv:
(DST) := (DST) * (SRS)

567

PVST := PVST + 1
Instruciunile FDIV DST,SRS i FDIVP DST,SRS efectueaz mprirea:
(DST) := (DST) / (SRS)
n plus FDIVP incrementeaz pointerul pentru gestionarea stivei. Pentru
mprirea numerelor ntregi se utilizeaz instruciunea FIDIV.
Pentru obinerea valorii absolute se utilizeaz instruciunea FABS, fr
operanzi care realizeaz operaia:
(ST) := | ST |
Schimbarea semnului se efectueaz de ctre instruciunea FCMS cu
operandul implicit ST, care efectueaz operaia:
(ST) := -(ST)
Pentru extragerea rdcinii ptrate se utilizeaz instruciunea FSQRT cu
operandul implicit ST, care realizeaz operaia descrisa prin:
(ST) :=

(ST )

Rotunjirea la ntreg a operandului implicit ST este efectuat de instruciunea


FRNDINT (Round to integer).
Operaia de scalare corespunde nmulirii unui numr aflat n registrul ST cu
2n, n aflat n registrul ST(1). Mnemonica instruciunii care implementeaz aceast
instruciune este FSCALE.
n anumite operaii este necesar preluarea repetat exponentului i a prii
fracionare, ceea ce impune memorarea lor ca operanzi distinci, figura 14.4.
exponent

ST(1)

parte fractionara

ST

Figura 14.4 Separarea ca operanzi distinci a exponentului i a prii


fracionare
Instruciunile de comparare compara doi operanzi i poziioneaz
indicatorii de condiie.

568

Instruciunea FCOM SRS efectueaz operaia (ST) (SRS) i poziioneaz


indicatorii de condiie.
Instruciunea FCOMP SRS efectueaz operaia (ST) (SRS) i
incrementeaz pointerul pentru gestionarea stivei. Pentru compararea datelor de tip
ntreg se folosesc instruciunile FICOM i FICOMP.
Pentru compararea cu zero a elementului din vrful stivei este folosit
instruciunea FTST, care efectueaz operaia (ST) 0.0 .
Funciile transcedentale au implementate expresii precum:
f(x) = 2x 1
g(x) = arctg(x)
r(x) = tg(x)
h(x,y) = y*log2(x), cu x (0, ) i y R
p(x,y) = y*log2(x + 1), cu x (0, 1 -

2 / 2 ) i y R

Instruciunea F2XM1 evalueaz funcia f(x). Dac x [0; 0.5] i x este


memorat n ST, atunci
(ST) := 2(ST) - 1
Instruciunea FPATAN evalueaz funcia g(x). Instruciunea FPTAN
evalueaz funcia r(x) pentru x (0; /4).
Instruciunea FYL2X evalueaz funcia h(x,y); operandul x se gsete n
registrul ST, iar operandul y se gsete n registrul ST(1).
Instruciunea FYL2XP1 evalueaz funcia p(x,y). Variabila x se memoreaz
n registrul ST, iar variabila y se memoreaz n registrul ST(1).
Instruciunile pentru gestionarea i manipularea constantelor
decrementeaz pointerul PVST i iniializeaz registrul ST cu o anumit valoare,
specificat prin instruciune.
Instruciunea FLDZ decrementeaz PVST i iniializeaz registrul ST cu
valoarea zero real (0.0) .
Instruciunea FLD1 decrementeaz PVST i iniializeaz registrul ST cu
constanta 1.0 .
Instruciunea FLDPI decrementeaz PVST i iniializeaz registrul ST cu constanta
PI.

569

Instruciunea
constanta log2 e .
Instruciunea
constanta log2 10 .
Instruciunea
constanta log10 2.
Instruciunea
constanta loge 2.

FLD2E decrementeaz PVST i iniializeaz registrul ST cu


FLD2T decrementeaz PVST i iniializeaz registrul ST cu
FLDLG2 decrementeaz PVST i iniializeaz registrul ST cu
FLDLN2 decrementeaz PVST i iniializeaz registrul ST cu

Instruciunile de control vizeaz iniializarea procesorului (FINIT),


punerea pe unu a biilor ce formeaz mti pentru ntreruperi (FDISI), punerea pe
zero a biilor ce formeaz mti ale ntreruperilor (FENI), incrementarea
pointerului stivei (FINCSTP), decrementarea pointerului stivei (FDECSTP),
memorarea registrului de stare (FSTSW), memorarea registrului de control
(FSTCW), ncrcarea registrului de control (FLDCW).
Instruciunea FNOP copiaz registrul ST n el nsui. Este folosit pentru
ntrzierea execuiei proceselor.
Pentru salvarea regitrilor se folosete instruciunea FSAVE, iar pentru
restaurarea regitrilor se folosete instruciunea FRSTOR. Zona de memorie n
care se salveaz regitrii are o lungime de 94 de baii.
Pentru dealocarea unui registru se folosete instruciunea FFREE, care
seteaz pe zero flagul corespunztor registrului respectiv, aceasta semnificnd ca el
este gol.
Pentru salvarea pe stiv a regitrilor de stare se folosete instruciunea
FSTSW, iar pentru salvarea informaiilor privind procesele, regitrii de control i
de stare, registrul tag i pointerii operanzilor se folosete instruciunea FSTENV.
Zona de memorie n care se salveaz va avea o lungime de 14 baii.
14.4 Sintaxa instruciunilor
Instruciunile pentru operaii n virgul mobil (floating point instructions)
ncep cu litera F. Mnemonicele conin elemente comune cu instruciunile
limbajului de asamblare (add addition, st store, ld load, cmp compare, div
divide, sub subtract, sqrt square root, abs absolute value, chs change sign,
mul multiply, cos cosine, sin sine, patan partial arctangent, ptan partial
tangent).
Instruciunile sunt de tip R R, R M, R I cu luarea n considerare a
faptului ca registrul acumulator este considerat ST(0), utilizat n formulele implicite
de scriere a instruciunilor.
Astfel putem ntlni urmtoarele tipuri de instruciuni:
Fmnem [[op1][,op2]]

570

sau
Fmnem [[destinaie][,sursa]]
Prin utilizarea parantezelor drepte se realizeaz opionalitatea operandului
n expresie. Definirea explicit a operanzilor corespunde construciei:
Fmnem destinaie, sursa
cu semnificaia:
destinaie := destinaie operaie sursa
De exemplu, n instruciunea:
FADD ST(1),ST

avem
ST(1) := ST(1) + ST

Operanzii ST(1) destinaie, ST(0) sursa sunt operanzii implicii pentru


aceast operaie. Dac n program se scrie FADD i lipsesc operanzii, se
subnelege ca registrul ST(1) este sursa, iar ST este destinaie.
Dac se utilizeaz lista de operanzi n mod explicit, are loc atribuirea de rol
sursa a unui anumit registru, respectiv, de rol destinaie pentru un alt registru.
Instruciunea:
FADD ST(i),ST

corespunde operaiei
ST(i) := ST(i) + ST
iar instruciunea
FADD ST,ST(i)

corespunde operaiei
ST := ST + ST(i)

571

n cazul n care un operand este definit n memorie se utilizeaz formele de


instruciuni:
Fmnem [[reg][,numevariabila]]
unde operandul sursa se afla numai n memorie, iar operandul destinaie se afla n
registru.
Instruciunea FADD ST(2), pre corespunde expresiei:
ST(2) := ST(2) + pret
Iar instruciunea FADD pret corespunde expresiei:
ST := ST + pret
Efectul execuiei instruciunilor
Instruciunile au ca efect att realizarea de operaii simple (adunri, scderi,
memorri, ncrcri, iniializri) cit i extragerea sau depunerea pe stiva a
rezultatelor cu efectele de translatare specifice acestui tip de structura de date care
este stiva.
Pentru a evidenia efectele execuiei unei operaii se impune:
prezentarea coninutului regitrilor ST, ST(1), ST(2), , ST(7) nainte de
execuie;
indicarea efectului execuiei propriu-zise;
prezentarea modului n care se schimba coninutul regitrilor prin
efectele operaiilor de depunere pe stiva (push), respectiv, de extragere
din stiva (pop) care nsoesc execuia instruciunilor de program.
14.5 Forma extern a instruciunilor
Instruciunile fr operanzi presupun fie utilizarea implicit a registrului
vrf de stiv ST(i), fie utilizarea implicit regitrilor ST(0) i ST(1).
Instruciunea FADD realizeaz
[ST(0)] := [ST(0)] + [ST(1)]
adic aduna coninutul registrului ST(1) la coninutul registrului ST(0). Rezultatul
se gsete n registrul ST(0).
Instruciunea FXCH interschimb coninutul registrului ST(0) cu coninutul
registrului ST(1).
Instruciunea FSCALE realizeaz operaia:

572

ST(0) := ST(0)*2ST(1)
Dac registrul ST(1) conine valoarea 4, coninutul registrului ST(0) va fi
multiplicat de 16 ori. Dac registrul ST(1) conine 3, coninutul registrului ST(0)
va fi mprit la 8.

Instruciunea FCOM realizeaz compararea registrului


ST(0) cu registrul ST(1) i poziioneaz indicatorii de condiie.
Instruciunea FTST compar coninutul registrului ST(0) cu 0.0 i seteaz
indicatorii de condiie.
Instruciunea FLDLG2 realizeaz ncrcarea n ST(0) a valorii log102 =
0.30102, cu o aproximaie de 19 cifre zecimale.
Instruciunea FLDPI ncarc n ST(0) numrul PI, cu o precizie de 19 cifre.
Instruciunea FLDZ ncarc n registrul ST(0) valoarea constantei zero (0.0)
.
Instruciunea FLD2T ncarc n registrul ST(0) valoarea log210 cu o
precizie de 19 cifre zecimale.
Instruciunea FLD2E ncarc registrul ST(0) cu valoarea log2e cu o precizie
de 19 cifre zecimale.
Instruciunile cu un operand presupun utilizarea implicit a registrului
ST(0).
Astfel, dac registrul ST(1) conine valoarea 275, instruciunea FLD ST(1)
are ca efect iniializarea registrului ST(0) cu aceast valoare. Dup execuia
instruciunii regitrii vor arata ca n figura 14.5.:

FLD ST(1)

ST(0)
340
275
?

ST(1)
275
340
?

ST(2)
?
275
?

Figura 14.5 Modificrile din regitrii la execuia instruciunii FLD ST(1)


14.6 Exemple

Se va construi un program care s nmuleasc dou


numere n virgul mobil folosind instruciunile coprocesorului.
Variabilele x1 i x2 sunt definite pe 64 bii. Instruciunea de
nmulire are ca parametri implicii pe st(0) i pe st(1) iar
rezultatul
este
stocat
n
st(0).
Pentru vizualizarea rezultatului se va utiliza facilitatea debuggerului de a afia coninutul registrelor coprocesorului.

573
;Program de demo lucru cu coprocesor
;Realizeaza inmultirea a doua numere x1 si x2
; daca exista coprocesor. Altfel afiseaza un mesaj de eroare.
.model small
.286
.data
NuInstalat db 'CoProcesor neinstalat',10,13,'$'
ctrl_87 dw lbffh; precizia =64
x1 dq 12.0
x2 dq 14.0
rezultat dq ?
.code
start:
mov ax,@data
mov ds,ax
mov ax,40h
mov es,ax
mov ax,es:10h
test ax,2
jnz Instalat
mov dx,offset NuInstalat
mov ah,9
int 21h
jmp final
Instalat:
FINIT
FLDC ctrl_87
FLD x1 ;st(0)=x1
FLD x2 ;st(1)=x1 si st(0)=x2
FMUL
FST rezultat ;rezultat=st(0)
final:
mov ax,4c00h
int 21h
end

n continuare se prezint un program care calculeaz


valoarea expresiei:

574

n xk
ex
= k=1 k!
Transferul datelor ctre procedur se va face prin referin. Stiva
coprocesorului va arta astfel:

ST(0 Va fi folosit pentru manevra


)
ST(1 Va conine xk
)
ST(2 Va conine k!
)
ST(3
)
n xk
ST(4 Va

)
conine
k=1 k!
ST(5
)
ST(6
)
ST(7
)
.model small
.stack 512h
.data
nnr dw 10
xnr dd 5
temp dw ?
rez dd ?
.code
e_la_x proc near
fld xnr

; incarca x din memorie

575
fst st(1)
;
fld1
;
fst st(2)
;
fst st(4)
;
mov cx,1
et: fnop
fld xnr
fmul st(1),st

pune x in st1
pune 1 in st
initializeaza k! cu 1
initializeaza suma cu 1

fxch st(2) ;
mov temp,cx
fimul temp ;
fxch st(2) ;
fld st(1)
;
fdiv st,st(2)
fadd st(4),st
din st4
inc cx
cmp cx,nnr ;
jle et
fxch st(4) ;
fst rez
ret
e_la_x endp
start:
mov ax,@data
mov ds,ax
;
xor cx,cx
call e_la_x ;
mov ax,4c00h
int 21h
end start

schimba st cu st2

; x la k

k!
schimba st cu st2
incarca in st pe x la k
; face impartirea
; aduna rezultatul fractiei la suma

compara cx cu n
; if <= sare la et
aduce rezultatul in st
; duce rezultatul in memorie

incarca segmentul de date


apeleaza procedura
; functia de iesire

14.7 Concluzii
Trebuie realizat un echilibru ntre utilizarea resurselor coprocesorului i
celelalte tipuri de aritmetici, aa fel nct s se obin precizia rezultatelor i n
acelai timp un numr ct mai mic de cicluri main la execuia programului.

576

17
PROGRAMARE MIXT: C LIMBAJ DE ASAMBLARE
17.1 Programul principal este scris n limbaj de asamblare, procedurile
apelate sunt scrise n limbajul C
Variabilele transmise procedurii apelate se definesc cu atributul extrn.
Procedurile apelate se definesc, de asemenea, cu atributul extrn. Se
folosesc pentru apel proceduri scrise n limbajul C pentru a realiza
funcii de intrare/ieire care presupun conversii.
Programul ASM1 adun trei numere. Se apeleaz funcia scanf()
pentru a iniializa trei variabile a, b, c. Dup nsumare se apeleaz
procedura printf() pentru a imprima variabila suma. Se definesc n
programul C variabilele de tip char: format1, format2, format3, format4.
;ASM 1
.model small
.stack 100h
.data
; date externe
extrn c format1:word
extrn c format2:word
extrn c format3:word
extrn c format4:word
extrn c format:word
extrn c a:word
extrn c b:word
extrn c c:word
;date locale
suma dw ?
.code
public _main
; functiile externe apelate
extrn c printf:proc
extrn c scanf:proc
extrn c sablon:proc
extrn c refac:proc
; intrarea in program
_main proc
; apel functie C de formatarea a ecranului

577
call sablon c
; citirea parametrilor de la tastatura
lea ax,format1
call printf c,ax
lea ax,format
lea bx,a
call scanf c,ax,bx
lea ax,format2
call printf c,ax
lea ax,format
lea bx,b
call scanf c,ax,bx
lea ax,format3
call printf c,ax
lea ax,format
lea bx,c
call scanf c,ax,bx
; insumarea celor trei valori
mov ax,a
add ax,b
add ax,c
mov suma,ax
; afisarea rezultatului
lea ax,format4
call printf c,ax,suma
; apel functie C de refacere a ecranului
call refac c
; iesirea din program
ret
_main endp
end
//C1
#include <stdio.h>
#include <conio.h>
char format1[20]="a=";
char format2[20]="b=";
char format3[20]="c=";
char format4[20]="\nsuma=%d\n";
char format[20]="%d";
int a,b,c;
void sablon(void)
{
int i;
clrscr();

578
for(i=0;i<80;i++)
printf("-");
printf("Introduceti datele:\n");
for(i=0;i<80;i++)
printf("-");
printf("\n\n\n");
for(i=0;i<80;i++)
printf("-");
printf("\n");
for(i=0;i<80;i++)
printf("-");
gotoxy(1,4);
}
void refac(void)
{
getch();
clrscr();
}

Programul ASM2 compar dou iruri de caractere. Se citesc irurile


apelnd ntreruperea 21h cu funcia 01h. Pentru comparare se
apeleaz funcia stringcmp() scris n limbajul C. Rezultatul returnat
este interpretat n programul scris n limbaj de asamblare.
;ASM 2
.model small
.stack 100h
.data
sir db 'parola',0
sirc db 10 dup(?)
m1 db 10,'Siruri identice',0
m2 db 10,'Siruri diferite',0
m3 db 10,'Dati sirul:',0
.code
public _main
extrn c printf:proc
extrn _stringcmp:proc
_main proc
lea ax,m3
call printf c,ax
xor bx,bx
citire:
mov ah,01h
int 21h
cmp al,0dh
je afisare
mov sirc[bx],al
inc bx
jmp citire

579
afisare:
mov al,0
mov sirc[bx],al
lea ax,sir
lea bx,sirc
push ax
push bx
call _stringcmp
add sp,4
test ax,ax
jnz diferite
lea ax,m1
call printf c,ax
jmp sfarsit
diferite:
lea ax,m2
call printf c,ax
sfarsit:
ret
_main endp
end
//C2
int stringcmp(char* x,char* y)
{
while(*x==*y)
{
if(*x=='\0')
return 0;
x++;
y++;
}
return *x-*y;
}

Programul ASM3 concateneaz dou iruri de caractere. Se citesc


irurile i se apeleaz funcia stringcat() care primete pe stiv
adresele celor dou variabile, sir1, sir2. Adresa irului rezultat este
returnat n registrul AX (funcia returneaz pointer spre char).
;ASM 3
.model small
.stack 100h
.data
sir1 db 'mergem la ',0,20 dup(?)
sir2 db 'stadion',0
format db 'Sirul concatenat este : %s',10,13,0
.code
public _main
extrn c printf:proc

580
extrn _stringcat:proc
_main proc
lea ax,sir1
lea bx,sir2
push bx
push ax
call _stringcat
add sp,4
lea bx,format
call printf c,bx,ax
ret
_main endp
end
//C3
#include <conio.h>
char* stringcat(char* s1,const char* s2)
{
char* t=s1;
while(*s1)
s1++;
while(*s1++=*s2++);
return t;
}
char* stringcat(char* s1,char* s2)
{
int i;
for(i=0;s1[i];i++);
for(;s1[i++]=*s2++;);
return s1;
}

Programul ASM4 afieaz minimul sau maximul dintre dou numere.


Se transmit funciei scrise n limbajul C numerele i opiunea de calcul
a valorii minime (1) sau maxime (2).
;ASM 4
.model small
.stack 100h
.data
format1 db 'Introduceti a,b,optiune(1-min,2-max):',0
format2 db '%d%d%d',0
format3 db 'Functia este: %d',10,13,0
a dw ?
b dw ?
x dw ?
pf dw ?
.code
public _main
extrn _funct:proc
extrn c printf:proc

581
extrn c scanf:proc
_main proc
lea ax,format1
call printf c,ax
lea ax,format2
lea bx,a
lea cx,b
lea dx,x
call scanf c,ax,bx,cx,dx
mov ax,x
push ax
mov dx,1
call _funct
add sp,2
mov pf,ax
call pf c,a,b
lea bx,format3
call printf c,bx,ax
ret
_main endp
end
//C4
int min(int a,int b)
{
return a<b?a:b;
}
int max(int a,int b)
{
return a>b?a:b;
}
int (*funct(int x))()
{
int (*pfunct)();
switch(x)
{
case 1:
pfunct=min;
break;
case 2:
pfunct=max;
break;
}
return pfunct;
}

Programul ASM5 stabilete i afieaz maximul dintre trei numere.


;ASM 5
.model small
mscanf macro par1,par2

582
lea ax,par1
lea bx,par2
call scanf c,ax,bx
endm
mprintf macro par
lea ax,par
call printf c,ax
endm
.stack 100h
.data
format1 db "Maxim = %d",10,13,0
format2 db "a=",0
format3 db "b=",0
format4 db "c=",0
format5 db "%d",0
a dw ?
b dw ?
c dw ?
rez dw ?
.code
public _main
extrn _max:proc
extrn c scanf:proc
extrn c printf:proc
_main proc
mprintf format2
mscanf format5,a
mprintf format3
mscanf format5,b
mprintf format4
mscanf format5,c
push c
push b
push a
call _max
add sp,6
lea bx,format1
call printf c,bx,ax
ret
_main endp
end
//C5
int max(int a,int b,int c)
{
return a>b?(a>c?a:c):(b>c?b:c);
}

17.2 Programul principal este scris n limbajul C, procedurile apelate sunt


scrise n limbaj de asamblare

583

Programul C6 citete un vector de numere ntregi i l afieaz pagin


cu pagin. Afiarea se face cu ajutorul funciei afis() definit n limbaj
de asamblare; aceasta apeleaz la rndul ei procedurile pozit() i
sterg().
//C6
#include <stdio.h>
#include <conio.h>
extern void afis(void);
void main(void)
{
float v,x[40];
int i,n;
printf("n=");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("x[%d]=",i);
scanf("%f",&v);
x[i]=v;
}
clrscr();
for(i=0;i<n;i++)
if((i%23==0)&&(i!=0))
{
afis();
printf("\nx[%d]=%f]",i,x[i]);
}
else
printf("\nx[%d]=%8.2f",i,x[i]);
afis();
}
;ASM 6
; Afisarea unui mesaj, asteptarea apasarii unei taste
; si stergerea ecranului
.model small
.data
sir db 'Pentru a continua apasati orice tasta...','$'
.code
public _afis
; Interfata cu programul C
pozit proc
; Pozitionarea pe linia 24,
coloana 1
mov ah,02h ; Functia BIOS
mov dh,24 ; Linia
mov dl,1
; Coloana
int 10h
; Apelul intr BIOS 10h (functii grafice)
ret
pozit endp

584
sterg proc
mov ah,0
mov al,2
int 10h
ret
sterg endp
_afis proc
call pozit
mov ax,seg sir
mov ds,ax
mov dx,offset sir
mov ah,09h
int 21h
terminat cu '$'
mov ah,08h
int 21h
call sterg
ret
_afis endp
end

; Stergerea ecranului

; Pozitionare pe ecran
; Afisare mesaj

; Apel functie DOS afisare text


; Asteptarea apasarii unei taste

; Iesirea catre functia apelatoare

Programul C7 calculeaz suma a trei numere citite de la tastatur.


Pentru efectuarea adunrii se apeleaz funcia scris n limbaj de
asamblare suma(). Parametrii sunt transmii prin valoare, pe stiv.
//C7
#include <stdio.h>
extern int suma(int,int,int);
void main(void)
{
int a,b,c;
printf("a=");
scanf("%d",&a);
printf("b=");
scanf("%d",&b);
printf("c=");
scanf("%d",&c);
printf("suma=%d\n",suma(a,b,c));
}
;ASM 7
.model small
.code
public _suma
_suma proc
push bp
mov bp,sp
mov ax,[bp+4]
add ax,[bp+6]
add ax,[bp+8]

;
;
;
;
;

Salvarea registrului bp
bp<-sp
ax=par1
ax+=par2
ax+=par3

585
pop bp
ret
_suma endp
end

; Refacere bp
; Iesirea din functie

Spre deosebire de programul precedent, programul C8 care


efectueaz aceleai calcule, transmite parametrii prin adres, pe stiv.
//C8
#include <stdio.h>
extern int suma(int*,int*,int*);
void main(void)
{
int *pa,a,*pb,b,*pc,c;
printf("a=");scanf("%d",&a);
printf("b=");scanf("%d",&b);
printf("c=");scanf("%d",&c);
pa=&a;pb=&b;pc=&c;
printf("suma=%d\n",suma(pa,pb,pc));
}
;ASM 8
.model small
.stack 100h
.code
public _suma
_suma proc
push bp
mov bp,sp
mov di,[bp+4]
mov ax,[di]
mov di,[bp+6]
add ax,[di]
mov di,[bp+8]
add ax,[di]
pop bp
ret
_suma endp
end

;
;
;
;
;
;
;
;
;
;

Salvare bp
bp<-sp
di=pa
ax=*pa;
di=pb
ax+=*pb
di=pc
ax+=*pc
Refacere bp
Iesire din functie

Programul C9 exemplific returnarea rezultatului pe stiv, prin adres.


//C9
#include <stdio.h>
extern int* suma(int*,int*,int*);
void main(void)
{
int *pa,a,*pb,b,*pc,c,*ps;
printf("a=");
scanf("%d",&a);

586
printf("b=");
scanf("%d",&b);
printf("c=");
scanf("%d",&c);
pa=&a;
pb=&b;
pc=&c;
ps=suma(pa,pb,pc);
printf("suma=%d\n",*ps);
}

;ASM 9
.model small
.stack 100h
.data
rez dw ?
.code
public _suma
_suma proc
push bp
mov bp,sp
mov di,[bp+4]
mov ax,[di]
mov di,[bp+6]
add ax,[di]
mov di,[bp+8]
add ax,[di]
mov rez,ax
mov ax,offset rez
pop bp
ret
_suma endp
end

; ax=*par1+*par2+*par3
; rez<-ax
; ax<-&rez

Programul C10 calculeaz i afieaz suma elementelor unui vector.


Parametrii transmii pe stiv sunt numrul de elemente al vectorului
i adresa primului element.
//C10
#include <stdio.h>
extern int suma(int*,int);
void main(void)
{
int v,x[40];
int i,n;
printf("n=");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("x[%d]=",i);

587
scanf("%d",&v);
x[i]=v;
}
printf("Suma elementelor vectorului = %d",suma(x,n));
}
;ASM 10
.model small
.stack 100h
.code
public _suma
_suma proc
push bp
mov bp,sp
mov cx,[bp+6]
mov si,[bp+4]
xor ax,ax
ciclu:
add ax,[si]
inc si
inc si
loop ciclu
pop bp
ret
_suma endp
end

;
;
;
;
;
;

cx <- numarul de elemente


si <- adresa primului element
ax=0
do{
ax+=x[i];
i++

; }while(i<n)

//C11
/*
Produsul scalar a doi vectori.
*/
#include <stdio.h>
extern int prodscalar(int*,int*,int);
void main(void)
{
int x[40],y[40],v,i,n;
printf("n=");
scanf("%d",&n);
for(i=0;i<n;i++)
{
printf("x[%d]=",i);
scanf("%d",&v);
x[i]=v;
printf("y[%d]=",i);
scanf("%d",&v);
y[i]=v;
}
v=prodscalar(x,y,n);
printf("Produsul scalar = %d\n",v);
}

588
;ASM 11
; Produsul scalar a doi vectori
.model small
.stack 100h
.code
public _prodscalar
_prodscalar proc
push bp
mov bp,sp
mov cx,[bp+8] ; Numarul de elemente
mov si,[bp+4] ; Adresa primului vector
mov di,[bp+6] ; Adresa celui de-al doilea vector
xor bx,bx
ciclu:
; Bucla repetata de cx ori
mov ax,[si] ; bx+=[si]*[di];
mul word ptr [di]
add bx,ax
inc si
inc si
inc di
inc di
loop ciclu
mov ax,bx
; ax=bx (rezultatul)
pop bp
ret
_prodscalar endp
end

//C12
/*
Suma elementelor unei matrice.
*/
#include <stdio.h>
#define N 5
extern int suma(int x[][N],int m,int n);
void main(void)
{
int x[3][N],v;
int i,j,m,n;
printf("numarul de linii = ");
scanf("%d",&m);
printf("numarul de coloane = ");
scanf("%d",&n);
for(i=0;i<m;i++)
for(j=0;j<n;j++)
{
printf("x[%d][%d]=",i,j);
scanf("%d",&v);
x[i][j]=v;
}
printf("suma elementelor matricii = %d\n",suma(x,m,n));

589
}
;ASM 12
; Suma elementelor unei
.model small
.stack 100h
.code
c equ 5
public _suma
_suma proc
push bp
mov bp,sp
mov bx,[bp+4]
xor ax,ax
mov dx,[bp+6]
c1:
mov cx,[bp+8]
xor si,si
c2:
add ax,[bx][si]
inc si
inc si
loop c2
add bx,c*2
dec dx
jnz c1
pop bp
ret
_suma endp
end

matrici

; Numarul de coloane al matricii

; Adresa primului element


; ax=0
; Numarul de linii
; Numarul de coloane
; si=0
; ax+=[bx][si]
; Urmatorul element
; Mai sunt coloane ?
; Urmatoarea linie
; Mai sunt linii ?

//C13
/*
Realizarea unei functii specificate de utilizator (min
sau max) asupra a doua numere introduse de la consola.
Se realizeaza cu aplelu unei functii asm care primeste
ca parametru
functia dorita.
*/
#include <stdio.h>
extern int suma(int*,int*,int(*)(int,int),int);
int max(int a,int b)
{
return a>b?a:b;
}
void main(void)
{
int x[40],y[40],n,i,v;
printf("n=");
scanf("%d",&n);
for(i=0;i<n;i++)

590
{
printf("x[%d]=",i);
scanf("%d",&v);
x[i]=v;
printf("y[%d]=",i);
scanf("%d",&v);
y[i]=v;
}
printf("Suma elementelor maxime = %d\n",suma(x,y,max,n));
}
;ASM 13
; Suma elementelor maxime din doi vectori de elemente
; Functia de comparare e transmisa ca parametru
; (o adresa near)
.model small
.stack 100h
.data
rez dw 0
.code
public _suma
_suma proc
push bp
mov bp,sp
mov cx,[bp+10]
; Numarul de elemente
mov di,[bp+6]
; Adresa celui de-al doilea vector
mov si,[bp+4]
; Adresa primului vector
ciclu:
mov ax,[si]
mov bx,[di]
call word ptr [bp+8] c,ax,bx ; Apel functie de comparare
add rez,ax
; rez+=max
inc si
; Urmatoarele elemente din vectori
inc si
inc di
inc di
loop ciclu
mov ax,rez
; ax<-rez
pop bp
ret
_suma endp
end

Celelalte programe realizeaz prelucrri care evideniaz modaliti de


dezvoltare software conform programrii mixte.
n cazul n care se dorete gestionarea strict a ciclurilor main n
secvene de program cu structuri repetitive imbricate n care numrul
de referiri ale unei secvene este foarte mare, se prefer dezvoltarea
unui program mixt n care secvena referit este scris direct n limbaj
de asamblare. De exemplu, secvena:

591
...
s=0;
for (i=0; i<30000; i++)
for (j=0; j<70000; j++)
for (k=0; k<20000; k++)
if(i= =j)
s+=k*2;
else
s+=k/2;
...

se transform n secvena mai performant de mai jos:


...
s=0;
for (i=0; i<30000; i++)
for (j=0; j<70000; j++)
for (k=0; k<20000; k++)
{
asm mov bx, k
asm mov ax, i
asm cmp ax, j
asm jz egal
asm shr bx
asm egal: nop
asm shl bx
asm mov ax, s
asm add ax, bx
asm mov s, ax
}
...

Blocul instruciunilor limbajului de asamblare


delimiteaz cu atributul asm, obinndu-se secvena echivalent
asm

17.3 Concluzii

{
mov bx, k
mov ax, i
cmp ax, j
jz egal
shr bx
egal: nop
shl bx
mov ax, s
add ax, bx
mov s, ax
}

se

592

Programarea mixt are ca obiective att creterea performanei


programelor n execuie, ct i reutilizarea de software verificat n
practic, din diferite generaii, scris n limbaje de programare mai
puin utilizate n prezent.
De asemenea prin programarea mixt se integreaz programele
scrise n orice limbaj de programare formnd un produs software
complex.

593

18
DEZVOLTAREA DE APLICAII ORIENTATE
OBIECT IN LIMBAJ DE ASAMBLARE
18.1. Concepte folosite n dezvoltarea programelor orientate obiect
O clas este definit ca abstractizare a trsturilor eseniale ale unei colecii
de obiecte nrudite. Deci o clas este o mulime de obiecte care partajeaz o
structur comun i un comportament comun. Se extinde astfel conceptul datelor
de tip structur, combinndu-se datele cu codul ce le proceseaz.
O clas are dou componente, una static i alta dinamic. Prima
component se refer la proprietile obiectelor caracterizate de clas, i este
reprezentat de datele membre (cmpurile cu nume care posed valoare i care
caracterizeaz starea obiectului n timpul execuiei). A doua se refer la
comportamentul obiectelor clasei, deci la modul n care acioneaz i reacioneaz
acestea, i este constituit din metodele clasei respective.
Un obiect este definit ca materializarea sau concretizarea tipologiei descrise
de o anumit clas. El este un concept, abstractizare sau lucru cu limite precizate i
cu neles pentru problema n cauz.
Clasa

Obiect1

Obiect2

Figura 18.1 Relaia dintre o clas i obiectele ei


Relaia dintre o clas i obiectele acesteia este echivalent relaiei dintre o
variabil i tipul acesteia, subliniindu-se astfel ideea c obiectele i clasa ce le
definete nu sunt altceva dect un model mai avansat de variabile i o extensie a
tipurilor fundamentale specifice fiecrui limbaj. Fiecare obiect preia ablonul
impus de clasa de care aparine, ablon ce descrie caracteristicile sale (componenta
static, reprezentat de date), precum i operaiile ce sunt permise asupra acestora
(interfaa obiectului, descris prin metodele clasei). Operaia de creare a unui obiect
din informaiile exprimate de o clas, se numete instaniere, iar operaia invers

594

(definirea unei clase pornind de la o mulime de obiecte) poart numele de


clasificare sau tipizare.
Prin intermediul metodelor, orice obiect este o entitate dinamic care poate
fi creat, utilizat i distrus. Ca metode cu semnificaie deosebit, atrag atenia
constructorii i destructorii. Aa cum ne sugereaz i denumirea, constructorii
sunt acele operaii apelate pentru crearea obiectelor i iniializarea strii lor, n timp
ce destructorii realizeaz operaia invers, tergnd spaiul de memorie ocupat de
metodele i datele membre ale acestora.
Acest mod de organizare a datelor i a metodelor, de manipulare a acestora,
face apel la o serie de concepte precum abstractizarea, motenirea i
polomorfismul.
Abstractizarea reprezint procesul de ignorare intenionat a detaliilor
nesemnificative i reinerea proprietilor definitorii ale unei entiti. Astfel, se
ascund detaliile de implementare, dezvluindu-se, prin intermediul interfeei
obiectului, comportarea esenial a acestuia relativ la viziunea exterioar pe care
vrea s o imprime creatorul clasei.
ncapsularea este mijlocul de separare a informaiilor de manipulare a
unei entiti (aspectele externe, accesibile utilizatorului acesteia) de informaiile de
implementare. Ea poate fi ntlnit i n alte tehnici de programare cum este, spre
exemplu, modularizarea programelor prin folosirea bibliotecilor. Prin intermediul
acesteia se realizeaz protejarea anumitor date membre ale obiectelor mpotriva
distrugerii lor accidentale, ajungndu-se n acest fel la o robustee ridicat a
programelor n implementarea orientat obiect comparativ cu cea tradiional.
Motenirea se definete ca fiind o relaie ntre clase prin intermediul
creia o clas partajeaz structura i comportamentul definite de una sau mai multe
clase. n funcie de numrul claselor de la se pornete motenirea, cunoscute sub
numele de clase de baz sau superclase, putem avea motenire simpl (cnd
avem o singur clas de baz) sau motenire multipl (cnd se folosesc
caracteristicile mai multor clase). Clasa rezultant se numete subclas sau clas
derivat.

595

Structura clasei derivate


Clasa de
baza 1

Clasa de
baza 2

C la sa
de
baza 1

C lasa
de
baza 2

Clasa
derivat

Date i
metode clasa
derivata . . . .

Figura 18.2 Motenirea multipl


Polimorfismul este capacitatea unei entiti de a mbrca mai multe
forme. n programarea clasic, funciile se difereniaz prin numele sub care sunt
cunoscute, parametri pe care i accept, precum i valoarea pe care o returneaz. n
programarea orientat obiect compilatorul poate s fac diferena ntre funcii i
prin intermediul clasei de care aparin.
Funcii care au acelai nume, parametri i valoare de retur n clasa de baz,
pot fi redefinite (suprancrcate) n clasele derivate i ajustate la noul context n
care sunt apelate. Acest tip de polimorfism poart denumirea de polimorfism de
motenire.
n cadrul polimorfismului ad-hoc, de care aparine cel menionat mai sus,
se regsete i polimorfismul coerciziune care este caracteristic limbajelor de
programare care dispun de faciliti de conversie intern ntre tipuri.
Un alt tip de polimorfism este i polimorfismul parametric, dar care
apelnd la capacitatea compilatoarelor tradiionale de a face diferena dintre funcii
cu nume i valoare de retur identice, dar cu tip i / sau numr de parametri diferit,
nu aparine neaprat de programarea orientat obiect.
Alturi de aceste concepte mai este adugat i cel de persisten a
obiectelor. Acesta se refer la timpul de via al unui obiect, la capacitatea acestuia
de a permite salvarea pe un suport de memorie extern i de reconstituire ulterioar
n memoria intern a calculatorului. Realizarea acestei cerine presupune
identificarea clasei obiectului din informaiile salvate i construirea dinamic (n
timpul execuiei) a acestuia, aciune ce necesit metode avansate de programare
cum ar fi RTTI (Run-Time Type Identification - identificarea tipului n timpul
execuiei) i folosirea metodelor virtuale.

596

Prin apelarea la aceste concepte, programarea orientat obiect aduce o serie


de avantaje:
reutilizabilitate se permite reutilizarea codului deja testat i se crete,
astfel, robusteea programelor concomitent cu diminuarea duratei de
realizare a acestora;
scderea complexitii fragmentarea aplicaiei n entiti i relaii,
care au neles pentru utilizator, este o analiz convenional i o tehnic
de design, care duce la o diminuare semnificativ a complexitii iniiale
a problemei studiate.
flexibilitate prin intermediul motenirii se permite adugarea sau
extragerea de obiecte, fr schimbri profunde n logica aplicaiei,
realizndu-se astfel o extindere sau o acomodare a aplicaiei cu minim
de efort.
nelegere mai uoar punerea n coresponden unu la unu a
obiectelor din structura aplicaiei cu cele ale problemei studiate duce la
o nelegere mai uoar a fenomenelor att de ctre utilizator ct i de
ctre proiectant.
Toate aceste avantaje au ca rezultat o cretere a productivitii i a uurinei
n ntreinere a aplicaiilor orientate obiect, ceea ce impune tehnica de elaborare a
programelor orientat obiect ca soluia optim pentru programatori i proiectani de
sisteme.
Orice tip de dat elementar sau derivat i orice mecanism de gestionare a
resurselor unui sistem de calcul se regsesc mai nti n descriptorii respectivi,
funcii i operaii n limbaj de asamblare.
Dezvoltarea de aplicaii orientate obiect face excepie numai aparent de la
aceast cerin. Proprietile obiectelor sunt implementate mai nti n limbajele
evoluate (cum ar fi C++, Pascal) i corespondenele lor n modulele obiect sunt
suplinite de proprietile i funciile primare deja existente n limbajul de
asamblare.
n [SWAN95] se prezint modalitatea de dezvoltare a aplicaiilor orientate
obiect fr ca limbajul de asamblare s conin atribuite, structuri specifice definirii
de clase i manipulrii de obiecte.
Pentru descrierea mai multor modaliti de implementare a programrii
orientate obiect n limbajul de asamblare, se va face apel la reprezentarea tipurilor
de date ntregi i complexe i a metodelor de manipulare a acestora. S-a ales astfel
un exemplu simplu care s uureze nelegerea i urmrirea codului prezentat,
tehnicile folosite fiind uor de extins la orice aplicaie real.

597

18.2. Definirea obiectelor prin structuri


Una dintre cele mai simple metode de implementare a obiectelor n limbajul
de asamblare este folosirea regulilor de construcie a structurilor simple, fr
folosirea unor construcii specifice orientate obiect.
Se consider o aplicaie n care se manipuleaz numere ntregi i numere
complexe (s-au ales numerele ntregi n locul celor reale pentru o simplificare a
codului). Se definete mai nti o clas care s ncapsuleze comportamentul
numerelor ntregi i, derivat din aceasta, una care s defineasc comportamentul
numerelor complexe.
Pentru fiecare din cele dou clase se definesc operaiile de adunare i de
nmulire (cele de scdere i de mprire sunt asemntoare). Pentru clasa Integer
se dezvolt urmtoarele proceduri:
...
.code
adunare_integer proc
push ax
mov ax, [di].nr_int
add ax, word ptr [si]
mov [di].nr_int, ax
pop ax
retn
adunare_integer endp
inmultire_integer proc
push ax
mov ax, [di].nr_int
mul word ptr [si]
mov [di].nr_int, ax
pop ax
retn
inmultire_integer endp
...

Numrul implicat n adunare / nmulire este trimis prin adres prin registrul
SI, iar adresa obiectului este trimis prin registrul DI.
Pentru clasa Complex procedurile sunt:
...
adunare_complex proc
push ax
mov ax, [di].nr_int
add ax, word ptr [si]
mov [di].nr_int, ax
mov ax, [di].nr_complex

598
add ax, word ptr [si+2]
mov [di].nr_complex, ax
pop ax
retn
adunare_complex endp
inmultire_complex proc
.data
int_temp dw 0
.code
push ax
mov ax, [di].nr_complex
mul word ptr [si+2]
mov bx, ax
mov ax, [di].nr_int
mul word ptr [si]
sub ax, bx
mov int_temp, ax
mov ax, [di].nr_complex
mul word ptr [si]
mov bx, ax
mov ax, [di].nr_int
mul word ptr [si+2]
add ax, bx
mov [di].nr_complex, ax
mov ax, int_temp
mov [di].nr_int, ax
pop ax
retn
inmultire_complex endp
...

Numrul complex este format din dou date membre, nr_int i nr_complex,
adunarea i nmulirea fiind definite astfel:
(a , a ) (b , b ) (a b , a b )
1 2
1 2
1
1 2
2
(a , a ) (b , b ) (a b a b , a b a b )
1 2
1 2
1 1
2 2 1 2
2 1

Transmiterea parametrilor se face prin adresa din registrul SI ([SI] = partea


ntreag de adunat / nmulit, iar [SI+2] = partea imaginar), iar adresa obiectului se
trimite prin registrul DI.
Dup definirea procedurilor urmeaz definirea obiectelor:
...
.data
Integer struc
nr_int
adun_int
dw

dw
0
adunare_integer

599
inm_int
Integer ends
Complex struc
baza
nr_complex
adun_compl
inm_compl
Complex ends

dw

inmultire_integer

Integer <>
dw
0
dw
adunare_complex
dw
inmultire_complex

...

Obiectele sunt definite ca nite structuri obinuite, avnd ca membri att


datele ct i pointeri spre metode. Obiectul Complex este derivat din obiectul
Integer prin definirea unei date membre de tip Integer (baza Integer <>).
Pentru rularea celor dou clase se poate construi un cod de genul celui
urmtor:
...
ob_integer Integer <4>
ob_complex Complex <7,5>
numar1
dw
10
numar2
dw

.code
start:
mov ax,@data
mov ds,ax
lea

si, numar1

;[si] = numar1, [si+2] = numar2

lea
call
call
lea
call

di,ob_integer
ob_integer.adun_int
;nr_int = 4+10 = 14
ob_integer.inm_int ;nr_int = 14*10 = 140
di,ob_complex
ob_complex.adun_compl
;nr_int = 7+10 = 17
;nr_complex = 5+5 = 10
call ob_complex.inm_compl
;nr_int = 17*10-10*5 = 120
;nr_complex = 17*5+10*10 = 185
sfarsit:
mov ax,4c00h
int 21h
end start

Instanierea claselor se face ca n cazul structurilor obinuite. Se observ c


naintea apelurilor procedurilor este necesar ncrcarea n registrele SI i DI a
parametrilor i a obiectelor asupra crora se efectueaz operaia.
Pentru verificarea corectitudinii calculelor se ncarc programul executabil,
rezultat prin asamblarea codului de mai sus, n turbo debugger dac se folosete

600

asamblorul oferit de firma Borland. Pentru aceasta trebuie ca programul s fie


asamblat i link-editat cu urmtoarele comenzi:
tasm /zi <nume_program.asm>
tlink /v <nume_program.obj>

18.3. Definirea obiectelor prin macrodefiniii


Limbajul de asamblare conine faciliti de definire a macrodefiniiilor.
Macrodefiniiile sunt construcii realizate cu ajutorul unor cuvinte cheie al cror
efect const ntr-un proces de expandare n textul programului surs, permindu-se
n acest mod definirea n mod simbolic a unor secvene de program (instruciuni,
definiii de date, directive etc.), asociate cu un nume.
Macrodefiniiile sunt structuri complexe n care se includ i elemente ale
macroexpandrii condiionale, repetitive, recursive i stringizare (vezi lucrrile
[SOMN92], [MUS96]). Un aspect foarte important de care trebuie sa se in cont n
utilizarea macroinstruciunilor este faptul c ele sunt procesate ntr-o faz
preliminar asamblrii.
Pentru definirea structurilor necesare modelrii orientate obiect, precum i a
motenirii i ncapsulrii datelor acestora, exist i varianta folosirii
macrodefiniiilor. Macrodefiniiile sunt deosebit de utile n realizarea programelor
orientate obiect, putnd fi folosite construcii speciale de verificare a restriciilor
care s genereze eventualele erori nu n timpul execuiei programului, ci n faza de
analizare sintactic a codului surs, exact ca n limbajele de nivel nalt orientate
obiect.
n continuare se prezint un model de implementare a obiectelor n limbajul
de asamblare, ce face apel la un sistem de simboluri variabile, construite prin
stringizare, folosite mpreun cu elemente macrocondiionale pentru verificarea
restriciilor impuse de modelul obiectual. Sintaxa rezultat prezint asemnri
evidente cu limbajele de nivel nalt orientate obiect, n special cu limbajul C++.
Mai nti este necesar definirea unor date i a unor variabile simbolice
folosite n cadrul macrodefiniiilor (semnificaia acestora va rezulta ulterior, pe
parcursul descrierilor din paginile urmtoare):
; V1.0
.data
currOffset dw 0 ;offsetul obiectului apelator pt. o
;functie din aceeasi clasa
;VARIABILE DE CONSTRUIRE (GENERALE)
currProt = 0
;implicit
public
(folosita
in
declaratiile ;claselor)
currId = 0
;id-ul curent (id-ul primei clase = 1)
currClass = 0
;(nici o clasa initial)
currApelator = 0 ;apelatorul curent al operatiei (id-ul
;obiectului)

601
Id = 1
;folosita de OBJECTS
gasit = 0
;folosita la cautarea in clase de baza
deplasament = 0
;deplasamentul folosit in cazul ;accesarii
unor variabile din
;clasele de baza
baseId = 0
;id-ul clasei de baza la cautarea datelor
;membre
publicDer = 1
;indica
daca
derivarea
se
face
;public (=1) sau private (=0)
;VARIABILE CARE DEPIND DE CLASE (de numele clasei sau de idul ei)
;<numeClasa>Id
id-ul clasei cu numele <numeClasa>
;<numeObiect>Id
id-ul obiectului (EGAL ;INTOTDEAUNA
CU ID-UL CLASEI
;
DE CARE APARTINE!)
;no<Id>
nr elementelor din clasa cu id-ul
<id>
;baseNo<Id>
nr claselor de baza pentru ;clasa cu
id-ul <id>
;disable<Id>Prot
indica daca se foloseste sau nu
;protectia datelor
;
(folosita
in
apelul
functiilor
;membre)
;friend<Id>Of<currId>Id indica, daca exista, prietenia ;intre
clasele cu
;
id-urile <Id> si <curcId>
;depl<baseId>In<currId> indica deplasarea clasei de baza (
<baseId> ) in clasa
;
cu id-ul <currId>

Pentru definirea unei clase se folosete macrodefiniia class cu urmtoarea


sintax:
class <nume_clasa>
...
<nume_clasa> ends

Aceast macrodefiniie ncapsuleaz o structur standard, iniiind i o serie


de simboluri variabile ce vor fi folosite la identificarea clasei:
class MACRO nume
IFB <nume>
%OUT < **Error** Class name not specified ... >
.ERR
ELSE
;genereaza clasa
%OUT < Creating class nume ... >
currId = currId + 1
;id-ul urmator
fi +1
nume&Id = currId
;id-ul de clasa
;creaza variabila ce contine nr de elemente
setBaseAndNoToZero
%currId

va

602
;creaza variabila de control a protectiei
;clasei
setDisableProt
%currId, 0
;initial protectia
este ;activata
nume struc

;creaza structura

ENDIF
ENDM

n cazul n care nu se precizeaz un nume pentru clas se genereaz eroare.


n caz contrar acest nume va fi folosit pentru declararea structurii, nu nainte ca idul clasei (format prin stringizare din numele clasei i irul de caractere Id) se fie
stabilit n mod secvenial cu ajutorul variabilei simbolice <currId>. Astfel, toate
clasele vor avea un numr de identificare distinct (ncepnd cu 1).
Macrodefiniia class se folosete de alte dou macrodefiniii. Una dintre
aceste este setBaseAndNoToZero:
setBaseAndNoToZero MACRO id
baseNo&id = 0
No&Id = 0
ENDM

care se folosete de parametrul transmis (<id> = id-ul clasei) pentru a stabili


numrul de clase de baz (baseNo<id>) i numrul de elemente (No<Id>) ale
clasei definite ca fiind zero.
Alt macrodefiniie folosit este setDisableProt:
setDisableProt MACRO id, val
disable&id&Prot = val
ENDM

cu ajutorul creia se creeaz o variabil de protecie a datelor ce va fi


folosit n macrodefiniiile urmtoare (prin transmiterea parametrului val cu
valoarea 0 protecia este activ).
Protecia membrilor clasei se realizeaz cu ajutorul variabilei simbolice
<currProt> a crei valoare se poate modifica cu macrodefiniiile urmtoare:
public_ MACRO
currProt = 0
ENDM
private_ MACRO
currProt = 1
ENDM

Pentru declararea datelor membre avem urmtoarele macrodefiniii:

603
date MACRO den, tip, v
internDate %currId, den, tip, <v>
ENDM
internDate MACRO id, den, tip, v
No&id = No&id + 1
;alocare data
IFB <v>
den&id&@val@ tip ?
ELSE
den&id&@val@ tip v
ENDIF
;alocare protectie
IFE currProt
;; public
%OUT < define den as public ... >
ELSE
%OUT < define den as private ... >
ENDIF
den&id&Prot = currProt
ENDM

Deci se folosete macrodefiniia date cu urmtoarea sintax:


date nume_data, tip_standard, [valoare]

Cu ajutorul acestei macroinstruciuni se aloc o variabil de un anumit tip


(precizat prin parametrul <tip>) care are un nume modificat (format prin
stringizare sub ablonul <den><id_clasa>@val@) fa de cel indicat de utilizator)
cu scopul de restricionare a accesului direct. Totodat se crete numrul de
elemente ale clasei i se definete o variabil (<den><id_clasa>Prot) prin care se
va reine protecia asupra datei introduse.
Declararea metodelor membre se face n mod asemntor folosindu-se
sintaxa:
func nume_rutina

iar macrodefiniiile folosite sunt:


func MACRO den
internFunc %currId, den
ENDM
internFunc MACRO id, den
No&id = No&id + 1
IFE currProt
;; public
%OUT < define function den as public ... >
ELSE
%OUT < define function den as private ... >
ENDIF

604
den&id&FuncProt = currProt
ENDM

Aceste macrodefiniii nu fac altceva dect s creasc numrul de elemente


ale clasei (No<id_clasa>) i s stabileasc protecia pentru procedura respectiv
(<den><id_clasa>FuncProt). n cadrul structurii nu este necesar reinerea vreunei
evidene a procedurii (pointer), rutina respectiv fiind identificat printr-un nume
ce depinde de identificatorul obiectelor clasei respective. Pentru definirea funciei
(dup declararea claselor) se folosete urmtoarea sintax:
classFunc nume_clasa, nume_rutina
...
endFunc
nume_clasa, nume_rutina

ce are ca suport urmtoarele macrodefiniii:


classFunc MACRO ob,fun
incepProc %(ob&Id), fun
;scoate temporar protectia pt datele din aceeasi clasa
setDisableProt %(ob&Id), 1
ENDM
incepProc MACRO id, fun
currApelator = id
;folosit in functiile prietene
currId = id
fun&id&@func@ proc
ENDM
endFunc MACRO ob,fun
;repune protectia
setDisableProt %(ob&Id), 0
;se iese din functie
currApelator = 0
currId = 0
ret
sfarProc %(ob&Id), fun
ENDM
sfarProc MACRO id, fun
fun&id&@func@ endp
ENDM

Se ncepe prin stabilirea unor variabile simbolice pentru identificarea


obiectului n al crui context se vor executa instruciunile din rutina
(<currApelator>, folosit pentru accesul la datele claselor pentru care clasa curent
a fost declarat ca prieten, i <currId> pentru accesul la datele membre clasei).
Dup care se declar nceputul procedurii (se remarc numele schimbat al
procedurii: <denumirea_functiei><id_clasa>@func@) i se ntrerupe, pe
parcursul ntregii rutine, protecia datelor membre (deoarece se ruleaz n contextul
clasei) prin setarea pe 1 a variabilei disable<id_clasa>Prot. Sfritul procedurii, pe

605

lng ncheierea efectiv a rutinei, repune protecia i reseteaz variabilele


simbolice folosite la identificarea contextului.
Declararea unei clase ca prietene a alteia (cu acces complet asupra datelor
membre) se realizeaz prin definirea unei variabile simbolice cu ajutorul
macrodefiniiei friend:
friend MACRO clase
IRP cl,clase
friend2 <cl>
%OUT < Class cl became friend of current class ... >
ENDM
ENDM
friend2 MACRO cl
friend3 %(cl&Id), %currId
ENDM
friend3 MACRO id, currId
friend&id&of&currId = 1
;defineste variabila
;de prietenie
ENDM

Pentru motenire simpl sau multipl, s-au folosit urmtoarele


macrodefiniii (motenirea este realizat doar pentru un singur nivel, dar poate fi
extins prin folosirea de macrodefiniii recursive):
publicExt MACRO b
IRP den,b
publicDer = 1
;mostenire publica
makeBaseName1 %currId, den
%OUT < Current class is derived from den ... >
ENDM
ENDM
privateExt MACRO b
IRP den,b
publicDer = 0
;mostenire private
makeBaseName1 %currId, den
%OUT < Current class is derived from den ... >
ENDM
ENDM
makeBaseName1 MACRO currId, den
baseNo&currId = baseNo&currId + 1
makeBaseId currId, %(baseNo&currId), %(den&Id)
makeBaseName2 %(baseNo&currId), currId, %(den&Id), den
ENDM
;macro-uri interne pentru extend
makeBaseId MACRO currId, currBaseNo, baseId
;creeaza
;variabila id a bazei
baseNo&currBaseNo&Of&currId&Id = baseId
ENDM
makeBaseName2 MACRO currBaseNo, currId, baseId, den

606
;aloca obiectul de baza
baseNo&currBaseNo&@base@ den <>
;calculeaza deplasamentul fata de clasa derivata
depl&baseId&In&currId = OFFSET baseNo&currBaseNo&@base@
;mostenire publica
IF publicDer
;declara clasa derivata ca prietena a clasei de baza
friend3 currId, baseId
ENDIF
ENDM

Se crete mai nti numrul de clase de baz ale clasei curente


(baseNo<id_clasa>), apoi se trece la definirea unei variabile de identificare a clasei
de baz (baseNo<nr_baza>Of<id_clasa> = <id_baza>) i la declararea efectiv a
structurii clasei de baz n cea derivat (cu numele schimbat
baseNo<nr_baza>@base@) i a deplasrii acesteia n cadrul clasei derivate
(depl<id_baza>In<id_clasa>). Pentru accesul la toate datele clasei de baz (n
cazul motenirii publice) se face apel la un artificiu: se declar clasa derivat ca o
clas prieten a clasei de baz.
Dup cum s-a artat, datele membre ale unei clase au numele modificat i
deci necunoscut pentru utilizator. Pentru accesul la acestea, prin verificarea
proteciei i cutarea n clasele de baz, s-au construit urmtoarele macrodefiniii:
set MACRO ob, camp, v
;verifica daca suntem intr-o functie membra (nu se mai
specifica
;
obiectul)
IFB <v>
operStanga movToOb, %currId, currOffset, ob, camp
ELSE
mov currOffSet,OFFSET ob
operStanga movToOb, %(ob&Id), currOffset, camp, v
ENDIF
IFE gasit
;nu s-a gasit
%OUT < **Error** camp is not a member of ob ... >
.ERR
ELSE
gasit = 0
;pt. urmatoarele cautari se revine
;la 0
ENDIF
deplasament = 0
ENDM
get MACRO unde, ob, camp
;verifica daca suntem intr-o functie membra (nu se mai
;specifica
;
obiectul)
IFB <camp>
operDreapta movFromOb, unde, %currId, currOffset, ob
ELSE

607
mov currOffSet,OFFSET ob
operDreapta movFromOb, unde, %(ob&Id), currOffSet, camp
ENDIF
IFE gasit
;nu s-a gasit
%OUT < **Error** camp is not a member of ob ... >
.ERR
ELSE
gasit = 0
;pt. urmatoarele cautari se revine
;la 0
ENDIF
deplasament = 0
ENDM
operStanga MACRO oper, id, ob, camp, v
IFDEF camp&id&@val@
;se afla direct in ;clasa?
;s-a gasit si se face operatia in functie de protectie
isProt? id, camp
oper id, ob, camp, v
gasit = 1
;l-a gasit
ELSE
;NU, poate se afla intr-o
;clasa de baza
;CAUTARE IN CLASELE DE BAZA:
searchInBase %(baseNo&id), id, camp
IF gasit
;se introduce operatia propriu-zisa
;baseId va contine id-ul la care s-a ajuns in
;cautare
;si a carui clasa cuprinde variabila
isProt? %baseId, camp
;vede
daca
este
;protejata
;in clasa derivata
oper %baseId, ob, camp, v
ENDIF
ENDIF
ENDM
operDreapta MACRO oper, unde, id, ob, camp
IFDEF camp&id&@val@
;se afla direct in ;clasa?
;s-a gasit si se face operatia in functie de protectie
isProt? id, camp
oper unde, id, ob, camp
gasit = 1
;l-a gasit
ELSE
;NU, poate se afla intr-o
;clasa de baza
;CAUTARE IN CLASELE DE BAZA:
searchInBase %(baseNo&id), id, camp
IF gasit
;se introduce operatia propriu-zisa
;baseId va contine id-ul la care s-a ajuns in
;cautare
;si a carui clasa cuprinde variabila

608
isProt? %baseId, camp
;protejata

;vede

daca

este

;in clasa derivata


oper unde, %baseId, ob, camp
ENDIF
ENDIF
ENDM
movToOb MACRO id, ob, camp, v
push bx
mov bx,word ptr ob
mov DS:[bx][deplasament].&camp&id&@val@, v
pop bx
endm
movFromOb MACRO unde, id, ob, camp
push bx
mov bx,word ptr ob
mov unde, DS:[BX][deplasament].&camp&id&@val@
pop bx
endm

Aceste macrodefiniii, n cazul gsirii variabilelor, verific protecia


acestora cu ajutorul macroinstruciunii:
isProt? MACRO id, den
isProt?2 id, den, %currApelator
ENDM
isProt?2 MACRO id, den, currApelator
;verifica daca suntem intr-o functie a unei clase
;prietene
IFNDEF friend&currApelator&of&id
;verifica daca se folosesc protectiile
IFE disable&id&Prot
IF den&id&Prot
%OUT < **Error** Member &den is not accesible ... >
.ERR
ENDIF
ENDIF
ENDIF
ENDM

n cazul negsirii variabilei n clasa curent se realizeaz cutarea ei n


primul nivel de derivare cu ajutorul macrodefiniiei:
searchInBase MACRO no, id, camp
noCurr = 1
REPT no
;cauta in toate clasele de baza
searchInBase2 %noCurr, id, camp
IF gasit
;l-a gasit si op. e deja
;introdusa
EXITM
;se iese din macrourile ;recursive

609
ENDIF
noCurr = noCurr + 1
ENDM
ENDM
searchInBase2 MACRO noCurr, currId, camp
baseId = baseNo&noCurr&Of&currId&Id
searchInBase3 currId, %baseId, camp
ENDM
searchInBase3 MACRO currId, baseId, camp
searchInBase4 camp&baseId&@val@
IF gasit
;la gasit si se calculeaza deplasamentul in
;functie de baseId
addDeplas %(depl&baseId&In&currId)
ENDIF
ENDM
searchInBase4 MACRO den
IFDEF den
;data
cu
denumirea
den
a
fost
;definita
gasit = 1
ENDIF
ENDM
addDeplas MACRO deplCurr
deplasament = deplasament + deplCurr
ENDM

Aceste macrodefiniii, n cazul gsirii variabilei, seteaz <gasit> pe 1 i


ncarc <baseId> cu identificatorul clasei n care aceasta a fost gsit. Totodat se
calculeaz i deplasamentul clasei de baz n derivat (folosit de funciile de acces
la membru).
Pentru apelul procedurilor membre mecanismul este acelai, chiar
simplificndu-se datorit necalculrii deplasamentului (pentru apel s-au construit
macrodefiniii run, isFuncProt?, searchFuncInBase). De asemenea, pentru
accesul la datele membre se pot imagina i funcii mai complicate, cum ar fi aflarea
adresei sau alte operaii directe fr preluarea coninutului ntr-un registru.
Pentru exemplificarea utilizrii acestor macrodefiniii se va folosi exemplul
numerelor reale i complexe prezentat n prima variant de implementare:
.model large
include object.asm
.stack 100h
class Integer
public_
date
nr_int, dw, 0
func
Adunare
func
Inmultire
Integer ends
class Complex

;partea intreaga

610
publicExt <Integer>
public_
date
nr_complex, dw, 0 ;partea complexa
func
Adunare
func
Inmultire
Complex ends
.code
;DEFINIREA METODELOR
classFunc Integer, Adunare
push ax
get ax, nr_int
add ax, word ptr [si]
set nr_int, ax
pop ax
endFunc
Integer, Adunare
classFunc Integer, Inmultire
push ax
get ax, nr_int
mul word ptr [si]
set nr_int, ax
pop ax
endFunc
Integer, Inmultire
classFunc Complex, Adunare
push ax
get ax, nr_int
add ax, word ptr [si]
set nr_int, ax
get ax, nr_complex
add ax, word ptr [di]
set nr_complex, ax
pop ax
endFunc
Complex, Adunare
classFunc Complex, Inmultire
push ax
push bx
get ax, nr_complex
mul word ptr [di]
mov bx, ax
get ax, nr_int
mul word ptr [si]
sub ax, bx
push ax
get ax, nr_complex
mul word ptr [si]
mov bx, ax
get ax, nr_int
mul word ptr [di]
add ax, bx

611
set nr_complex, ax
pop ax
set nr_int, ax
pop bx
pop ax
endFunc
Complex, Inmultire

Se observ modul de definire al claselor asemntor celui existent n


limbajul C++. Clasa Complex este motenit din clasa Integer (publicext
<Integer>) ceea ce i asigur i partea ntreag.
Numele procedurilor nu mai trebuie s fie diferit ca n exemplul anterior
(deoarece numele procedurilor este format i din identificatorul clasei),
polimorfismul fiind realizat prin cutarea mai nti n clasa curent a procedurii i
apoi n cele de baz. n cadrul procedurilor accesul la datele membre se face prin
funciile get i set (obiectul nu mai trebuie precizat, se ia obiectul n contextul
cruia are loc execuia). Parametrii se trimit prin adres prin registrele SI i DI.
Adresa obiectului nu mai trebuie trimis ca n varianta anterioar, macrodefiniiile
folosindu-se de identificatorii obiectelor pentru a identifica structurile i funciile
corespunztoare.
Pentru testare se poate folosi urmtoarea surs:
.data
define ob_integer, Integer
define ob_complex, Complex
numar1
dw
10
numar2
dw
5
.code
start:
mov ax,@data
mov ds,ax
set ob_integer, nr_int, 4
set ob_complex, nr_int, 7
set ob_complex, nr_complex, 5
lea
run
run
lea
run
run

si, numar1
ob_integer,
ob_integer,
di, numar2
ob_complex,
ob_complex,

sfarsit:
mov ax,4c00h
int 21h
end start

Adunare
Inmultire
Adunare
Inmultire

612

Instanierea claselor se face prin macrodefiniia define. Valorile iniiale ale


datelor membre se pot seta prin instruciunea set (trebuie precizat obiectul de care
aparin datele membre). naintea apelului procedurilor de adunare i nmulire, se
ncarc n registrele SI i DI adresele numerelor folosite pentru aceste operaii.
Rezultatele acestor apeluri se regsesc n noile valori ale datelor membre.
Pentru verificarea operaiilor se procedeaz identic ca n cazul variantei
anterioare (se folosete opiunea /zi pentru asamblare i opiunea /v pentru linkeditare dup care se verific valorile membrilor celor dou obiecte prin execuie
pas cu pas n turbo debugger).
La compilarea acestui program se va obine urmtorul listing:
E:\TOOLS\TASM\WORKING>tasm intcomp2
Turbo Assembler
Version 4.1
Copyright
Borland International

(c)

1988,

1996

Assembling file:
intcomp2.ASM
< Creating class Integer ... >
< define nr_int as public ... >
< define function Adunare as public ... >
< define function Inmultire as public ... >
< Creating class Complex ... >
< Current class is derived from Integer ... >
< define nr_complex as public ... >
< define function Adunare as public ... >
< define function Inmultire as public ... >
Error messages:
None
Warning messages: None
Passes:
1
Remaining memory: 422k

Macrodefiniiile realizeaz o serie de afiri prin care indic structura


claselor create i eventualele erori.
Dac se ncearc schimbarea definiiei clasei Integer n urmtoarea (nr_int
devine private):
class Integer
private_
date
nr_int, dw, 0
public_
func
Adunare
func
Inmultire
Integer ends

;partea intreaga

macrodefiniiile vor semnala o serie de erori datorit ncercrii de iniializare a


prii ntregi prin instruciunile set (set ob_integer, nr_int, 4 i set ob_complex,
nr_int, 7) de dup instanierea obiectelor:

613
E:\TOOLS\TASM\WORKING>tasm intcomp2
Turbo Assembler
Version 4.1
Copyright
Borland International

(c)

1988,

1996

Assembling file:
intcomp2.ASM
< Creating class Integer ... >
< define nr_int as private ... >
< define function Adunare as public ... >
< define function Inmultire as public ... >
< Creating class Complex ... >
< Current class is derived from Integer ... >
< define nr_complex as public ... >
< define function Adunare as public ... >
< define function Inmultire as public ... >
< **Error** Member nr_int is not accesible ... >
< **Error** Member nr_int is not accesible ... >
**Error** intcomp2.ASM(96) ISPROT?2(8) User error
**Error** intcomp2.ASM(97) ISPROT?2(8) User error
Error messages:
2
Warning messages: None
Passes:
1
Remaining memory: 422k

Se observ c apar dou erori, una pentru set-ul pe clasa Integer, iar alta
pentru cel pentru clasa derivat Complex. Dac cele dou instruciuni set se terg,
procesul de compilare nu va mai semnala nici un fel de eroare, ceea ce
demonstreaz faptul c accesarea datelor membre private din cadrul procedurilor de
adunare i nmulire sunt corecte datorit apartenenei acestor rutine la cele dou
clase.
18.3.1. Optimizarea codului generat de macrodefiniii
Aa cum se va arta spre sfritul capitolului, codul generat de
macrodefiniii n varianta actual este ineficient. Spre exemplu, secvena de
macroinstruciuni:
set
lea
run
run

ob_integer, nr_int, 4
si, numar1
ob_integer, Adunare
ob_integer, Inmultire

va genera urmtoarele instruciuni:


mov currOffSet,offset ob_integer
push bx
mov bx,word ptr currOffset
mov [bx][deplasament].nr_int1@val@, 4
pop bx

614
lea si, numar1
mov currOffset,offset ob_integer
call Adunare1@func@
mov currOffset,offset ob_integer
call Inmultire1@func@

Dup cum se observ, pentru indicarea instanei curente (cea asupra creia
se realizeaz operaiile) se folosete o dat de tip word, currOffset. Aceasta se
ncarc n mod repetat n registrul BX, deoarece ntre instruciunile prezentate pot
exista i alte instruciuni care afecteaz acest registru. n consecin, codul rezultat
din expandarea macroinstruciunilor este departe de a fi optim.
O optimizare foarte uor de fcut, este aceea de a sacrifica un registru (aa
cum n cazurile anterioare s-a folosit registrul SI), care urmeaz s ia locul
variabilei currOffset, dar care nu mai poate fi utilizat dect cu precauie de ctre
utilizator (trebuie salvat n stiva nainte de blocul de operaii n care se folosete i
restaurat nainte de folosirea uneia dintre macroinstruciuni). Pentru aceasta s-a ales
registrul BX, pentru c acesta oricum se folosete la adresarea bazat din cadrul
macrodefiniiilor set i get.
Dup modificare, macrodefiniiile get i set devin:
;setare valoare
set MACRO ob, camp, v
;verifica daca suntem intr-o functie membra (nu se ;mai
specifica obiectul)
IFB <v>
operStanga movToOb, %curId, curOffset, ob, camp
ELSE
mov bx,OFFSET ob
operStanga movToOb, %(ob&Id), ob, camp, v
ENDIF
IFE gasit
;nu s-a gasit
%OUT < **Error** camp is not a member of ob ... >
.ERR
ELSE
gasit = 0
;pt. urmatoarele cautari se
;revine la 0
ENDIF
deplasament = 0
ENDM
;incarcare valoare
get MACRO unde, ob, camp
;verifica daca suntem intr-o functie membra (nu se ;mai
specifica obiectul)
IFB <camp>

615
operDreapta movFromOb, unde, %curId, curOffset,
ob
ELSE
mov bx,OFFSET ob
operDreapta movFromOb, unde, %(ob&Id), ob, camp
ENDIF
IFE gasit
;nu s-a gasit
%OUT < **Error** camp is not a member of ob ... >
.ERR
ELSE
gasit = 0
;pt. urmatoarele cautari se
;revine la 0
ENDIF
deplasament = 0
ENDM

De asemenea, i macroinstruciunile movToOb i movFromOb folosite


indirect (prin intermediul lui operDreapta i operStanga) sufer modificri,
nemaifiind necesar ncrcarea n registrul bx a offset-ului:
movToOb MACRO id, camp, v
mov [BX][deplasament].&camp&id&@val@, v
endm
movFromOb MACRO unde, id, camp
mov unde, [BX][deplasament].&camp&id&@val@
endm

n mod asemntor se procedeaz i pentru macrodefiniiile folosite la


apelul funciilor. Odat fcute aceste modificri, codul generat pentru secvena de
instruciuni prezentat mai sus, se va micora, producnd o cretere semnificativ
de vitez de execuie:
mov bx,offset ob_integer
mov [bx][deplasament].nr_int1@val@, 4
lea si, numar1
mov bx,offset ob_integer
call Adunare1@func@
mov bx,offset ob_integer
call Inmultire1@func@

616

Optimizarea s-a produs pentru funcia set prin preluarea direct a


deplasamentului n registrul BX. O optimizare ce mai poate fi adus codului, dar
care duc la o scdere a transparenei implementrii obiectelor, este ncrcarea
explicit n registrul BX a deplasamentului instanei curente. Astfel, nu ar mai fi
necesar ncrcarea repetat a deplasamentului dup cum se observ n codul
urmtor:
mov bx,offset ob_integer
mov [bx][deplasament].nr_int1@val@, 4
lea si, numar1
call Adunare1@func@
call Inmultire@funct@

Fcndu-se aceste simple modificri codul rezultat n urma expandrii va fi


asemntor cu cel oferit de prima variant, cea care folosete structuri simple, dar
va oferi n plus ncapsulare, motenire i polimorfism, toate realizate n faza de
asamblare. n acest mod, viteza de execuie a programelor scrise n cele dou
variante va fi identic, dar avantajele oferite de cea de-a doua implementare vor fi
net superioare.
18.4. Folosirea specificaiilor proprii limbajului de asamblare
ncepnd cu versiunea 3.0, asamblorul produs de firma Borland conine
elementele fundamentale ce permit programarea orientat obiect n limbaj de
asamblare, i anume structurile de tip clas. n Turbo Assembler, datele i codul se
pot ncapsula n declaraii speciale de tip STRUC, numite clase. O clas (numit
clas derivat) poate moteni codul i datele unei alte clase (numit clas de baz).
Subrutinele clasei, sau metodele, pot fi statice (apelate direct) sau virtuale (apelate
prin cutarea adresei subrutinei ntr-o tabel a metodelor virtuale).
Sintaxa unei declaraii de clas este:
<nume> STRUC <modificator> <nume_clasa> METHOD {
declaraii metode
}
declaraii date membre
ENDS <nume_clasa>

unde modificator poate fi NEAR sau FAR, nsoit sau nu de directiva GLOBAL.
Declaraia metodelor clasei are urmtoarea sintax:
[virtual] nume_metoda : tip = nume_eticheta

617

Numele metodei nu este supus restriciei de unicitate, ca n cazul declaraiilor de


membri ai tipului de date STRUC. Numele etichetei prin care este implementat
metoda trebuie s fie unic. Tipul poate fi WORD sau DWORD.
Un exemplu de implementare a unei clase n limbaj de asamblare orientat
obiect:
GLOBAL Baza_constructor: PROC
GLOBAL Baza_actiune: PROC
Baza STRUC GLOBAL METHOD{
constructor:WORD = Baza_constructor
VIRTUAL actiune:WORD = Baza_actiune
}
x
DD
0.0
ENDS Baza

Urmtoarele declaraii definesc dou obiecte ale clasei Baza, cu iniializare


sau fr:
DATASEG
b1
Baza
b2
Baza

<1.1>
< >

Prin folosirea motenirii se creeaz clase noi din cele deja existente. Clasa
derivat este o copie a clasei de baz la care se pot aduga noi metode sau
variabile. Metodele adugate pot fi complet noi sau le pot nlocui pe cele cu acelai
nume n clasa de baz. n plus, metodele din clasa nou pot apela metodele din
clasa de baz pe care le nlocuiesc. Nu se pot nlocui date ale clasei de baz.
n continuare se prezint un exemplu de implementare a unei clase derivate
din cea anterioar, n limbaj de asamblare orientat obiect:
GLOBAL Deriv_constructor: PROC
GLOBAL Deriv_actiune: PROC
Deriv STRUC GLOBAL Baza MEHOD{
constructor:WORD = Deriv_constructor
VIRTUAL actiune:WORD = Deriv_actiune
}
TBLPTR
y
DD
0.0
ENDS Deriv

Metodele virtuale difer de metodele statice prin modul n care sunt


adresate. n loc s calculeze adresa unei metode virtuale la asamblare, asamblorul
genereaz instruciuni care extrag adresa la momentul execuiei din VMT.
Apelurile metodelor virtuale sunt indirecte, fiind fcute prin referin la intrrile
dintr-o VMT.

618

Inserarea uneia sau mai multor metode virtuale ntr-o declarare a unei clase
se realizeaz prin prefaarea declarrii metodei cu cuvntul cheie VIRTUAL. Apoi,
n seciunea de date a clasei se insereaz un pointer la VMT folosind directiva
TBLPTR.
Cuvntul cheie TBLINST declar o instan a tabelei metodelor virtuale
(VMT), definind spaiul n memorie pentru aceasta. Simpla declarare a unei
instane VMT nu realizeaz i iniializarea pointerului la VMT pentru diversele
obiecte ale respectivei clase.
DATASEG
TBLINST

La urmtorul pas, pentru fiecare obiect n parte se include n constructorul


su instruciunea TBLINIT <adresa>, unde adresa poate fi un registru sau o locaie
de memorie.
PROC

Deriv_constructor
TBLINIT Deriv PTR si

ret
ENDP Deriv_constructor

Pointerul la metoda static constructor este iniializat cu adresa subrutinei


asociate, i anume Deriv_constructor. Constructorul clasei trebuie apelat pentru
toate obiectele clasei. Fiecare astfel de obiect are pointerul propriu la VMT, care
trebuie iniializat individual. Apelarea constructorului se realizeaz ca i pentru
oricare alt metoda static. De exemplu, n segmentul de date, se definete mai
nti un obiect:
DATASEG
d1
Deriv

< >

n segmentul de cod, se adreseaz d1 prin intermediul ds:si i se apeleaz


constructorul clasei:
CODESEG
mov si, offset d1
CALL si METHOD Deriv:constructor

Apelarea metodei virtuale actiune din clasa Baza se exemplific n


continuare:
CODESEG
mov si, offfset b1
CALL Baza PTR si METHOD Baza:actiune

619

Dac SI adreseaz un obiect al unei clase derivate, atunci subrutina actiune


a clasei derivate este apelat. Astfel, n secvena de mai jos, dei instruciunea
CALL...METHOD specific Baza, instruciunea de fapt apeleaz metoda actiune a
clasei derivate.
CODESEG
mov si, offset d1
CALL Baza PTR si METHOD Baza:actiune

Aceasta este o dovad a polimorfismului, proces prin care se creeaz clase


care folosesc metode virtuale pentru a selecta aciuni la momentul execuiei. Deci
obiectul nsui determin care metod virtual s fie apelat.
n anumite cazuri, apelul de forma CALL...METHOD se poate nlocui cu
JMP...METHOD pentru a optimiza metodele care se termin cu apeluri ctre alt
metode.
Pentru a apela o funcie virtual a clasei de baz din interiorul unei funcii
virtuale a clasei derivate se folosete un apel de funcie static. De exemplu, n
metoda virtual actiune din clasa derivat Deriv se apeleaz metoda virtual
actiune din clasa de baz Baza:
PROC

Deriv_actiune
call Baza_actiune
ret
ENDP Deriv_actiune

n continuare se reia exemplul numerelor ntregi i complexe pentru


exemplificarea acestei variante.
Mai nti este necesar folosirea unor directive:
IDEAL
JUMPS
LOCALS @@
MODEL large, PASCAL
STACK 1000h
. . . . .

Directiva IDEAL selecteaz modul de lucru Ideal al turbo asamblorului.


Acest mod face ca membrii structurilor s fie locali acestora, ceea ce ne permite s
avem nume de date membre identice n structuri diferite. Acest mod impune
folosirea directivei GLOBAL pentru metode.
Cea de-a doua directiv, JUMPS, permite salturi condiionale automate,
fcnd posibil generarea unui cod mai eficient din partea asamblorului. Directiva
LOCALS @@ previne o serie de conflicte rezultate din folosirea variabilelor cu
acelai nume la nivel global i la nivel de procedur. Prin MODEL large, PASCAL
se declar modelul de memorie ca fiind large i folosirea modului de transmitere al

620

parametrilor ca n Pascal (parametrii sunt transmii n ordinea n care sunt


declarai), mai potrivit programrii orientate obiect n limbajul de asamblare. STACK
1000h declar mrimea stivei.
Urmeaz codul n care se declar ablonul oferit de cele dou clase i
procedurile din cadrul acestora:
...
GLOBAL
GLOBAL
GLOBAL
GLOBAL

Int_Adunare: PROC
Int_Inmultire: PROC
Complex_Adunare: PROC
Complex_Inmultire: PROC

STRUC Integer METHOD{


Adunare:WORD = Int_Adunare
Inmultire:WORD = Int_Inmultire
}
nr_int
DW
0
ENDS Integer
CODESEG
PROC Int_Adunare
ARG @@int:word
USES ax
mov ax, [@@int]
add ax, [(Integer PTR si).nr_int]
mov [(Integer PTR si).nr_int], ax
ret
ENDP Int_Adunare
PROC Int_Inmultire
ARG @@int:word
USES ax
mov ax, [@@int]
mul [(Integer PTR si).nr_int]
mov [(Integer PTR si).nr_int], ax
ret
ENDP Int_Inmultire

STRUC Complex Integer METHOD{


Adunare:WORD = Complex_Adunare
Inmultire:WORD = Complex_Inmultire
}
nr_complex DW
0
ENDS Complex
PROC Complex_Adunare

621
ARG @@int:word, @@compl:word
USES ax
CALL si METHOD Integer:Adunare, [@@int]
mov ax, [@@compl]
add ax, [(Complex PTR si).nr_complex]
mov [(Complex PTR si).nr_complex], ax
ret
ENDP Complex_Adunare
PROC Complex_Inmultire
ARG @@int:word, @@compl:word
USES ax, bx
mov ax, [@@compl]
mul [(Complex PTR si).nr_complex]
mov bx, ax
mov ax, [@@int]
mul [(Complex PTR si).nr_int]
sub ax, bx
push ax
mov ax, [@@compl]
mul [(Complex PTR si).nr_int]
mov bx, ax
mov ax, [@@int]
mul [(Complex PTR si).nr_complex]
add ax, bx
mov [(Complex PTR si).nr_complex], ax
pop ax
mov [(Complex PTR si).nr_int], ax
ret
ENDP Complex_Inmultire
...

Fiecare metod a unei clase trebuie s lucreze cu o anumit instan a clasei


respective. Aceast instan poate fi transmis metodei prin oricare din modurile de
transmitere a parametrilor, dar prin convenie se transmite adresa acesteia prin
perechea de registre DS:SI. De aceea accesul la o dat membr n cadrul unei
metode a clasei se face prin (<nume_clasa> PTR si).<nume_camp>.
Parametrii sunt transmii prin stiv, iar extragerea acestora se face prin
directiva ARG, urmat de numele dat parametrului i tipul acestuia. Folosirea
prefixului @@ n numele parametrilor face ca acetia s devin locali procedurii i
s nu fie confundai cu parametrii globali cu acelai nume. Se face uz de directiva
USES prin care se indic regitrii ce vor fi folosii, urmnd ca asamblorul s includ
push-urile i pop-urile necesare pentru revenirea la valorile iniiale ale acestor
regitri.
Pentru folosirea acestor clase se face apel la datele i operaiile de test
prezentate i la celelalte dou variante:

622
...
DATASEG
ob_integer Integer <4>
ob_complex Complex <7, 5>
CODESEG
start:
mov ax,@data
mov ds,ax
mov si,
CALL si
CALL si
mov si,
CALL si
CALL si

offset
METHOD
METHOD
offset
METHOD
METHOD

ob_integer
Integer:Adunare, 10
Integer:Inmultire, 10
ob_complex
Complex:Adunare, 10,5
Complex:Inmultire, 10,5

sfarsit:
mov ax,4c00h
int 21h
end start

naintea apelurilor procedurilor se ncarc n registrul SI deplasamentul


instanei. Parametrii au fost transmii prin specificarea unor constante dup numele
procedurii (numele este cel din cadrul clasei i nu cel efectiv) n cadrul
instruciunilor CALL. n locul acestor constante se puteau specifica i identificatori
de regitri sau zone de memorie.
18.5. Analiza comparativ a variantelor de implementare a obiectelor
Fiecare dintre cele trei variante de implementare a obiectelor n limbajul de
asamblare are att avantaje ct i dezavantaje. Prima variant, cea prin care se
foloseau structuri simple, este uor de folosit i nu necesit nici un fel de construcii
speciale. Prezint ns o serie de deficiente: nu asigur o protecie a datelor i
metodelor, n cazul motenirii multiple apare problema deplasamentelor datelor
membre ale claselor de baz, indicarea obiectelor se face explicit prin ncrcarea
ntr-un registru a adreselor, lipsesc elementele avansate de programare orientat
obiect, cum este polimorfismul, clasele prietene i funciile virtuale.
Cea de-a doua variant, se remarc printr-o transparen mare a
mecanismelor de implementare a obiectelor, ceea ce poate uura substanial munca
programatorului, precum i prin optimalitatea codului datorit folosirii
macrodefiniiilor (dureaz mai mult compilarea, dar codul executabil rezultat este
optim). Sintaxa a fost construit s semene ct mai mult cu cea folosit de limbajul
C++, cu care majoritatea programatorilor sunt familiarizai. Varianta prezentat nu
suport motenirea pe mai multe niveluri (dar care nu este imposibil de realizat

623

datorit existenei construciilor macro recursive i repetitive) i nici funciile


virtuale, care necesit cod efectiv (nu numai macroinstruciuni) folosit n timpul
executrii programului. De asemenea, este necesar scrierea tuturor acestor
macroinstruciuni i includerea lor n fiierele surs.
Ultima variant, care folosete construcii speciale orientate obiect specifice
implementrii propuse de firma Borland, acoper multe din aspectele programrii
orientate obiect. n plus fa de celelalte dou variante, ofer folosirea funciilor
virtuale. Trebuie inut cont c aceast implementare este specific doar produsului
realizat de firma Borland i, deci, nu reprezint un standard. Asambloarele oferite
de alte firme nu cuprind aceste construcii, iar dac se dorete un cod surs
compatibil (cu att mai mult cu ct chiar sintaxa oferit de Borland poate suferi
schimbri) trebuie fcut apel la alte variante. De asemenea, la fel ca n prima
variant, indicarea instanelor nu se face la fel de uor ca n cea de-a doua metod,
ci prin ncrcarea explicit a adreselor n regitri. Sintaxa nu permite o verificare
complet a codului chiar nainte de link-editare, ca n cazul variantei folosirii
macrodefiniiilor, erorile fiind uneori greu de depistat, iar efectul acestora apare
doar n timpul execuiei.
Pentru o comparaie mai profund a celor trei variante de implementare,
trebuie calculai i o serie de indicatori, cum ar fi: numrul de instruciuni scrise,
numrul efectiv de instruciuni folosite de asamblor, timpul de execuie pentru o
problem dat etc.
Pentru a afla valorile unor astfel de indicatori n fiecare din variante trebuie
apelat la un alt exemplu dect cel prezentat anterior. Astfel, pentru aflarea duratei
de execuie trebuie construit un exemplu de calcul care necesit un timp de
execuie mai lung, i astfel cuantificabil. Se va lucra tot pe cele dou clase
prezentate n paginile de mai sus, dar pentru testarea operaiilor acestora se va opta
pentru un cod ciclic. Ca numr de iteraii s-a optat pentru 10.000.000, ceea ce face
ca timpul de execuie s fie de ordinul zecilor de secunde. n cadrul unei iteraii se
realizeaz nmuliri pentru ambele clase, utilizndu-se datele de test deja
prezentate.
Pentru prima variant, cea care folosete doar structuri simple, noul cod va
fi urmtorul:
; vechea poriune de cod prin care se declara clasele
; si operaiile acestora ...
...
contor1
dw
2000
contor2
dw
5000
10.000.000 de iteraii
.code
start:
mov ax,@data
mov ds,ax

2000

5000

624
lea
mov
next1:
push
mov
next2:
mov
mov
mov

si, numar1

;[si] = numar1, [si+2] = numar2

cx, contor1
cx
cx, contor2
ob_integer.nr_int, 4
ob_complex.nr_int, 7
ob_complex.nr_complex, 5

lea di, ob_integer


call ob_integer.inm_int
lea di, ob_complex
call ob_complex.inm_compl
loop next2
pop cx
loop next1
sfarsit:
mov ax,4c00h
int 21h
end start

Pentru varianta n care se folosesc macroinstruciuni, noul cod va fi:


; vechea poriune de cod prin care se declara clasele
; si operaiile acestora ...
...
contor1 dw 2000
contor2 dw 5000
; 2000 x 5000 = 10.000.000
iteraii
.code
start:
mov ax,@data
mov ds,ax
lea si, numar1
lea di, numar2
mov cx, contor1
next1:
push cx
mov cx, contor2
next2:
set ob_integer,
set ob_complex,
set ob_complex,
run ob_integer,
run ob_complex,
loop next2
pop cx

nr_int, 4
nr_int, 7
nr_complex, 5
Inmultire
Inmultire

de

625
loop next1
sfarsit:
mov ax,4c00h
int 21h
end start

Iar pentru ultima variant, n care se folosete implementarea Borland,


codul folosit pentru testare va fi:
; vechea poriune de cod prin care se declara clasele
; si operaiile acestora ...
...
contor1
dw
2000
contor2
dw
5000
; 2000 x 5000 = 10.000.000 ;de
iteraii
CODESEG
start:
mov ax,@data
mov ds,ax
mov cx, contor1
next1:
push cx
mov cx, contor2
next2:
mov si, offset ob_integer
mov [(Integer PTR si).nr_int], 4
CALL si METHOD Integer:Inmultire, [numar1]
mov si, offset ob_complex
mov [(Complex PTR si).nr_int], 7
mov [(Complex PTR si).nr_complex], 5
CALL si METHOD Complex:Inmultire, [numar1], [numar2]
loop next2
pop cx
loop next1
sfarsit:
mov ax,4c00h
int 21h
end start

Folosindu-se aceste secvene de cod se obin indicatori att cantitativi, ct i


calitativi referitori la cele trei variante implementate, tabelul 18.5.

626

Tabelul 18.1. Analiza comparativ a celor trei variante


Varianta ce folosete
Varianta
macroinstruciuni
ce
Indicator
folosete Variant
Varianta
structuri
a
optimizat
simple
iniial
Linii de cod
95
93
93
scrise
Linii de cod
asamblate (dup
95
147
96
expandare)
Linii de cod
folosite n
73
124
73
timpul execuiei
Timpul de
execuie
20
37
22
(secunde)
ncapsulare
(protecia

membrilor)

Implementarea
Borland orientat
obiect
100
121

81

27

Motenire

Polimorfism

Funcii virtuale

18.5.1. Analiza indicatorilor rezultai


Tabelul prezint patru indicatori, trei referindu-se la numrul liniilor de cod
(ceea ce n limbaj de asamblare este echivalent cu numrul instruciunilor), iar
ultimul este timpul de execuie exprimat n secunde. Primul indicator se refer la
numrul de linii scrise de programator (neincluznd codul surs al
macrodefiniiilor), n timp ce al doilea reflect numrul de instruciuni dup
efectuarea expandrilor macrodefiniiilor. Al treilea indicator cuprinde doar
instruciunile ce intervin n mod activ n timpul execuiei (se elimin unele
instruciuni cum ar fi etichetele, directivele de compilare etc.). Analiza se poate
dezvolta apelndu-se la lungimile n octei a instruciunilor. Dup aceti patru
indicatori se indic existena sau inexistena a patru concepte fundamentale ale
programrii orientate obiecte: ncapsulare, motenire, polimorfism i funcii
virtuale.

627

Prima variant de implementare prezint cele mai puine linii de cod i cel
mai mic timp de execuie. Acest lucru este explicat prin lipsa celor mai elementare
concepte ale programrii orientate obiect (implementarea nu ofer nici mcar o
protecie a datelor sau polimorfism). Tot ceea ce scrie programatorul se reflect n
mod identic n codul surs supus asamblrii, singura abatere de la programarea
tradiional n cod de asamblare o constituie includerea pointerilor ctre proceduri
n cadrul structurilor.
Cea de-a doua metod de implementare este prezentat n cele dou
variante, observndu-se ctigul substanial de vitez al formei optimizate. Aceasta
se apropie ca performan de metoda care folosete structuri simple (22 de secunde
de execuie fa de 20), oferind n plus programatorului ncapsulare, polimorfism i
motenire multipl. Prima variant este mult mai lent datorit folosirii unei date
suplimentare pentru deplasare n cadrul structurilor i a salvrilor repetate n stiv a
registrului BX. Dar, aceasta ofer un grad mai ridicat de ncapsulare. Utilizatorul
macroinstruciunilor nu este supus nici unor restricii n folosirea registrului BX,
care n cazul variantei optimizate trebuie salvat i restaurat de fiecare dat innd
cont c i codul expandat de macrodefiniii folosete acest registru. De asemenea,
varianta a doua, din motive de optimizare a codului, necesit ncrcarea explicit n
registrul BX a instanei asupra creia se lucreaz, ceea ce duce la creterea
probabilitilor de apariie a erorilor.
Ultima variant de implementare, cea oferit de firma Borland, ofer
performane medii i acest lucru se explic prin modul n care sunt tratai
parametrii procedurilor. Acetia sunt transmii prin stiv, iar pentru folosirea lor se
rezerv regitri care trebuiesc salvai nainte de ncrcare i restaurai la ieirea din
procedur. Pentru a urmri codul generat, s lum procedura de adunare a
numerelor complexe:
PROC Complex_Adunare
ARG @@int:word, @@compl:word
USES ax
CALL si METHOD Integer:Adunare, [@@int]
mov ax, [@@compl]
add ax, [(Complex PTR si).nr_complex]
mov [(Complex PTR si).nr_complex], ax
ret
ENDP Complex_Adunare

Macrodefiniiile ARG i USES introduc urmtoarele modificri codului de


mai sus:
PROC Complex_Adunare
PUSH
BP
MOV
BP,SP
PUSH
AX

628
CALL si METHOD Integer:Adunare, [@@int]
mov ax, [@@compl]
add ax, [(Complex PTR si).nr_complex]
mov [(Complex PTR si).nr_complex], ax
POP
AX
POP
BP
ret
ENDP Complex_Adunare

Pentru accesul la variabilele din stiv, trebuie salvat vechea valoare a


registrului BP, care va fi folosit pentru accesarea stivei ( mov BP, AX). Urmeaz
salvarea registrului AX folosit pentru preluarea uneia dintre variabile. naintea
revenirii din procedur se restaureaz vechile valori ale regitrilor AX i BP. Pentru
reutilizarea codului, este apelat metoda de adunare din clasa de baz, care, la
rndul ei, va relua secvena de salvri i restaurri de regitri. Toate aceste operaii
duc la o ncetinire semnificativ n execuie atunci cnd apelurile de proceduri sunt
folosite frecvent. Regitrii, cum sunt AX i BX, sunt salvai n mod repetat cu toate
c pstrarea vechilor valori nu prezint importan. Din acest punct de vedere,
aceast metod se aseamn cu prima variant a implementrii prin
macroinstruciuni, oferind un grad mare de transparen i securitate, dar i o
ncetinire a calculelor.
Alegerea uneia dintre variante trebuie fcut n strns corelaie cu
problema de rezolvat:
dac se dezvolt cod relativ mic, care se dorete a fi rapid se opteaz
pentru prima variant;
dac sunt necesare facilitile de motenire, ncapsulare sau polimorfism
pentru probleme mai complexe, dar pentru care timpul de execuie este
critic, se va opta pentru varianta optimizat ce folosete
macroinstruciuni;
dac codul rezultat trebuie s fie sigur, punndu-se accentul pe
securitatea oferit n timpul execuiei i mai puin pe timpul de execuie,
implementarea Borland orientat obiect sau prima variant ce folosete
macrodefiniii se dovedesc alegerile viabile;
dac se doresc secvene de program complexe, care apeleaz la lucrul cu
pointeri spre obiecte ale cror tipuri sunt cunoscute abia n timpul
execuiei, cea mai buna alegere este implementarea Borland care ofer
suport pentru funcii virtuale.
Fiecare variant este optim pentru anumite tipuri de probleme i cerine ale
acestora, programatorului revenindu-i responsabilitatea alegerii. Prima variant este
simpl i nu necesit nici un fel de efort suplimentar, dar lipsurile acesteia sunt
evidente cnd se dezvolt programe complexe. Variantele ce folosesc
macrodefiniii necesit scrierea sau procurarea acestora, iar implementarea oferit
de firma Borland este recunoscut doar de asamblorul acesteia.

629

19
STRUCTURI DE PROGRAME
O structur de program se memoreaz n segmente de date (x), segmente de
stiv (y) i segmente de cod (z) i este definit prin tripletul (nx, ny ,nz), unde:
nx numrul de segmente de date;
ny numrul de segmente de stiv;
nz numrul de segmente de cod.
n continuare se prezint tipurile principale de structuri de program att prin
plasarea n memorie (segmente) ct i n raport cu raporturile dintre proceduri.
19.1 Programul ca singur secven (0, 0, 1)
Aceast structur de program de tip monolit este caracteristic problemelor
simple, crora li se d soluie de ctre un singur programator. Operanzii (variabilele
simple, masivele, tipurile derivate) se definesc n acelai segment n care se afl
secvena de instruciuni executabile.
Programul ca singur secven corespunde i construciilor elaborate de
ctre programatorii nceptori care nu au capacitatea de a structura la nivel de
proceduri sau secvene apelabile, operaii complexe cu caracter repetitiv. Tot att
de bine, acest mod de a soluiona o problem este specific i programatorilor care
urmresc minimizarea salturilor necondiionate, generate de apelurile de proceduri
(instruciunea call) i de revenirile la procedura apelatoare (instruciunea ret).

De exemplu, evaluarea funciei:

x+y+z+w

F(x,z,y,w)=
x2+y2+z2+w2

x>0
y>0
z>0
w>0

x<0
y<0
z<0

630

w<0
|x|+|y|+|z|+|w|

n rest

se efectueaz cu un program n care se definesc proceduri pentru :


ADD3 nsumarea a trei elemente;
PDW2 ridicarea la putere a unui numr;
MODUL calculul modulului unui numr.
Textele surs asociate procedurii pentru adunarea a 4 numere este:
ADD3

PROC ;
s=a+b+c+d
push bp
mov bp, sp
push ax
mov ax, [bp+4] a ;ax:=0
add ax, [bp+6] b ;ax:=ax+b
add ax, [bp+8] c ;ax:=ax+c
add ax, [bp+10] d ;ax:=ax+d
mov [bp+12], ax
;s:=ax
pop ax
pop bp
ret
endp

ncrcarea pe stiv a adreselor parametrilor reali nainte de efectuarea


apelului procedurii ADD3 se realizeaz:
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
call ADD3

;variabila unde se stocheaz suma

d;
c
b
a

Textul surs pentru ridicarea la ptrat a unui numr este:


POW2

proc
push bp
mov bp, sp
push ax

631
push dx
mov ax, [bp+4]
mul [bp+4]
mov [bp+6], ax
pop dx
pop ax
pop bp
ret
endp

Pentru evaluarea expresiei e=a*a, ncrcarea pe stiv a adresei parametrilor


este realizat astfel:
mov ax, offset a
push ax
mov ax, offset e
push ax
call POW2

Textul surs pentru procedura de calcul a modulului unui numr s=|a| este:
modul proc
push bp
mov bp,sp
push ax
mov ax, [bp+4]
neg ax
mov [bp+6], ax
pop ax
pop bp
ret
endp

Textul surs al programului cu apelarea celor trei proceduri este:


start:
mov ax, @data
mov ds, ax
cmp x, 0
jle alfa
cmp y, 0
jle alfa
cmp z, 0
jle alfa
mov ax offset fxyz
push ax
mov ax, offset w
push ax
mov ax, offset z
push ax

632
mov ax, offset y
push ax
mov ax, offset x
push ax
jmp suma
alfa:
cmp x, 0
jz beta
cmp y, 0
jz beta
cmp z, 0
jz beta
cmp w, 0
jz beta
mov ax, offset
push ax
mov ax, offset
push ax
call POW2
mov ax, offset
push ax
mov ax, offset
push ax
call POW2
mov ax, offset
push ax
call POW2
mov ax, offset
push ax
mov ax, offset
push ax
call POW2
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
jmp suma

xp
x

yp
y

zp

wp
w

s
wp
zp
yp
xp

beta:
mov ax, offset
push ax
mov ax, offset
push ax
call modul
mov ax, offset
push ax
mov ax, offset

mx
x

my
y

633
push ax
call modul
mov ax, offset
push ax
mov ax, offset
push ax
call modul
mov ax, offset
push ax
mov ax, offset
push ax
call modul
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax
mov ax, offset
push ax

mz
z

mw
w

s
w
mz
my
mx

suma:

end

call ADD3
...
;procedura pentru conversia de la binar la ir de caractere
;i reprezentare f(x, y, z, w)
...
mov 4c00h
int 21h
start
x
y
z
w
px
py
pz
pw
mx
my
mz
mw
s

dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw

2
3
4
1
?
?
?
?
?
?
?
?
?

Structura grafic a programului este dat n figura 19.1.

634

start
x>0
y>0
z>0
w>0
x=0

push

y=0
push
z=0
push

w=0
|x|

push

s=a+b+c+d

x2

|y|

y2

|z|

z2

|w|

w2

push

conversiepush
afisare

push
push

stop
push

push
push
push

635

Figura 19.1 Graficul asociat programului PP pentru


evaluarea funciei ntr-un punct folosind proceduri
Pentru eliminarea salturilor necondiionate impuse de apelurile procedurilor
se procedeaz la conturarea unui program numit PM ca un tot unitar, n care
secvenele alctuiesc o singur entitate, avnd textul surs:
...
cmp x, 0
jle alfa
cmp y, 0
jle alfa
cmp z, 0
jle alfa
cmp w, 0
jle alfa
add ax, z
add ax,y
add ax,x
mov s, ax
jmp imprimare
alfa: cmp x, 0
jz beta
cmp y, 0
jz beta
cmp z, 0
jz beta
cmp w, 0
jz beta
mov ax, x
mov mx, ax
neg mx
mov ax, y
mov my, ax
neg my
mov ax, z
mov mz, ax
neg z
mov ax, w
mov mw, ax
neg w
mov ax, mx
add ax, my
add ax, mz
add ax, mw
mov s, ax
jmp imprimare
beta: xar bx, bx

636
mov
mul
add
mov
mul
add
mov
mul
add
mov
mul
add
mov

ax, x
x
bx, ax
ax, z
y
bx, ax
ax, z
z
bx, ax
ax, w
w
bx, ax
s, ax

...

Dezavantajul programului PM este dat de faptul c se construiete de ctre


un singur programator. Programul n care se definesc proceduri se elaboreaz n
echipe de programatori, fiecrui programator revenindu-i sarcina de a elabora
simultan un numr proceduri i de a obine reducerea duratei de elaborare a
programului.
19.2 Programul din secvene distincte grupate ntr-un segment (1, 1, 1)
Acest tip de construcie este compus dintr-un segment de date, un segment
stiv i un segment de cod.
Segmentul de cod conine secvene referite instruciuni de apel
(instruciunea call). Evaluarea expresiei:
e=(a+min{xi}+max{xi})*(b+min{yi})-(c+max{wi})-(min{zi}+max{zi})
se realizeaz prin programul PEVAL al crui text surs este:
mov si, offset x
mov cx, n
mov bx, a
minim:
mov ax, [si]
ciclul1:
cmp ax, [si+2] minim
jle salt_1
mov ax, [si+2]
salt1:
inc si
inc si
loop ciclul1
ret
add bx, ax
; bx:=bx+min{xi}
mov cx, n

637
mov si, offset y
maxim:
mov ax, [si]
ciclul2:
cmp ax, [si+2]
jge
salt2
mov ax, [si+2] max
salt2;
inc si
inc si
loop ciclul2
ret
add bx, ax
mov e, bx
mov bx, b
mov si, offset y
mov cx, m
call minim
add bx, ax
mov si, offset y
mov cx, m
call maxim
add bx, ax
mov ax, e
mul bx
mov e, ax
mov ex2, dx
mov bx, c
mov si, offset w
mov cx, m
call maxim
add bx, ax
sub e, bx
sbc ex2, 0 e:=e-(c+max{xi})
mov si offset z
mov cx, k
call minim
mov bx, ax
mov si, offset z
mov cx, k
call maxim
add bx, ax
shl bx, 1
sub e, bx
sbc ex2, 0

Programului PEVAL i se asociaz secvenele:


Sx iniializri pentru operaii pe masivul x,
Smin gsire element minim;

638

Smax gsire element maxim;


Sy iniializri pentru operaii pe masivul y;
Se evaluri expresie Se;
Sw iniializri pentru operaii cu masivul w;
Sz iniializri pentru operaii pe masivul z.
Secvenele se activeaz astfel:
Sx Smin Sx Smax Se Sy Smin Sy Smax Se Sw Smin Se Sz Smin Sz
Smax Se.
Acest mod de structurare a secvenelor este asemntor construirii
programelor n limbajul BASIC, cu utilizarea instruciunilor GOSUB.

De asemenea, programatorii n limbajul COBOL


structureaz programele n paragrafe, delimitate prin etichete,
paragrafe pe care le refer cu instruciunea PERFORM.
Paragrafele se scriu n interiorul programului sau se poziioneaz dup
instruciunea STOP RUN. De exemplu, programul TAB pentru afiarea unui cap
de tabel avnd structura:

Denumire
(30)
0
Prod1
Prod2
Prod3

Cant
(4)
1
10
5
2

Pret unitar
(5)
2
2
3
13

Total
are textul surs:
rnd1
filler1
linii
rnd2
filler2
col21
denumire 2
col22
cant2
col23
pret2
col24

struc
db 10
db 60
ends
struc
db
db
db
db
db
db
db

db 10 dup ()
I
30 dup ()
,
4 dup ()
,
5 dup ( )
,

Valoare
(8)
3
20
150
26
196

639
valoare2
col25
rnd3
filler
col31
denumire3
col32
cant3
col33
pretunit3
col34
valoare3
col35

db 8 dup ( )
db ,
struc
db 10 dup ( )
db ,
db Denumire/30
db ,
db CANT
db ,
db PU
db ,
db valoare
db ,

Pentru afiarea capului de tabel se folosete secvena:


call
call
call
call
call
call
call
call
call

scrie-rand1
scrie-rand2
scrie_rand2
scrie_rand3
scrie_rand2
scrie_rand2
scrie_rand1
scrie_rand4 (I0I1I2I3)
scrie_rand1

Pentru afiarea datelor tabelului se folosete secvena:


mov cx, n (numr produse)
mov si offset vect_prod
ciclu:
.
. ;calcul valoare, total
. ;conversii
. ;call scrie_rnd5
.
loop ciclu
.
. ;conversie total
. ;mut n rnd 6 la coloana
. ;de total irul convertit
. ;call scrie_rnd6
.
mov ax, 4c00h
int 21h
serie_rnd1:
.
.
ret
serie_rnd2:

640
.
.
ret
serie_rnd6:
.
.
ret

Secvenele care se refer prin instruciunea call sunt dispuse dup


instruciunile care definesc transferul controlului programului ctre sistemul de
operare:
mov ax, 4c00h
ret 21h

19.3 Proceduri incluse n segmentul programului principal (1, 1, 1)


Aplicaia conine un segment de date, un segment pentru stiv i un
segment pentru cod.
Corespunde situaiei n care conductorul echipei de programatori
gestioneaz cu rigurozitate proiectul. El definete datele cu care se lucreaz,
structureaz aplicaia pe module (proceduri sau macrodefiniii) pentru a fi elaborate
simultan de ctre membrii echipei.
Dac A, B sunt matrice ptrate i C, D, G sunt vectori, evaluarea expresiei:
F=((A2+B)*C+D)*G

presupune scrierea de proceduri:


construirea unei matrice transpuse;
efectuarea produsului a dou matrice;
calcul produs matrice vector coloan;
adunarea a doi vectori;
calcul produs scalar a doi vectori.
eful echipei de programatori construiete segmentul de date:
Datele

seg
NCOL
NLIN
dw
dw
dw
dw
dw
dw
dw

DATE
EQU 4
EQU 4
7, 5, 8, 13
3, 1, 8, 6
1, 0, 3, 7
4, 5, 11, 2
2, 4, 9, 1
32, 2, 5, 7
4, 9, 7, 4

641
C
D
G
BT
A2
SUMA
VP
VS
i
j

dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
ends

3, 5, 21, 17
8, 3, 5, 2
6, 1, 1, 4
9, 11, 2, 5
NLIN dup (NCOL dup(?)) ;
NLIN dup (NCOL dup(0)) ;
NLIN dup (NCOL dup(0)) ;
NCOL dup(0)
;vector
NCOL dup(0)
;vector
?
?

B transpus
patratul lui A
A^2+B
produs
suma

Variabilele de lucru ale fiecrei proceduri se definesc ntre instruciunile


RET i ENDP.
Programatorul ef stabilete modul de transmitere a parametrilor i de
utilizare a regitrilor, dup cum urmeaz:
matricele i vectorii se folosesc ca variabile globale;
pentru referirea elementului aij al masivului bidimensional se folosete
macrodefiniia:
emw

macro a, n, i, j, poz
push ax
push bx
mov ax, i
mul ax, n
mov bx, j
add ax,bx
shl ax, 1
mov bx, offset a
add ax, bx
mov poz, ax
pop bx
pop ax
endm

pentru referirea elementului bj al unui masiv unidimensional se


folosete macrodefiniia:

evw

macro b, j, poz
push ax
push bx
mov ax, offset b
mov bx, j
shl bx, 1
add ax, bx
mov poz, ax
pop bx
pop ax

642
endm

se folosete adresarea indirect n care expresia de adresare este zon de


memorie

Programatorii lucreaz simultan la scrierea procedurilor. Astfel,


programatorul P1 scrie procedura pentru adunarea elementelor a doi vectori,
obinnd un al treilea vector:
Vsi:=Vpi+D

unde i=1,NCOL
Pentru procedurile de efectuare a produsului scalar, programatorul P2
elaboreaz n paralel cu ceilali componeni ai echipei procedura:
prodscal

ciclu:

proc
mov cx, NCOL-1
mov i,0
mov f,0
mov f+r, 0
evw vs,i, poz
mov ax, [poz]
evw g, i, poz
mul [poz]
add f, ax
adc f+2, dx
inc i
loop ciclu
ret

endp

Pentru transpunerea unei matrice, programatorul P3 scrie textul surs:


transp

proc
push ax
push cx
mov ax, NLIN
mov i, 0

ciclu1:
push cx
mov j, 0
mov cx, NCOL
ciclu2:
emw
mov
emw
mov
inc

b, i, j, NCOL, poz
ax, [poz]
bt, j, i, NLIN, poz
[poz], ax
j

643
loop ciclu2
pop cx
inc i
loop ciclu 1
pop cx
pop ax
ret
endp

Pentru adunarea a dou matrice AP i BT programatorul P4 scrie procedura:


admat

proc
push ax
push ax
mov ax, NLIN
mov i, 0

ciclu 1:
push cx
mov j, 0
mov cx, NCOL
ciclu 2:
emw AP, i, j, NCOL, poz
mov ax,[poz]
emw BT, i, j, NCOL, poz
add ax,[poz]
emw MS, i, j NCOL, poz
mov [poz], ax
inc j
loop ciclu 2
pop ax
inc d
loop ciclu 1
ret
endp

Programatorul ef scrie programul apelator:


call prodmat
call transp
call admat
call prodmv
call advec
call prodscal
call convert
call afisir
mov ax, 4c00h
int 21h
end start

644

Acest mod de a concepe un program vizeaz lucrul n paralel, figura 19.2,


intercalnd apelurile cu instruciuni de stocare pe stiv a listelor de parametri.

A1

A1
A2
A3
A4
A5
A6
A7

Ax+1

Figura 19.2 Paralelizarea programelor


n figur:

a1 definire segmentul de date


a2 elaborare procedura 1

at elaborare procedura n
at+1 elaboreaz programul apelator

Decizia de a utiliza variabile globale n proceduri restrnge


gradul de generalitate al procedurilor dar elimin lucrul pe stiv
cu parametrii simplificnd expresiile de referire ale operanzilor.
19.4 Definiri distincte pentru toate componentele (m, k, n)
n cazul aplicaiilor deosebit de complexe programatorul ef definete
structura pe module i variabile, ns nu mai poate impune restricii severe
colaboratorilor n ceea ce privete variabilele intermediare i structurarea
modulelor la nivel de proceduri i secvene.
Mai mult, pentru a lsa independen n procesul de testare a modulelor este
necesar ca fiecare programator s-i defineasc elementele specifice prii din
aplicaie aa fel nct s delimiteze precis momentul de nceput al lucrului,
respectiv, momentul de predare al modulelor. n acest fel se creeaz posibilitatea

645

trecerii la alt aplicaie i realizarea departajrii programatorilor dup nivelul


performanei individuale. Aplicaia complex presupune:
distribuirea modulelor;
construirea de segmente de date;
construirea de segmente de stiv;
construirea de segmente cu proceduri i cu program de test;
stabilirea corelaiilor dintre programatori i segmentele elaborate;
stabilirea interdependenei dintre proceduri;
stabilirea interdependenelor dintre segmentele de date i stive, respectiv
proceduri.
Se consider aplicaia GESTIUNE MATERIALE care conine urmtoarele
funcii, proceduri:
Pcre
creare fiier materiale prin adugare;
Pdel
tergere articol din fiier;
Padd adugare articol;
Pins
inserare articol;
Psort sortare fiier;
Pmodif modificare denumire material;
Pscrie scrie articol n fiier;
Pmdpr modificare pre material;
Pindv identificare articol dup o cheie;
Paprv aprovizionare cu o cantitate;
Pies
ieiri de materiale;
Psupra afiarea materialelor n stocuri supranormative;
Pfr afiarea stocurilor fr micare;
Pzero afiarea materialelor cu stoc zero;
Pval
calculul stocului final n expresie valoric.
Pentru rezolvarea acestei aplicaii se procedeaz astfel:
a) se definete structura articolului n segmentul SEGART
SEGART
SEG
mat
cod
den
UM
Pret
Stocin
Intrari
Iesiri
Val
Ends

struc
dw
db
dw
dw
dw
dw
dw
dw

?
30 dup (?)
?
?
?
?
?
?

b) Se stabilesc datele de test sub forma tabelului 19.1

646

Tabelul 19.1. Datele de test ale aplicaiei GESTIUNEA


MATERIALELOR
Cod
Stoc
Stoc
Valoa
Denumire UM Pre
Intrari Ieiri
matrial
iniial
final
re
1289
Tabl
Foi
1200 25
12
5
32
38400
5423
Cuie
Kg
150 10
15
7
19
2850
4566
Srm
Kg
230 50
20
25
45
10350
3689
Crmid Buc 50
500
700
300
900
45000
TOTAL
96600
c) Se stabilesc intrrile i ieirile modulelor.
Pdel are ca intrare: nume fiier, codul materialului care va ters (cheia)

Proceduri apelate:
Pindex pentru localizare articol dup cheie;
Pscrie pentru rescrierea articolului dezactivat;
d) se scrie procedura pentru creare prin adugare de articol i se ncarc
fiierul fimat care este sursa de baz pentru toi programatorii. Ei au
obligaia de a-l copia i de a-l utiliza n programele lor proprii.
e) se scrie procedura de afiare a fiierului.
f) se scrie procedura de numrare a articolelor din fiier i de afiare a
numrului de articole.
Fiecare i definete i structurile proprii n segmente. n final exist n
proceduri i m segmente de date.

Programatorul ef asambleaz i scrie programul apelator.


Se procedeaz la efectuarea testrii:
o testarea modulelor (de ctre realizatori)
o testarea produsului asamblat.
19.5 Structuri liniare de program
Aplicaiile sunt vzute ca funcii de prelucrare care se execut obligatoriu,
una dup cealalt.
Se consider funciile de prelucrare f1, f2, , fn care alctuiesc o aplicaie.
Graficul asociat structurii liniare de program este dat n figura 19.3.
f1

f2

fn-1

fn

Figura 19.3 Structur liniar de program


Acestei structuri i corespunde secvena de program:

647

f1

...
call f1
call f2
...
call fn
mov ax,4c00h
int 21h
proc
...

ret
endp
f2

proc
...
ret

endp
fn

...
proc
...
ret

endp

Pentru asigurarea traversrii secvenei celor n instruciuni call se


procedeaz la definirea unui vector de pointeri spre funcii vpf prin linia surs:
vpf

dw f1, f2, f3
dw f4, f5, f6
...
dw fn-2, fn-1, fn

care se refer prin secvena:


mov si, offset vpf
mov cx, n
ciclu:
call [si]
inc si
in si
loop ciclu
mov ax, 4c00h
int 21h

Structura liniar corespunde unei singure succesiuni de apelare a


procedurilor. Procedurile sunt referite n totalitate i strict n ordinea impus,
indiferent de context.
19.6 Structura arborescent

648

Se consider funciile de prelucrare: f0 f1 f2 f3 fn. Referirea funciilor se


efectueaz selectiv dup cum sunt ndeplinite o serie de condiii.
Fie irul de elemente v1 v2 vm definite pe mulimea boolean unde
vi{o,1} i=1, 2,, m. Se construiete structura arborescent din figura 19.4.

f0

vi
fi

fj

Figura 19.4 Structura asociat nodului rdcin corespunztoare programului


principal (funcia , f0)
Nodurile corespund apelurilor de funcii(proceduri)
call fi
...
call fj

i testelor pentru verificarea unor condiii.


cmp vi, 0
jz apelj
apeli:
call fi
jmp ...
...
apelj:
call fj
...

n structura arborescent asociat unui program se gsesc noduri interne


avnd forma dat n figura 19.5.
fk
vk

649

Figura 19.5 Secvena de structur arborescent asociat


unui apel de funcii fk nod intern al structurii
arborescente
n structura arborescent exist funcii terminale care corespund nodurilor
frunz. Ele nu apeleaz alte funcii i corespund execuiilor ce preced ncheierea
programului, figura 19.6.

fi

fj

fk

Figura 19.6 Funciile terminale


Se consider variabile funciile f0 f1 f2 f3 f4. Se construiesc perechile
(f1, v=1)
(f2, v=2)
(f3, v=3)
(f4, vR\1, 2, 3)
(f0, )

Se asociaz acestui
arborescent din figura 19.7.

sistem

de

perechi

f0
Vk=1
f1

Vk=2
f2

Vk=3
f

structura

650

Figura 19.7 Structura arborescent de program cu


funcie cu condiie simpl

f0
V1=1
V2=1
V3=1

V2=1
V4=1

f1

f2

f3

V3=1

f4

f5

f6

V4=1

f7

f8

Figura 19.8 Structur arborescent cu selecia


procedurilor de tip nod terminal
Programul apelator pentru structura dat n figura 19.8, f0, se structureaz
astfel:
start:
mov ax,
mov ds,
cmp v1,
jz salt_11
cmp v2,

@data
ax
1
1

651
jz salt_21
cmp v3, 1
jz salt_23
call f1
jmp final
salt_23:
call f2
jmp final
salt_21:
cmp v4, 1
jz salt_31
call f3
jmp final
salt_31:
call f4
jmp final
salt_11:
cmp v2, 1
jz salt_22
cmp v3, 1
jz salt_32
call f5
jmp final
salt_32:
call f6
jmp final
salt_22:
cmp v4, 1
jz salt_3y
call f7
jmp final
salt_3y:
call f8
final:
mov ax, 4c00h
int 21h
end start

pentru a evita scrierea secvenei:


mov ax, 4c00h
int 21h

dup fiecare apel de forma:


call fi ;i=1, 2, , 8

s-a folosit instruciunea:


jmp final

652

f1

f2

f3

f4

f5

f6

f7

f8

final: mov ax, 4c00h


int 21h

Figura 19.9 Structura arborescent cu ncheierea


execuiei ntr-un singur punct
n cazul n care selecia procedurilor se efectueaz dup o variabil ale crei
valori sunt a1, a2, , ak, structura arborescent are graful asociat prezentat n figura
19.10.
f0
V=a1
Vk=a2
Vk=a3
Vk=an
fn+1

fn

f3

f2

f1

Figura 19.10 Structura arborescent de selecie dup o


singur variabil de control, cu toate procedurile de tip
terminal
Programul asociat este:
...
cmp v, a1
jz salt_1
cmp v, a2
jz salt_2

653
cmp v, a3
jz salt_3
...
cmp v, an
jz salt_n
call fn1; fn1=fn+1
mov ax, 4c00h
int 21h
salt_1:
call f1
mov ax, 4c00h
int 21h
salt_2:
call f2
mov ax, 4c00h
int 21h
...
salt_n:

f1

f2

fn

fn1

call fn
mov ax, 4c00h
int 21h
proc
...
ret
endp
proc
...
ret
endp
...
proc
...
ret
endp
proc
...
ret
endp
end nume_program

Program calcul salarii A


- creare baz de date B
- calcul salarii C
- actualizare D
- afiare rezultat E
- Creare baz de date B
- dup fiiere existente B1
- cu introducere de la tastatur B2

654

- prin scanare B3
- concatenare de fiiere B4
- Calcul salarii C
- pentru un salariat C1
- pentru salariaii unui compartiment C2
- pentru toi salariaii C3
- Actualizare D
- modificare salariu brut D1
- modificare impozit D2
- modificare vechime D3
- modificare volum produse D4
- Afiare rezultate E
- pentru un salariat E1
- pentru toi salariaii E2
- afiare nume i salariu net E3
- afiare toate datele E4

Figura 19.11 Meniuri pentru programe de calcul salarii


Structurile arborescente organizate pe mai multe niveluri corespund
implementrii interfeelor cu regsire a prelucrrilor din aproape n aproape. De
exemplu, se consider meniurile din figura 19.11.

Pentru realizarea acestui meniu se dezvolt structura


arborescent din figura 19.12 organizat pe trei niveluri.
Selectarea se efectueaz cu ajutorul unui mouse sau prin
tastarea literelor A, B, C, D, E respectiv B1, , B4; C1, C2, C3; D1,
, D4; E1, E4 depinznd de nivelul pe care se efectueaz
selecia.
A

B1 B2

B3 B4

C1 C2 C3

D1 D2 D2 D4

E1 E2 E3 E4

655

Figura 19.12 Structura arborescent organizat pe trei


niveluri
Structura de tip arborescent se caracterizeaz prin:
apelul unic al unei funcii (proceduri) n timpul lansrii n
execuie a programului;
dispunerea condiiilor i funciilor (procedurilor) pe
niveluri;
exist un singur sens de apelare a funciilor
(procedurilor) de pe procedura printe (de pe un nivel
superior) ctre procedura descendent (de pe nivel
inferior) de pe nivelul imediat urmtor;
programul are un singur program apelator;
funciile (procedurile) nu apeleaz la rndul lor alte
proceduri.
Implementarea structurilor alternative multiple (GOTO
depending onCOBOL, GOTO calculat Fortran, switch
C/C++) permite dezvoltarea de structuri arborescente de
program complexe fa de structurile binare bazate pe structura
IF THEN ELSE, figura 19.13.

f0
C1(1, 2, 3, 4)
1

2
3
C3(1, 2, 3, 4)

C2(1, 2)

f1

f2

f3

f4

f5

f6

4
C4(1)

f7

f8

C5(1, 2, 3, 4, 5)

f9

f10 f11

f12

656

Figura 19.13 Structuri arborescente oarecare


Algoritmii de transformare a structurilor arborescente
oarecare, n structuri arborescente binare evideniaz natura
binar a structurilor GOTO depending on, GOTO calculat sau a
structurii switch sau CASE ON prin care se implementeaz ca
secvene n modulele obiect rezultat
al procesului de compilare.
f0
Structurii din figura 19.13 i corespunde structura binar din
figura 19.14.
C1=1
C2=1

C1=2
C3=1

f1

C1=3

f2

C3=2
f3
C3=3

f4

C5=1
f7

C5=2
f8

f5

C5=3

f6
f9

C5=4
f10
f11

f12

657

Figura 19.14 Structura binar asociat unei structuri oarecare


de program
19.7 Structuri de tip reea
Se consider funciile f0 f1 f2 fn de prelucrare, din care f0
este nodul iniial i fn+1 este nodul final.
Succesiunea de apelare a procedurilor este dat de
rezultatul testelor. Se stabilete prin convenie ca rezultatul
adevrat (1) al condiiei c s fie notat cu D, iar rezultatul fals (0)
s fie notat cu N, figura 9.1:

fk
C=1
N

fi

fj

Figura 19.15 Rezultatul testrii condiiei c


Succesiunea de apel a procedurilor nu este restrictiv. O
procedur apeleaz la rndul ei proceduri care au mai fost
apelate. De asemenea, apelul unei proceduri este realizat din
mai multe locuri.
n figura 19.16 este prezentat o structur de tip reea:
f0

C1
N

f1

f2
C2

C3
D

f3

N
f4

C1:= C1+

D
f6

f5

658

Figura 19.16 Structur de program tip reea


Secvenele de proceduri apelate corespunztor structurii
de tip reea dat n figura 19.16 sunt:
f0 (f1 f3) (f1 f3) (f1 f3) f1 f4 f5 f7
f0 f1 f4 f5 f7
f0 (f1 f3) (f1 f3) (f1 f3) f2 f5 f7
f0 (f1 f3) (f1 f3) (f1 f3) f2 f6 f7
f0 (f1 f3) (f1 f3) (f1 f3) f4 f5 f7
f0 f2 f5 f7
f0 f2 f6 f7
n cazul n care se dezvolt aplicaii de tip serial ncruciat
(figura 19.17), se obin, de asemenea, structuri de tip reea.
f1

q1

f2

q2

f3

f4

f5

q3

q4

q5

Figura 19.17 Structur de tip serial ncruciat


Se execut apelurile de proceduri:
f1 f2 f3 f4 f5

659

f1 f2 q3 q4 q5
q1 q2 q3 q4 q5
q1 q2 f3 f4 f5
Mai nou, se construiesc structuri de tip reea cu reluarea
prelucrrilor de la toate punctele de prelucrare, figura 19.18:
f0

f1

C=1

f2

C=1

f3

C=1

fn

Figura 19.18 Structur de tip reea cu reluarea ntr-un punct


(f1)
Se utilizeaz operatorul ()k pentru a specifica repetarea de
k ori a secvenei de apeluri a procedurilor incluse n paranteze.
Se execut urmtoare succesiuni de referiri ale
procedurilor:
f0 (f1)k f2 fn
f0 (f1f2)k f3 fn
f0 (f1f2f3)k f4 fn
f0 (f1fn-1)k fn
Acestea sunt considerate repetri simple. De asemenea
se execut succesiuni de repetri compuse, precum:
f0 ((f1 f2 fj)kr)kr+1fn
De exemplu, secvena de repetri:
f0 (f1 f2 f3 (f1 f2 f3 f4 (f1 f2 )2 f3 f3 f5) f6 f7)3 fn
se dezvolt:

660

f0 f1 f2 f3 f1 f2 f3 f4 f1 f2 f1 f2 f3 f4 f5
Cu ct structura produsului este mai mare, cu att se
impune gsirea unor modaliti de simplificare a reprezentrii
interaciunilor dintre proceduri.

19.8 Concluzii
La soluionarea unei probleme se va alege acea structur
care genereaz numrul cel mai mic de apeluri si de reveniri n
programele apelatoare. Cunoaterea celor mai importante tipuri
de structuri de programe creeaz premisele comparrii ntre
structuri cu proprieti care nu difer semnificativ din punct de
vedere al performanelor n vederea lurii deciziei care s
propage la un numr ct mai mare de utilizatori efecte pozitive.

20
OPTIMIZAREA PROGRAMELOR
Optimizarea programelor reprezint una din direciile spre care se
concentreaz realizatorii de software. Exist numeroase aspecte ale optimizrii
programelor: optimizarea timpului de execuie, optimizarea dimensiunii
operanzilor, optimizarea textului surs etc. Toate aceste criterii de optimizare,
considerate cu diferite ponderi, contribuie la definirea conceptului de optimizare a
unui program.
Compilatoarele pentru limbajele evoluate (C, C++, Pascal etc) conin
faciliti de generare de cod executabil optimizat n timp de execuie, n dimensiune
a codului, sau combinaii ntre acestea. Datorit specificaiilor de limbaj, la nivel de
asamblare nu exist asemenea faciliti ncorporate n asambloare, de aceea
aspectele de optimizare revin n exclusivitate programatorului.
n materialul de fa s-a tratat problema optimizrii timpului de execuie,
care survine uneori n defavoarea dimensiunii codului. S-a considerat aceast
abordare deoarece la arhitecturile actuale, memoria nu mai este, n general, o
resurs critic. Resursa critic devine timpul, mai ales la aplicaiile de prelucrare n
timp real, la prelucrri grafice, la jocuri etc.

661

20.1 Criterii de optim


Se consider un numr de programe destinate rezolvrii aceleiai probleme.
Dintre toate, unul singur conduce la obinerea rezultatului n timpul cel mai scurt.
n raport cu criteriul timpul de rulare, acest program este optim, raportat la
mulimea de programe disponibile la un moment dat.
ntruct nu se poate vorbi de program optim n general, n continuare, prin
program optim se nelege acel program care are comportamentul cel mai bun,
chiar i numai statistic, pe baza unui eantion de probleme rezolvate.
Introducnd sau eliminnd programe sau seturi de probleme de test, este
posibil ca programul optim s fie de fiecare dat altul.
Criteriile dup care se ierarhizeaz programele sunt:
durata de timp necesar rezolvrii unei probleme;
dimensiunea problemei de rezolvat;
necesarul de memorie intern;
precizia rezultatelor;
nivelul de generalitate al problemei ce poate fi acceptat;
costul rulrii programului;
nivelul unei caracteristici de calitate;
lungimea textului programului.
Criteriile sunt contradictorii, ceea ce determin ca la obinerea unor
avantaje din punct de vedere ale unui criteriu s se estimeze care sunt efectele
negative antrenate pentru celelalte.
Programele scrise n limbajul de asamblare au particulariti impuse de
faptul c programatorul gestioneaz toate resursele i are posibilitatea s aleag
dintre mai multe variante pentru orice construcie pe care o realizeaz.
Toate criteriile sunt importante i ideal este s fie construit programul care
le ndeplinete pe toate. Se observ c lungimea textului, dimensiunea problemei,
precizia rezultatelor, calitatea i necesarul de memorie sunt strns legate de durata
execuiei.
Estimarea duratei de rulare a unui program scris ntr-un limbaj evoluat este
dificil. Optimizarea timpului de execuie al unui program scris ntr-un astfel de
limbaj ine de caracteristicile limbajului i ale compilatorului. De asemenea,
compilatoarele evoluate suport opiuni pentru optimizarea dimensiunii codului sau
a duratei de execuie, dar aceste optimizri, sunt, deocamdat, relative, deoarece se
fac la nivel local i nu in cont de evoluia n perspectiv a programului sau de
strile prin care s-a trecut anterior.
Dac n cazul limbajelor evoluate complexitatea instruciunilor face dificil
estimarea duratei, pentru limbajele de asamblare durata necesar execuiei unei
instruciuni este dat cu precizie prin numrul de cicluri main.

662

Dac programatorul face opiuni din aproape n aproape asupra


instruciunilor selectate, cutnd s reduc numrul de cicluri, va obine un
program bun n raport cu durata de execuie. Optimalitatea programului trebuie
demonstrat prin compararea cu alte programe sau chiar cu alte variante de
secvene destinate respectivului program i este privit ca mbuntire.
Optimizarea timpului de execuie se preteaz la sistemele cu capacitate
mare de memorie care necesit prelucrarea unei cantiti de informaie foarte mare
n timp critic (de exemplu, afiarea unor imagini dinamice pe un display grafic de
rezoluie mare).
n cazul unor sisteme cu resursa de memorie de cod redus i care
proceseaz un volum de date mai modest, se pune problema optimizrii
dimensiunii codului (de exemplu, procesoare pentru urmrirea unor instalaii cu
parametrii lent variabili n timp).
n continuare se analizeaz modaliti de optimizare a timpului de execuie.
20.2 Cicluri main
n general, mecanismele au o component principal care dezvolt o
operaie de baz, esenial pentru funcia pentru care au fost realizate. Strungul are
un ax a crui rotaie determin antrenarea celorlalte subansamble. Operaia de baz
este rotaia complet. n cazul altor maini, operaia de baz este efectuarea
complet a unei deplasri dute-vino. Ciclul main este fie o rotaie complet, fie o
micare rectilinie dus-ntors.
Calculatoarele sunt nzestrate cu circuite de tact care definesc coordonatele
n timp ale operaiilor ce se efectueaz. Astfel, un calculator are un ciclu main de
durata dat prin mprirea unei microsecunde la numrul de MHz ai ceasului su.
Un calculator 80286/10 MHz are un ciclu de 100 nanosecunde; un
calculator 80286/5 MHz are un ciclu de 200 nanosecunde; un calculator
80486/50MHz are un ciclu de 20 nanosecunde.
Cnd se proiecteaz un limbaj de asamblare se stabilesc implementrile
fizice ale instruciunilor, precizndu-se cu exactitate numrul de cicluri necesare
efecturii lor.
Astfel, pentru procesoare 8088, cnd operanzii sunt specificai, numrul de
cicluri este fix. De exemplu, instruciunea:
mov ax, 100

se execut n 4 cicluri, iar instruciunea:


mov ax, cx

se execut n 2 cicluri.

663

Cnd operanzii sunt variabile a cror poziie se calculeaz prin evaluarea


unei expresii, iar poziia lor efectiv este segmentul precizat sau adresa este un
numr impar dei se lucreaz la nivel de cuvnt, numrul de cicluri se majoreaz.
Instruciunea
mov ax, SUMA

se execut n 8+6 cicluri, expresia deplasamentului necesit pentru calculul adresei


6 cicluri. Cnd adresarea operandului este indirect folosind fie registrul index, fie
registrul de baz, sunt necesare nc 5 cicluri. Astfel, instruciunea
mov ax, [bx]

se execut n 8+5 cicluri.


Dac expresia pentru adresarea operandului conine deplasare i registru
index sau registru de baz, sunt necesari nc 9 cicluri: instruciunea
mov ax, VECTOR[bx]

se execut n 8+9 cicluri.


Expresia de calcul a adresei n care apar registrul de baz i registrul index
necesit nc 7 cicluri, iar expresia care determin adresa pe baz de deplasare,
registru index i registru de baz necesit nc 11 cicluri. Instruciunile :
mov ax, bx[si]
mov ax, MATRICE[bx][di]

necesit 8+7, respectiv, 8+11 cicluri.


Cnd sunt definite instruciunile, se specific toi factorii ce influeneaz
numrul de cicluri. La prezentarea instruciunilor, n tabele exist o coloan
destinat numrului de cicluri i a variabilitii.
Dac se consider factorii f1,f2,...,fk ce influeneaz numrul de cicluri
pentru operaii, dup ce se determin exact contribuia fiecrui factor, stabilind
coeficienii c1, c2, ..., ck, modelul de calcul al numrului de cicluri pentru
instruciunea Ij este dat de ecuaia:
NCI j c 0 j Sc i x i
unde :
c0j
- numrul de cicluri fixat pentru instruciunea I j;
xi
- variabila boolean cu valoarea 1 dac factorul fi este prezent, i cu
valoarea 0 n caz contrar.
Dac un factor vizeaz ncrcarea de segment, coeficientul su asociat este
cu valoare 2. Dac factorul de aliniere a adresei la nivel de cuvnt este prezent,

664

cnd operandul are adresa efectiv un numr impar, "forarea" la baitul urmtor cu
adresa numr par presupune adugarea a 4 cicluri. Instruciunea
mov SUMA, ax

se execut n 20 cicluri dac 8 cicluri se datoreaz faptului c un operand este n


registrul AX iar celalalt este n memorie, 6 cicluri rezult din calculul adresei de 16
bii ai deplasamentului, 2 cicluri provin din ncrcarea segmentului unde se afl
variabila SUMA, aa cum rezult din definirea ei i din punerea n coresponden a
segmentelor cu registrele de segment n directiva ASSUME i 4 cicluri sunt
necesare pentru a fora ncrcarea unei adrese pare, pentru c variabila SUMA este
definit la o adres impar.
Numrul de cicluri este influenat de distana la care se face saltul
necondiionat, dac se lucreaz n mod protejat sau nu, ct de lung este zona de
memorie care se transfer, dac se lucreaz n cadrul aceluiai segment sau ntre
segmente diferite. Rezultatele pot fi scurte, n apropiere sau la distan.
Modelul de calcul al numrului de cicluri se obine din tabelele de descriere
a instruciunilor ct i din prezentarea fiecrei instruciuni n parte.
Meninnd clasificarea instruciunilor dup numrul de cicluri, se prefer
acele instruciuni care nu depind de amplasamentul operanzilor sau se prefer acele
moduri de adresare care genereaz sistematic un numr redus de cicluri.
Instruciunea de salt necondiionat din secvena:
..................
alfa: mov ax, 5
..................
jmp alfa

avnd distana de tip scurt necesit 1 ciclu, n timp ce un salt necondiionat


intersegmente, folosind adresarea indirect ca n instruciunea:
jmp beta [bx][di]

necesit 16 + 7 + 2 cicluri (c0j = 16, c1 = 7, c2 = 2).


n documentaii se fac referiri detaliate asupra expresiilor de adres care
intervin n calculul ciclurilor ce se asociaz fiecrei variabile de instruciune.
Este important s se cunoasc efectele contradictorii ale opiunilor la
scrierea de programe n limbaj de asamblare. De regul se obinuiete obinerea
unui text compact prin definirea i apelarea de proceduri. Se minimizeaz lungimea
textului dar fiecare apel de procedur nseamn o instruciune CALL. Dac
procedura este referit prin adresa n cadrul aceluiai segment, numrul de cicluri
necesar execuiei este 11. Dac se lucreaz n cadrul aceluiai segment dar adresele
sunt pe 4 baii, pentru un apel de procedur sunt necesare 26 cicluri. Gestionarea

665

prin apeluri de proceduri a task-urilor sau lucrul n mod privilegiat conduce la un


necesar de cicluri de 177, respectiv, 90+4*x cicluri (x reprezint numrul de
parametri). Orice procedur presupune revenirea n funcia apelatoare folosind
instruciunea RET, care consum ntre 11 i 55 cicluri, de asemenea, depinznd de
tipul formulei de calcul a adresei instruciunii ce urmeaz lui CALL. Dac aceast
adres este stocat cu instruciunea POP/PUSH nainte de apel i procedura este n
acelai segment n care se afl funcia apelatoare, sunt necesare 11 cicluri. Dac
tipul de pointer este FAR sunt necesari 55 cicluri. Dei lucrnd cu proceduri s-a
obinut reducerea lungimii textului, numrul de cicluri adugat este de cel puin 7 +
11 sau de cel mult 185 + 55 cicluri.
20.3 Volumul de operaii
Un program scris n limbaj de asamblare conine linii surs care la
asamblare genereaz instruciuni executabile (main) i linii surs ce definesc
contextul de alocare resurse i de iniializare. Volumul de operaii se refer la
instruciunile executabile.
Procedura:
aduna PROC
push
mov
mov
add
add
pop
ret
aduna ENDP

bp
bp,sp
ax,[bp+4]
ax,[bp+6]
ax,[bp+8]
bp

conine apte instruciuni executabile, fiecare se execut o singur dat. Volumul


de operaii, ca numr de instruciuni ce se execut, n acest caz este chiar 7.
Procedura:
generare
push
mov
push
push
mov
mov
mov
ciclu:
adc
inc
loop
pop

PROC FAR
bp
bp,sp
cx
bx
cx,[bp+6]
bx,[bp+8]
ax,0
add
al,[bx]
ah,0
bx
ciclu
cx

666
pop
pop
ret
generare

bx
bp
ENDP

conine 14 instruciuni executabile, dintre care:


ciclu:
add
adc
inc
loop

al,[bx]
ah,0
bx
ciclu

se execut de un numr de ori dependent de coninutul registrului CX. Presupunnd


c registrul CX conine o valoare notat generic n, volumul de operaii executate la
apelul procedurii generare va fi dat de relaia:

V k0 n1 k1 ... n p k p
unde:
k0
-numrul instruciunilor executate o singur dat;
ni
-numrul de repetri ale buclei de program i;
ki
-numrul de instruciuni cuprinse n bucla de program i.
Valoarea sa este V=11+4*n.
Exist proceduri n care apar comparaii i se efectueaz selecii ale
secvenelor. Se noteaz P j probabilitatea ca o condiie Cj s fie ndeplinit, caz n
care se execut o secven avnd volumul Vt. Numrul repetrilor testului pentru
condiia Cj este nj.
Volumul operaiilor este dat de relaia:

V Pj Vf 1 Pj Vt n j .
Volumul de operaii apare ca un numr mediu de operaii care se vor executa n
timp. Procedura:
trans PROC
mov
cmp
jz
cmp
jb
cmp
ja
and
mov
urmat:

NEAR
al,[si]
al,0
final
al,'a'
urmat
al,'z'
urmat
al,NOT 20h
[si],al

667
inc
jmp
final:
ret
trans ENDP

si
trans

convertete un ir de lungime M caractere, terminat cu zero, ntr-un ir format


numai din litere mari. Volumul de operaii depinde de structura irului de caractere.
n structura textelor din limba romn 6% dintre caractere sunt litere mari.
Procedura trans va efectua transformarea and al,NOT 20h n 94% din cazuri. La
stnga literelor mici se afl 3,3 % dintre caracterele unui text, iar la dreapta restul
de 96,7 %, aa cum rezult din observaii pariale.
Pentru textul de lungime M caractere, delimitat prin zero, instruciunile
procedurii trans se execut n medie de un numr de ori indicat n tabelul 20.1.

Instruciunea
Mov al,[si]
Cmp al,0
jz final
Cmp al,a
jb urmat
Cmp al,z
ja urmat
And al,NOT 20h
Mov [si],al
Inc si
Jmp trans
Ret

Tabelul 20.1.
Numr de repetri mediu
M
M
M
M
0.033*M
0.967*M
0.967*M
0.96*M
0.96*M
M
M
1

Volumul mediu de operaii executabile la un apel al procedurii trans este


V = M*(6+0.967+0.967+0.96+0.96+0.033)+1
operaii.
Conceptul de operaie este general i se observ de la nceput c
posibilitatea de a compara operaiile este dificil datorit diferenei de complexitate

668

pe care fiecare operaie o induce. Un transfer de date, intuitiv este mai simplu dect
o nmulire, iar apelul unei proceduri este mai complex dect o implementare.
Se accept ipoteza conform creia complexitatea operaiilor este strns
legat de numrul de cicluri main asociate. Diversitii de instruciuni i
corespunde o multitudine de numere de cicluri. Mai mult, tipurile de adresare
modific numrul de cicluri pentru fiecare instruciune. Instruciunile care
manipuleaz un volum redus de informaie sau au operanzi prefixati sunt puse n
coresponden cu un numr redus de cicluri. Instruciunile care au adrese ce sunt
calculate dup formule complexe, care impun regsiri, necesit un numr de cicluri
main superior.
Pentru a reflecta mai exact efortul de execuie, volumul programului se va
exprima ca numr de cicluri main. Astfel, secvena:
.......................
mov
ds,ax
; 2 cicluri masina
xor
ax,ax
; 3 cicluri masina
inc
ax
; 2 cicluri masina
cmp
ax,20
; 3 cicluri masina
...............................

are un volum V = 10 cicluri, rezultat ca sum a ciclurilor asociate instruciunilor


care o alctuiesc.
Pentru procedura:
strlen PROC
cld
push
mov
mov
repne
jne
fara salt
mov
sub
dec
dec
dec
jmp
eroare:
mov
mov
final:
pop
ret
strlen ENDP

NEAR
cx
cx,0ffffh
al,0
scasb
eroare

;
;
;
;
;
;

2 cicluri
10 cicluri
4 cicluri
4 cicluri
n*(6+15) cicluri
8 cicluri pentru salt, 4 cicluri

ax,0ffffh
ax,cx
ax
di
di
SHORT final

;
;
;
;
;
;

4
3
2
2
2
1

di,0
es,di

; 4 cicluri
; 2 cicluri

cx

; 8 cicluri
; 8 cicluri

cicluri
cicluri
cicluri
cicluri
cicluri
ciclu

volumul de operaii exprimat n cicluri este


V1 50 21 n

669

n caz de eroare sau


V2 24 21 n 30
cicluri.
20.4 Secvene echivalente
Dac se urmrete optimizarea programelor scrise n limbaj de asamblare
reducnd volumul operaiilor, n primul rnd se caut folosirea de secvene
echivalente care se execut ntr-un numr mai redus de cicluri.
Iniializarea unui registru se realizeaz n moduri diferite. Din secvena:
mov
sub
xor

ax,0
ax,ax
ax,ax

; 4 cicluri
; 3 cicluri
; 3 cicluri

rezult necesitatea de a utiliza una din ultimele dou variante, dei prima
instruciune este mai sugestiv.
La tipul de adresare indexat este necesar incrementarea unui registru cu o
raie egal cu lungimea zonei de memorie care este referit. Dac raia este o
unitate, din secvena:
add
inc

si,1
si

; 4 cicluri
; 2 cicluri

rezult c este avantajoas utilizarea instruciunii inc si, efectul fiind major mai
ales pentru faptul c referirea este proprie unei secvene executate repetitiv.
Dac raia cu care se modific registrul index este un numr oarecare,
repetarea instruciunii inc registru este ineficient. Se opteaz spre una din
variantele din secvena:
add
si,57
add
si,bx
initializat mov
add
si,ratia

; ratia este 57, 4 cicluri


;
3
cicluri,
registrul
bx,57
; 16+6 cicluri

bx

fost

De cele mai multe ori nu este posibil alocarea unui registru pentru
memorarea raiei i se definete o constant simbolic ( RATIA EQU 57) dup care
incrementarea este realizat prin add si,RATIA.
Lucrurile devin mult mai simple dac se pune problema alegerii modalitii
de a nmuli un numr cu 2k sau de a-l mpri prin 2k. Pentru nmulirea numrului
79 aflat n registrul AX cu 32 se alege secvena:
mov
mov

cl,5
ax,79

670
sal

ax,cl

; 8+4*5 cicluri

ntruct secvena:
mov
bl,32
mov
al,79
cbw
b
mul bl

; 2 cicluri
; 71 cicluri

necesit mai multe cicluri.


n cazul n care o procedur este apelat de un numr mare de ori, este
preferabil s se includ textul ei n locul instruciunii call. Chiar dac lungimea
textului surs crete, se obine o reducere a numrului de cicluri generate de fiecare
apel i de fiecare revenire n secvena apelatoare.

20.5 Alegerea tipului de dat


n limbajele evoluate lucrul cu diferite tipuri de date este netransparent,
programatorul neavnd la dispoziie resursele antrenate. n programul scris n
limbaj de asamblare lucrul cu date codificate binar nseamn a defini variabile la
nivel de bait sau pe cuvnt. Odat definit o variabil la nivel de bait, se vor utiliza
registrele AL, BL, CL, DL, AH, BH, CH, DH. Lucrul la nivel de cuvnt nseamn
lucrul cu registrele AX, BX, CX, DX. n ambele cazuri se are n vedere testarea
indicatorului de condiie CF pentru a gestiona corect rezultatele. Se pot folosi
instruciunile setului, ca i cum limbajul de asamblare este proiectat preponderent
pentru a lucra cu numere codificate binar.
Dac se dorete s se lucreze n aritmetica zecimal, mai nti se construiesc
toate procedurile care opereaz n aceast aritmetic: transferuri ntre operanzi,
adunri, scderi, nmuliri, mpriri, deplasri, alinieri. Procedurile vor fi cu un
grad ridicat de generalitate. Evaluarea unei expresii va consta mai nti n
demontarea ei n pai elementari, se pregtesc parametrii i se vor apela funciile
pentru efectuarea operaiilor. Programatorul va gestiona i rezultatele elementare i
pe cele intermediare.
Dac se lucreaz n virgul mobil, fiecare limbaj de asamblare admite un
set de instruciuni specifice acestui tip de date i chiar registre specializate.
n procesul de optimizare a programelor scrise n limbaj de asamblare,
alegerea tipului de date este esenial pentru efortul de programare n primul rnd.
Lucrul cu date de tip real presupune utilizarea resurselor unui coprocesor, iar
aritmetica zecimal e folosit cnd operanzii au un numr foarte mare de cifre i
sunt ntregi.

671

Neomogenitatea operanzilor este aproape exclus n programele scrise n


limbaje de asamblare.
Dac un operand este definit pe un bait i particip la evaluarea unei
expresii n care un rezultat intermediar este n registrul AX, la nivel de cuvnt, este
necesar o conversie de la bait la cuvnt pe care o asigur programatorul. n
programele scrise n limbaj de asamblare construciile implicite sunt foarte rare.
Secvena:
mov
mov
cbw
add

bx,ax
al,operand_bait
ax,bx

ilustreaz faptul c programatorul gestioneaz i rezultatele intermediare. Problema


devine mai complicat cnd un operand este ntreg iar altul este zecimal
mpachetat. Mai nti se ia decizia cum se va lucra n continuare. Dac se va
continua lucrul n zecimal mpachetat, operandul binar va fi convertit apelnd la o
procedur la forma de reprezentare zecimal mpachetat. n continuare se vor apela
proceduri de lucru pentru zecimal mpachetat.
Dac opiunea este de a lucra n binar, operandul zecimal mpachetat va fi
convertit n binar i se vor folosi n continuare instruciunile setului definit pentru
limbajul de asamblare considerat.
n cazul n care este necesar s se lucreze n virgul mobil cei doi operanzi
vor fi convertii folosind proceduri speciale i cu instruciunile de virgul mobil se
va continua lucrul.
Lucrul cu operanzi neomogeni impune existena unei multitudini de
proceduri de conversie care s acopere totalitatea cerinelor de omogenizare a
tipurilor. Dup omogenizare, programatorul va folosi numai instruciunile sau
procedurile specifice tipului pentru care s-a hotrt s continue lucrul.
Optimizarea programului este obinut n aceast faz prin numrul de
proceduri de conversie ce se apeleaz i prin procedurile de operaii. Un
programator cu experien va ti cnd s nu foloseasc aritmetica binar,
problematica alegerii tipului cel mai potrivit fiind destul de rar. Programatorul i
definete din start operanzi omogeni i exclude efectuarea de conversii tocmai
pentru c neomogenitatea este transparent n programele scrise n limbaj de
asamblare prin creterea lungimii datorate secvenelor suplimentare specifice
omogenizrii.
Chiar dac procedurile de conversie sunt rezultatul unui proces de
optimizare, adugarea lor la un program determin creterea volumului de operaii.
20.6 Eliminarea subexpresiilor comune

672

Limbajele evoluate au tendina de a reda forma algebric a expresiilor. De


aceea programatorul i pune distinct problema eliminrii subexpresiilor comune.
Expresia:
2
E = (a+b+c) * (a+b+c-d) + (c +a+b+c) / (a+b+c)
va fi scris de cele mai multe ori direct cum apare i n rare cazuri se va calcula
E1=a+b+c dup care se va calcula:
2
E = E1 * (E1-d) + (c +E1) / E1.
Cnd se scrie programul n limbaj de asamblare, demontarea expresiei i
reaezarea rezultatelor intermediare pentru a respecta prioritile operatorilor l
determin pe programator s urmreasc simultan i modaliti de a reduce
lungimea secvenei. Eliminarea subexpresiilor comune apare ca o necesitate
fireasc pentru programator. Mai mult, el va cuta s gestioneze cu grij rezultatele
intermediare, lungimile zonelor de memorie asociate lor, pentru a nu deteriora
omogenitatea operanzilor. Secvena:
mov
add
add
mov
sub
mul
mov
mov
mov
mul
add
adc
div
xor
add
adc
mov
mov

ax,a
ax,b
ax,c
E1,ax
ax,d
E1
prod1,ax
prod1+2,dx
ax,c
c
ax,E1
dx,0
E1
dx,dx
ax,prod1
dx,prod1+2
E,ax
E+2,dx

;5
;7
;7
;3
;7
;24
;3
;3
;5
;24
;7
;7
;25
;2
;7
;7
;3
;3

total 149 cicluri (80286)

ine seama de ceea ce conin registrele dup efectuarea operaiilor i utilizeaz acest
coninut. Este puin probabil ca programatorul s repete de patru ori secvena:
mov
add
add

ax,a
ax,b
ax,c

673

n programul su, fr ca cel puin s se gndeasc la scrierea unei macrodefiniii


pentru a-i uura efortul de a scrie textul surs.
20.7 Gestionarea corect a invarianilor
n secvenele care se execut repetitiv, din eroare sunt introduse iniializri
ale variabilelor care altereaz rezultatele finale. Secvena:
mov
ciclu:
mov
mov
add
inc
loop
mov

cx,22
ax,0
si,0
ax,x[si]
si
ciclu
total,ax

va conduce nu la nsumarea elementelor unui vector, ci la nsumarea primei


componente a vectorului, numai. Cele dou iniializri de registre, invarianii din
secven, sunt scoi n afar, obinnd variabilitatea cerut de orice structur
repetitiv. Secvena:
mov
mov
mov
ciclu:
add
inc
loop

ax,0
si,0
cx,22
al,x[si]
si
ciclu

realizeaz corect obiectivul propus.


20.8 Regruparea ciclurilor
n cazul secvenelor repetitive n care rezultatele sunt independente,
numrul de repetri este identic, secvenele se regrupeaz reducnd numrul
operaiilor induse de testul variabilei de control i de modificarea acesteia.
Secvena:
mov
xor
xor
ciclux:
add
inc
loop

cx,37
ax,ax
si,si

; 4 cicluri
; 3 cicluri
; 3 cicluri

al,x[si]
si
ciclux

;18 cicluri * 37
; 2 cicluri * 37
; 37 * 9 cicluri sau 5 cicluri

674
mov
suma,ax
; 14 cicluri
mov
cx,37
; 4 cicluri
xor
ax,ax
; 3 cicluri
xor
si,si
; 3 cicluri
cicluy:
add
al,y[si]
; 18*37 cicluri
inc
si
; 2*37 cicluri
loop cicluy
; 9*37 sau 5 cicluri
mov sumy,ax ; 14 cicluri

se execut ntr-un volum


V=10+29*37+24+10+29*37+14=2204
de cicluri. Secvena n care se regrupeaz ciclurile:
mov
cx,37
xor
si,si
xor
ax,ax
xor
bx,bx
ciclu:
add
al,x[si]
add
bl,y[si]
inc
si
loop ciclu
mov
sumax,ax
mov
sumay,bx

;
;
;
;

4
3
3
3

cicluri
cicluri
cicluri
cicluri

;
;
;
;
;
;

18*37 cicluri
18*37 cicluri
2*37 cicluri
9*37 cicluri sa 5 cicluri
14 cicluri
14 cicluri

necesit un volum
V=13+37*47+5+28=1785
de cicluri (8088).
Dac numrul de elemente ale unui ir este par se poate njumti numrul
de repetri prin calculul a dou sume (suma elementelor cu poziie par i suma
elementelor cu poziie impar). La ieirea din ciclu printr-o nsumare se obine
rezultatul dorit.
Secvena:
mov
cx,2*N
xor
ax,ax
xor
si,si
ciclu:
add
ax,x[si]
inc
si
inc
si
loop ciclu
mov
sum,ax

;4 cicluri,
; 3 cicluri
; 3 cicluri
;
;
;
;
;

N constanta simbolica

18*2*N cicluri
2*2*N cicluri
2*2*N cicluri
9*2*N cicluri sau 5 cicluri
14 cicluri

675

necesit un volum de operaii V=29+2*N*31 cicluri.


Prin nsumarea separat a elementelor cu poziii pare, respectiv impare,
secvena:
mov
cx,N
xor
ax,ax
xor
bx,bx
xor
si,si
ciclu:
add
ax,x[si]
add
si,2
add
bx,x[si]
add
si,2
loop ciclu
add
ax,bx

necesit un numr de operaii V=13+2*N*26+N+8. Comparnd cele dou volume,


rezult o diferen D=8+9*N cicluri, ceea ce justific o astfel de regrupare a
termenilor din structurile de date omogene.
20.9 Eliminarea secvenelor inconsistente
Uneori n programe se introduc instruciuni care anuleaz efectele
operaiilor precedente. Programatorul va elimina acele instruciuni care nu
corespund cerinelor i distrug rezultate create anterior. Eliminarea de instruciuni
atrage reducerea volumului de operaii.
n secvena urmtoare:
mov
xor
add
mov

bx,0
ax,ax
ax,2
bx,ax

;1
;2
;3
;4

instruciunea 1 este inconsistent, deoarece registrul BX este apoi modificat


(instruciunea 4) fr ca valoarea stocat n el anterior s fie folosit. Pentru
limbajele evoluate (C, Pascal) la compilare exist posibilitatea ca utilizatorul s fie
avertizat asupra variabilelor nefolosite. n asamblare o asemenea analiz la
compilare este cvasi-imposibil, de aceea programatorul trebuie s depisteze
asemenea secvene nc din faza de scriere a codului surs.
20.10 Eliminarea secvenelor inactive (cod mort)
Programele scrise n limbaje evoluate pot conine secvene ce nu se
activeaz indiferent de contextul n care se ruleaz programul. n programele scrise

676

n limbaj de asamblare, pentru a reduce deplasarea operanzilor, la definire acetia


sunt inclui n segmentul program, ca n secvena:
.CODE
start:
jmp
x
dw
y
dw
z
dw
alfa:
mov
add
mov
mov
int
END
start

alfa
10
20
?
ax,x
ax,b
z,ax
ah,4ch
21h

Astfel de instruciuni sunt frecvente i corecte, poate chiar eficiente, i de


aceea este dificil a se identifica secvenele care nu se activeaz niciodat n
execuie.
Exist i situaii cnd se construiesc teste n mod eronat, fr a asigura
ncheierea unui ciclu sau existena cel puin a unei situaii n care se traverseaz i o
alt ramur a structurii alternative.
Expresiile booleene construite n limbajele evoluate pot conduce la evaluare
la valori constante indiferent de variaiile operanzilor. Complexitatea expresiilor i
manipularea eronat a operatorilor genereaz secvene numite cod mort, adic
secvene ce nu se execut niciodat. n programele scrise n limbaj de asamblare
astfel de construcii apar ca incorecte relativ uor, ntruct se identific
invariabilitatea operanzilor.
Secvena:
mov
ax,5
cmp
ax,0
jz
alfa
..............
jmp
beta
alfa:
.........
beta:
nop

este interpretat ca generatoare de cod mort dac este inclus chiar ntr-o structur
repetitiv, pentru c att timp ct ax va conine 5 i se va compara cu valoarea zero,
secvena etichetat cu alfa nu se va executa. Volumul de operaii nu este influenat
dac se ia n considerare coeficientul zero al probabilitii acestei secvene inactive.

677

Codul mort afecteaz numai lungimea programului ca numr de baii ocupai de


codul obiect asociat unui text surs.
20.11 Reacoperirea segmentelor
Segmentele se gestioneaz de ctre programator. Directivele de punere n
coresponden a segmentelor cu registre de segmente, ncrcarea adreselor de
segment, sunt elemente la dispoziia programatorului. Instruciunile de salt
necondiionat se difereniaz dup cum destinaia este n acelai segment sau este
n alt segment, adresarea fiind direct sau indirect. Apelul de procedur din acelai
segment are 7 sau 11 cicluri, n timp ce pentru proceduri din alte segmente numrul
de cicluri poate fi 13 sau 26 cicluri.
Optimizarea reacoperirii vizeaz programe complexe, care opereaz cu
structuri de date ce necesit mai multe segmente de date care se ncarc alternativ.
Pentru proceduri se va asocia o arborescen pentru a se identifica ce componente
se afl ncrcate de pe fiecare ramur.
20.12 Alocarea optim a regitrilor
Alocarea regitrilor este o problem de construire a compilatoarelor.
Aceeai secven se va utiliza n moduri diferite, obinndu-se de fiecare dat alt
numr de cicluri main.
Alocarea regitrilor are ca obiectiv minimizarea numrului de cicluri. Se
vor construi compilatoare care realizeaz alocri de registre i tipuri de adresri
care s conduc la atingerea acestui obiectiv. De exemplu, pentru evaluarea
expresiei:
e=a+b+c
se construiete secvena:
mov
mov
mov
add
add
mov

ax,a
bx,b
cx,c
ax,bx
ax,cx
e,ax

;5
;5
;5
;2
;2
;3

cicluri
cicluri
cicluri
cicluri
cicluri
cicluri

creia i corespund 22 cicluri main. Secvena echivalent:


mov
add
add
mov

ax,a
ax,b
ax,c
e,ax

;5
;7
;7
;3

cicluri
cicluri
cicluri
cicluri

678

conine instruciuni care totalizeaz tot 22 cicluri.


Problematica alocrii este important pentru operanzii reutilizabili din
expresii. Astfel, expresia:
e=(a+b-c)*(a-b+c)
se calculeaz n secvena:
xor
mov
sub
add
mov
mov
add
sub
mul

dx,dx
ax,a
ax,b
ax,c
bx,ax
ax,a
ax,b
ax,c
bx

;2 cicluri
;5 cicluri
;7 cicluri
;7 cicluri
;2 cicluri
;5 cicluri
;7 cicluri
;7 cicluri
;21 cicluri

creia i corespund 63 cicluri. n secvena echivalent:


xor
mov
mov
mov
mov
sub
add
mov
mov
add
sub
mul

dx,dx
bx,b
cx,c
si,a
ax,si
ax,bx
ax,cx
bx,ax
ax,si
ax,bx
ax,cx
bx

;2 cicluri
;5 cicluri
;5 cicluri
;5 cicluri
;2 cicluri
;2 cicluri
;2 cicluri
;2 cicluri
;2 cicluri
;2 cicluri
;2 cicluri
;21 cicluri

se obin 52 cicluri.
Numrul de cicluri necesare pentru execuia unei instruciuni cu operanzi
din memorie este mai mare dect n cazul n care operanzii s-ar afla n regitrii.
Pentru reducerea timpului de execuie, se va urmri pstrarea rezultatelor
intermediare n regitrii liberi, printr-o alocare optim a acestora.
Conform acestui principiu, secvena pentru calculul expresiei :
2
E=(a+b+c)*(a+b+c-d)+(c +a+b+c)/(a+b+c)
devine, prin utilizarea regitrilor BX, SI i DI, urmtoarea:
mov
add

ax,a
ax,b

;5 cicluri
;7 cicluri

679
add
mov
sub
mul
mov
mov
mov
mul
add
adc
div
xor
add
adc
mov
mov

ax,c
bx,ax
ax,d
bx
di,ax
si,dx
ax,c
c
ax,bx
dx,0
bx
dx,dx
ax,di
dx,si
E,ax
E+2,dx

;7 cicluri
;2 cicluri expresia E1
;7 cicluri
;21 cicluri
;2 cicluri
;2 cicluri
;5 cicluri
;24 cicluri
;2 cicluri
;7 cicluri
;14 cicluri
;2 cicluri
;2 cicluri
;2 cicluri
;3 cicluri
;3 cicluri total 117 cicluri

Se remarc utilizarea regitilor BX, SI i DI pentru pstrarea unor rezultate


intermediare. Este clar c dup aceast secven, valorile iniiale din aceti regitri
vor fi modificate. Dac acestea sunt necesare pentru prelucrri ulterioare, se
salvez, fie n stiv cu instruciunea push, fie n variabile din memorie.
Utilizarea regitrilor se face dup o analiz a codului pe baz statistic,
astfel nct costul salvrii i refacerii regitrilor folosii s fie mai mic dect costul
utilizrii exclusiv a memoriei pentru salvarea rezultatelor intermediare.
20.13 Concluzii
Particularitile limbajelor de programare se regsesc la optimizare. Se
observ c optimizarea programelor scrise n limbaj de asamblare conine acele
elemente ce impun simplitate secvenelor de program. Criteriile de optim,
numeroase la celelalte limbaje de programare, se restrng, atenia fiind ndreptat
spre minimizarea volumului de operaii.
Datorit faptului c programele scrise n limbaj de asamblare nu nlocuiesc
aplicaii scrise n limbaje de tip C, ci le presupun, dac minimizeaz numrul de
cicluri main, nseamn c s-a realizat optimizare. Programatorul n limbaje de
asamblare are multe restricii de utilizare a registrelor, a instruciunilor. S-a fcut
deosebire ntre optimizarea sistemelor de programe i optimizarea pe textul surs.
De aceea, aplicaiile n scrise n limbaj de asamblare sunt de regul pari ce se
ncorporeaz n construcii mult mai complexe. Optimizarea va fi orientat spre
viteza de calcul n principal; reducerea lungimii programului, creterea intensitii
de utilizare a operanzilor trec pe un plan secundar.
Microprocesoarele evoluate (ex. i386, 486, Pentium, etc) sunt proiectate
astfel nct instruciunile sunt executate n pipeline. Aceasta presupune
suprapunerea unor stri disjuncte din execuia unor instruciuni. Astfel, dup
extragerea codului unei instruciuni i trecerea la execuia acesteia, se extrage n

680

paralel codul instruciunii urmtoare. Aceste particulariti in exclusiv de


arhitectura microprocesorului pe care va rula programul. Se poate rafina
optimizarea timpului de execuie lund n calcul aceste particulariti, dar cu
referire strict la un tip de procesor.

21
DESIGNUL LIMBAJELOR DE ASAMBLARE
21.1 Cerine ale designului
Limbajele de asamblare apar ca rezultat al proiectrii microprocesoarelor.
Limbajele evoluate de programare permit accesul la toate resursele sistemelor de
calcul. Performana software este influenat de modul n care a fost proiectat, de
limbajul n care este elaborat i de facilitile oferite de limbajul de asamblare, la
care se ajunge n final. Designul limbajelor de asamblare reprezint un nou mod de
abordare a construirii acestora n vederea ameliorrii performanei software
aplicativ.
Limbajele evoluate de programare elimin suportul nvrii programrii n
limbaj de asamblare pentru a avea acces la toate resursele sistemelor de calcul.
Utilizarea corect a funciilor din bibliotecile standard din programele scrise n
limbajele C++ sau PASCAL ofer programatorilor posibilitile de acces la orice
nivel al resurselor.
n acest nou context, studierea unui limbaj de asamblare se justific pentru
eficientizarea unor secvene de program. Exist posibilitatea de a introduce direct
n textele surs C/C++ secvene asm.
O alt motivaie este nelegerea exact a unor mecanisme de manipulare a
informaiei (lucru pe stiv, lucru cu variabile pointer, definirea i utilizarea
funciilor virtuale).
Dac au existat perioade n care limbajul de asamblare a fost considerat un
produs natural, uneori imperfect, al procesului de proiectare al procesoarelor, acum
se pune i problema de a realiza microprocesoare pornind de la un limbaj de
asamblare dat. Limbajul de asamblare este definit aa fel nct s asigure eficiena,
msurat statistic, fie la implementarea unor mecanisme noi de gestiune a
memoriei, fie n generarea de secvene compacte, fie n reducerea duratei de
execuie a prelucrrilor. n continuare sunt analizate aspecte de baz ale designului
limbajelor de asamblare. Programele scrise ntr-un limbaj de asamblare proiectat cu
luarea n considerare a anumitor criterii de performan, vor propaga efecte pozitive
n toate fazele realizrii codului surs i ale utilizrii software-ului la beneficiari. Se

681

pune n eviden legtura dintre caracteristicile de ordin cantitativ i laturile


calitative ale unul limbaj de asamblare i efectele de antrenare multipl induse.

21.2 Structura instruciunii limbajului de asamblare


Programatorul n limbajele de asamblare, nainte de orice, trebuie s cunoasc structura intern a instruciunilor, care difer de la un limbaj la altul.
Structura intern arat modul n care se dispun la nivel de bii informaiile privind:
codul operaiilor, etichetele i expresiile de adresare ale operanzilor.
irul de bii care memoreaz codul operaiei are o lungime strict dependent
de numrul de operaii de baz pe care le implementeaz limbajul de asamblare.
Astfel, dac proiectantul limbajului de asamblare opteaz pentru un ir de
opt bii, limbajul de asamblare va fi nzestrat cu maxim 256 de mnemonice asociate
unor instruciuni diferite. Numrul foarte mare de mnemonice disponibile permite
definiri de instruciuni diferite pentru aceleai operaii n cazul n care tipul
operanzilor este altul. De exemplu, vor exista instruciuni distincte pentru
efectuarea adunrii n binar, n zecimal mpachetat i n virgul mobil.
Programatorul ce utilizeaz limbajul de asamblare va alege aritmetica n care
lucreaz strict dependent de contextul problemei pe care o rezolv.
Dac proiectantul limbajului de asamblare definete codul operaiei ca un
ir de apte bii, numrul mnemonicelor cu care va manipula programatorul va fi de
cel mult 127. Un astfel de limbaj este mai srac, posibilitile de alegere se reduc.
Chiar dac pot fi definii operanzi de tipuri diferite, implementarea aritmeticilor
presupune apelarea funciilor care s prelucreze datele fiecrui tip folosind operaii
dintre cele 127 implementate n limbaj. Efortul de programare este mult mai
ridicat.
Este posibil ca numrul de instruciuni N, s fie mai mic dect 2k unde k
reprezint lungimea irului de bii pe care este memorat codul instruciunilor.
Gradul de ocupare, G este dat de relaia:
N1
G=

2k

*100

Gradul de neocupare este dat de relaia:


= 100 G

682

Gradul de neocupare este cel care ofer posibilitatea designerilor s


dezvolte un sistem de macrodefiniii coerent sau s impun definirea de noi operaii
de baz ce conduc la reducerea efortului de programare.
Designul structural al limbajului de asamblare are la baz ipoteza conform
creia toate elementele limbajului au aceeai importan. Aceast viziune conduce
la abordarea separat a componentelor instruciunii.
n designul structural resursele sunt privite de sine stttor. Operanzii sunt
stocai n registre (R), n memorie (M) sau sunt definii n corpul instruciunii,
imediat (I). Complexitatea limbajului de asamblare se modific radical n cazul
opiunilor designerului pentru instruciunile cu doi operanzi.
Dac se opteaz pentru ntreaga gam de structuri de operanzi, vor fi
definite instruciuni de tip R-R, R-M, R-I, M-M, M-I. Structurile interne ale acestor
tipuri vor ocupa zone de memorie de lungime variabil.
n cazul n care exist 16 registre de lucru codul operaiei ocup 8 bii, o
instruciune de tip R-R va fi definit pe cel puin 16 bii. Pentru operaii R-R se
asociaz coduri distincte.
n cazul n care codul operaiei este unic, nedepinznd de operanzi, sunt
necesari nc 3 bii, pentru a indica tipul (000 pentru tipul R-R, 001 pentru tipul RM, 010 pentru tipul R-I etc.). Limbajele de asamblare ale generaiilor de
microprocesoare actuale evit tipul de instruciuni M-M, avnd definite mnemonice
pentru lucrul cu iruri de caractere, suficient de flexibile. Expresiile de adresare se
evalueaz n timpul asamblrii, semnificaiile fiind date de coduri memorate pe
anumite poziii din corpul structurii interne a instruciunii.
Folosind o zon de 2 bii se obin toate combinaiile ce corespund
atributelor direct / indirect i indexat / neindexat. Pentru tipologii identificate i
limitate ca numr de expresii de adresare se stabilete o zon care memoreaz
coduri asociate care prin interpretare n timpul execuiei permit utilizarea corect a
informaiilor din zonele "operanzi" din structura intern a instruciunii. Codurile
conduc la posibilitatea realizrii unei variabiliti a lungimii zonei de memorie
ocupat de informaiile despre operanzi.
Designul limbajului de asamblare pentru microprocesoarele 80x86 a condus
la o structur de instruciune intern specific tipurilor de instruciuni R-R, R-M,
R-I, codul operaiei are ncorporate informaii privind formatul datelor (bait,
cuvnt, cuvnt dublu) i direcia de parcurgere (adresare sau traversare) a
memoriei, figura 21.1.

Biii

T T T
7 6 5

T
4

T
3

T
2

d
1

w
0

M M
7 6

reg
5 4 3

Figura 21.1 Structura intern a instruciunii


unde:
T - bii pentru codul operaiei;

r/m
2 1 0

683

d - direcie de parcurgere;
w - tip operand (bait/cuvnt);
MM - interpretarea deplasrii;
reg - registre (semiregistre) codificate;
r/m - tipologii expresii de adresare.
Limbajele de asamblare mai vechi, datorit numrului mare de registre i a
aritmeticilor implementate, au regrupat expresiile de adresare pe un numr mai
restrns de bii. Gradul de dependen a cmpurilor din structura instruciunilor era
foarte slab.
Limbajul de asamblare a microprocesorului convenional x86 are definit un
grad de dependent ridicat ntre elementele din structura instruciunii. Astfel,
deplasarea este interpretat funcie de cmpul w (cmpul MM depinde de cmpul
w), iar cmpul reg depinde ca interpretare tot de cmpul w. Cmpul r/m depinde
de cmpul MM. Dac valoarea MM este 11, cmpul r/m este interpretat reg.

21.3 Designul corectiv pentru limbajele de asamblare


Pentru limbaje precum Fortran, Cobol, PL/l n timp au fost efectuate analize
statistice, toate evideniind neuniformitatea cu care programatorii utilizeaz
instruciunile i tipurile de date i de structuri definite.
n mod normal, experiena oferit de utilizarea facilitilor trebuie s
conduc la perfecionarea limbajelor, aspect realizat prin trecerea de la FORTRAN
IV Ia FORTRAN 77 i acum deja exist FORTRAN 95. Mai dinamic, limbajul C
a nregistrat evoluiile C++ i VISUAL C++. Limbajele de asamblare sunt cele
chemate s permit implementarea noilor mecanisme. Avantajele lucrului pe stiv a
condus la implementarea de instruciuni (push, pop) absente la primele limbaje.
Frecvena redus de lucru n aritmetica zecimal mpachetat a condus la excluderea
din lista mnemonicelor a elementelor corespunztoare operaiilor acestei aritmetici.
Se presupune existena unui program, simplu de altfel, care citete fiiere cu
texte surs n limbaj de asamblare i contorizeaz. instruciunile. Se observ clar c
frecvena cu care apar instruciuni precum mov, add, inc, dec difer radical de
frecvena cu care apar instruciuni ca hlt, aaa, aad, das, lock, les, xchg.
De asemenea, dac alturi de frecvenele cu care sunt utilizate resursele (registre,
zone de memorie) se vor putea defini asocieri operaii - resurse care trebuie tratate
distinct.
Existena metodelor statistice moderne ofer un instrument eficient de
grupare a instruciunilor legate de operanzi ca un tot si tratarea distinct a
instruciunilor din punct de vedere al utilizrii. Toate clasificrile instruciunilor
(dup tipul operaiei, natura operanzilor, tipul operanzilor) sunt strict legate de
latura semantic a limbajului. Metodele de clasificare statistice ofer posibilitatea
de a structura limbajul de asamblare dup rigorile utilizatorilor.

684

Se consider o matrice a frecventelor F cu elemente fij care au semnificaia:


numr de apariii ale instruciunii Ai cu utilizarea resursei Sj. Prin definirea unui
sistem de ponderi adecvat, se procedeaz la agregarea informaiilor, obinndu-se o
msur a intensitii ntrebuinrii unei instruciuni ntr-un context dat (operatori
utilizai). Un algoritm de clasificare conduce la identificarea unei noi tipologii de
instruciuni. Structura intern a instruciunii este rezultatul natural al utilizrii. Se
pornete la proiectarea limbajului de asamblare de la cerinele reale ale
programatorilor. Se spune c se utilizeaz un design corectiv, ntruct clasele se
obin pornind de la programe scrise ntr-un limbaj existent. Noul limbaj de
asamblare este rezultatul introducerii de corecii la un limbaj existent. Pentru ca
rezultatele s fie semnificative este necesar ca eantionul de programe cu care s-a
efectuat constituirea matricei F s fie suficient de mare i s cuprind o diversitate
de programe care s acopere multitudinea de aplicaii care se dezvolt n limbaje de
asamblare.
Clasele de instruciuni obinute dup frecvenele de ntrebuinare n
programe vor avea asociate coduri ale operaiilor care din structur s permit
interpretri diferite.
Dac de exemplu, instruciunea inc ax are frecvena de apariie cea mai
mare, i se va asocia codul de operaie format numai din zerouri.
Dac se opteaz pentru un limbaj de asamblare cu codul operaiei format
din 8 bii, zerourile nesemnificative ca numr permit crearea de grupe de
instruciuni, fr o acoperire consecutiv a submulimilor formate din codurile
consecutive.
n ipoteza c n clasa de instruciuni foarte frecvent ntlnite se afl 18
elemente, reprezentabile pe cinci poziii binare, codurile acestei clase vor avea trei
zerouri n fa (000xxxxx). Din cele 32 de combinaii binare cu cinci poziii sunt
utilizate numai 18.
ntr-o prim etap se realizeaz punerea n coresponden a claselor cu
codurile. n cazul n care rmn instruciuni crora nu li se asociaz coduri datorit
epuizrii celor 256 de combinaii binare, se trece la rafinarea claselor.
Rafinarea este un procedeu complex care vizeaz fie reducerea numrului
de clase, fie translai de instruciuni de la o clas la alta, obinndu-se o alt
repartizare a instruciunilor n clase.
Dac prin restrngerea claselor sau prin translaie s-a obinut creterea
numrului de elemente de la 18 la 31 n clasa instruciunilor cel mai frecvent
folosite i dac -a obinut ncadrarea instruciunilor prin punere n coresponden
cu coduri binare i de opt poziii, se poate trece la dezvoltarea n continuare a
structurii interne a instruciunilor limbajului de asamblare.
Un astfel de limbaj prezint particularitatea c structurarea instruciunilor
ncepe chiar cu codul operaiei. Este mai corect s se vorbeasc de codul operaieioperand, ntruct frecvenele de apariie in seama de operaie i de operanzii
utilizai.

685

Aparent un astfel de limbaj nu mai prezint regularitaile ntlnite la


celelalte limbaje de asamblare.
Structurarea n continuare a instruciunilor se efectueaz depinznd strict de
alctuirea claselor. Tipurile de adresare, modul de parcurgere (stnga/ dreapta),
expresiile de adresare, se vor regsi sau nu la fiecare clas, dup cum rezult din
elementele care o alctuiesc. Cifrele semnificative de pe poziiile zero, unu sau doi
vor marca fiecare tip structural. Chiar dac se nregistreaz "ntreruperi" n
secvenele de atribuire a codurilor, clasele neavnd exact 32 de elemente,
codificarea aceasta a instruciunilor tine seama de particularitile de utilizare ale
limbajului.

21.4 Stabilirea numrului de registre


Limbajele de asamblare consider registrele ca resurse. Se definesc
instruciuni n care se utilizeaz numai anumite registre, ceea ce restricioneaz
foarte mult manipularea datelor. nseamn c registrele nu au funciuni identice,
unele dintre ele fiind dedicate.
Astfel, n cazul limbajului de asamblare definit pentru microprocesoarele
x86, registrul AX este dedicat pentru numeroase operaii (ajustri, nmuliri,
mpriri) i este destinaie pentru multe operaii. Problematica pe care o are
designerul este de a stabili numrul optim de registre pe care s le gestioneze
eficient (statistic) programatorii. Acest optim este rezultatul unui proces de definire
la birou a secvenelor n diferite ipoteze cu luarea n considerare a numrului de
cicluri pe care le determin fiecare soluie dat. Se consider un lot de probleme
frecvent rezolvate in limbaj de asamblare P1, P2, ... Pm. Se vor scrie programe n
ipoteza n care limbajul este definit cu un singur registru de lucru. Se va observa
abundena de instruciuni mov pentru stocare rezultate intermediare i pentru
iniializri. Scriind un program de analiz a celor m programe care ofer soluii
pentru problemele Pi, i=1,2,..,m, se evalueaz volumul de prelucrri exprimat ca
numr de cicluri main.
Tot astfel se procedeaz i pentru definirile de limbaje de asamblare n care
exist dou, trei sau mai multe registre. Numrul de registre determin i
implementrile de structuri fundamentale prin intermediul expresiilor de adresare.
De exemplu, registrul index permite att implementarea structurii de dat masiv,
ct i definirea structurii repetitive.
Utilizarea indicatorului numr de cicluri main, conduce la omogenizarea
de rezultate, chiar dac se pierd anumite informaii. El permite agregri i
manipularea cu medii aritmetice i dispersii.
Dac se consider mai multe loturi de probleme, este posibil analiza
stabilitii limbajului de asamblare - tot din punct de vedere statistic. n cazul n
care s-a obinut un grad de stabilitate corespunztor, se poate trece la alegerea

686

numrului eficient de registre n raport cu criteriul reducerii numrului de cicluri


main.
Cu ct lotul problemelor este mai vast, exist posibilitatea de a acoperi o
gam mare de aplicaii i de a face un studiu mai complet asupra comportamentului
limbajului de asamblare. Indiferent de mrimea lotului, este riscant s se vorbeasc
despre optimizarea limbajului sau de stabilirea numrului optim de registre de
lucru, dedicate sau nu. Oricum atributul de optim se va referi la lotul de programe
rezultat, orice extensie fiind riscant dac nu s-a studiat suficient reprezentativitatea
acestui lot.
Cercetrile efectuate pn n prezent pe un lot de 60 de programe cu acelai
grad de complexitate pune n eviden eficiena unui limbaj de asamblare cu dou
registre acumulator (mperecheate corespunztor pentru a se face identificarea
corect a operanzilor i pentru eliminarea ambiguitii n cazul ajustrilor). De
asemenea, tipurile de expresii de adres ce intervin n registre pot fi dezvoltate
pentru a introduce nivele de indirectare de ordin superior.

21.5 Concluzii
Designul limbajului de programare cu luarea n considerare a finalitii,
scrierea de programe, determin proiectarea unui limbaj pentru utilizator.
Numeroase dificulti care apar n asamblare, la generarea formei interne a
instruciunilor, sunt probleme independente de programator. Odat rezolvate
corect, programul asamblor va opera asupra unei mulimi de programe n cretere,
propagnd efectele pozitive ale limbajului.
Dac la proiectare sunt luate n considerare i elemente de compresie a
programelor n cod main, limbajul de asamblare ofer o trstur benefic tot la
nivelul utilizatorilor finali. Preocuprile de design pentru limbaje de asamblare
capt acum o nou caracteristic, aceea de a fi deschis spre utilizatori. Opiunea
spre neomogenitate de tratare a instruciunilor nu determin complicaii la nivelul
utilizatorilor. La nivelul celor care implementeaz limbajul de asamblare, fiecare
neomogenitate se traduce n modalitate distinct de tratare. Diversitii de tipuri de
instruciuni i va corespunde o cretere a complexitii programului asamblor.
Pentru a obine rezultate cu nivel de stabilitate ridicat este necesar crearea
unei baze de programe scrise n limbaj de asamblare care s includ ct mai multe
stiluri de programe i ct mai multe tipuri de probleme rezolvate.
Ca i n cazul altor limbaje, designul limbajelor de asamblare ia n
considerare meninerea unui nivel ridicat al ortogonalitii instruciunilor. Studiul
efectuat acum a presupus ortogonalitatea deja existent a instruciunilor din
limbajul de asamblare asociat microprocesoarelor x86, fr a se proceda la
definirea de noi instruciuni sau noi tipuri de expresii de adresare. Dac se vor
efectua n viitor i aceste modificri, designul limbajului de asamblare capt un

687

nivel de profunzime mult mai accentuat, influennd portabilitatea limbajului, n


sensul reducerii efortului de integrare a componentelor n software neomogen.

688

22
ELEMENTE DE GRAFIC
22.1 Istoric al adaptoarelor grafice
Imaginea pe care un computer o reprezint cu ajutorul unui monitor a fost
nc de la nceputurile erei informatice cea mai important metod utilizat pentru
a interaciona cu utilizatorul. Ca multe alte familii de calculatoare, cele compatibile
IBM-PC folosesc n acest scop un dispozitiv electronic numit adaptor grafic sau
plac video i dispozitivul de afiare propriu-zis (monitorul, ecranul cu cristale
lichide i altele).
Sistemele pentru afiarea informaiei s-au dezvoltat foarte mult ncepnd cu
monitoarele monocrome folosite pentru procesarea de text i sistemele bazate
exclusiv pe modul text din jurul anilor 1970.
n anul 1981 compania IBM a introdus adaptorul grafic color CGA (Color
Graphics Adapter). Acest sistem era capabil s reprezinte patru culori i avea o
rezoluie de 320x200. Dei adaptoarele CGA ofereau faciliti pentru grafic,
aceste faciliti erau mult prea simple comparativ cu nivelul cerinelor pentru
procesare de text, procesare grafic sau alte aplicaii grafice sofisticate.
n anul 1984 compania IBM a introdus adaptorul grafic EGA (Enhanced
Graphics Adapter). Acest adaptor, cu performane mult mai bune dect
precedentul, oferea o rezoluie mult mbuntit de 640x350 de pixeli i
posibilitatea de a reprezenta 16 culori simultan.
n 1987 compania IBM a fcut public ceea ce urma s devin standardul
minim acceptat, pstrat i astzi, i anume adaptorul VGA (Video Graphics
Adapter). Rezoluia maxim a acestui adaptor depinde de numrul de culori
afiabile simultan. Astfel, se poate opta ntre 640x480 de pixeli cu 16 culori
simultane sau 320x200 de pixeli cu 256 de culori simultane. Toate calculatoarele
actuale compatibile IBM-PC au un adaptor grafic compatibil VGA.
n 1990 compania IBM a introdus adaptorul grafic extins XGA (Extended
Graphics Array), ca succesor al sistemului 8514/A, propriu IBM. O versiune
ulterioar a acestui adaptor, XGA-2, oferea o rezoluie de 800x600 pixeli n mod
true color, aproximativ 16 milioane de culori, sau 1024x768 de pixeli n mod
high color, adic 65536 de culori afiabile simultan.
Cele mai multe adaptoare grafice vndute n ziua de azi sunt descrise ca
SVGA (Super Video Graphics Array). Iniial SVGA a nsemnat doar ceva mai
bun dect VGA, diveri productori ncercnd s impun propriul standard.

689

Ulterior, VESA (Video Electronics Standards Association) a stabilit un standard


comun pentru adaptoarele SVGA, numit Extensia BIOS VESA.
n mod obinuit un adaptor grafic SVGA suport o palet de 16000000
culori, dei cantitatea de memorie video limitez numrul de culori n anumite
rezoluii. n general, cu ct diagonala monitorului este mai mare cu att el poate
reprezenta rezoluii mai mari. Astfel, un monitor SVGA cu diagonala de 14 inch de
obicei poate afia 800x600 pixeli, pe cnd un monitor mare, cu diagonala de 21 de
inch reprezint 1280x1024 sau chiar 1600x1200 pixeli.
O imagine reprezentat pe monitor are trei caracteristici principale:
rezoluia, aceasta fiind produsul dintre numrul de pixeli reprezentai pe
orizontal i vertical (de exemplu 320x200, 640x480)
numrul de culori afiabile simultan; din acest punct de vedere modurile
grafice sunt paletate sau nepaletate.
rata de remprosptare a imaginii (sau refresh), care poate varia ntre
limite largi; VESA recomand o rat de 72Hz (72 cadre/secund).
Un mod grafic este definit ca o combinaie ntre rezoluia afiat i numrul
de culori afiabile. Un caz particular al modurilor grafice, prezent numai la
calculatoarele IBM-PC, este aa-numitul mod text. Prin acest mod se reprezint
caractere pe ecran prin scriere direct n memoria principal la adresa B800:0000h,
rutinele BIOS ale calculatorului fcnd scanarea zonei respective i conversiile
necesare afirii caracterelor pe ecran, folosind matrie de fonturi.
S-a menionat anterior c modurile grafice sunt paletate sau nu. Un mod
grafic paletat are asociat o palet de culori, iar valorile folosite pentru a stabili
culoarea unui pixel pe ecran nu reprezint culori absolute, ci indeci n paleta de
culori, care conine culori n format RGB. ntr-un mod grafic nepaletat fiecare pixel
are asociat un grup de baii care conin culoarea real. Astfel, exist urmtoarele
moduri nepaletate:
pixel reprezentat pe 2 baii, cu 32768 de culori (5 bii pentru fiecare
component RGB)
pixel reprezentat pe 2 baii, cu 65536 de culori (5 bii pentru rou i
albastru, i 6 bii pentru verde), mod numit high color
pixel reprezentat pe 3 baii, cu 16777216 de culori (un bait pentru
fiecare component RGB), mod numit true color
pixel reprezentat pe 4 baii mod true color cu informaie de
transparen (un bait pentru fiecare component RGB i un bait pentru
canalul de transparen, numit alpha channel)
Producerea imaginii pe ecranul monitorului se face prin operaia de scanare
a memoriei video. Astfel, informaia din memoria video este procesat de un
convertor analogic-digital (DAC), care transform imaginea nscris n mod liniar
din memoria video n semnal analogic care este transmis mai departe monitorului.
Numrul de culori afiabil simultan depinde de capacitatea de stocare
alocat fiecrui pixel. Astfel, 4 bii permit 16 culori simultane, iar 3 baii permit

690

aproximativ 16000000 de culori. Generaliznd, cu ajutorul a n bii se reprezint 2 n


culori.
Regula principal pentru determinarea numrului maxim de culori afiabile
la o anumit rezoluie este urmtoarea:
rezoluie orizontal * rezoluie vertical * memorie alocat pentru un pixel <= memoria video

Astfel, un adaptor grafic ce dispune de 4Mbytes memorie video poate


reprezenta 1280x1024 cu maxim 65536 de culori sau 1024x768 cu maxim
16000000 milioane de culori.
22.2 Rutine BIOS i moduri grafice

Rutinele BIOS furnizeaz un mod elegant de a programa


adaptoarele video. Folosind ntreruperea 10h se poate invoca un
set de funcii care permit stabilirea modului video, citi/scrie
valorile pentru pixeli. n tabelul de mai jos sunt listate modurile
video valabile n rutinele video BIOS att n mod text ct i
grafic, fiecare specifice unui anumit tip de monitor (dac
adaptorul accept mai multe tipuri de monitor). BIOS-ul este
folosit pentru operaii primare de afiare. Pentru animaie mai
complicat i mai rapid este recomandat citirea/scrierea
direct n memoria video.
Tabelul 22.1. Modurile video BIOS
Modul
Rezoluie i culori
0
40X25 text n 16 nuane de gri
1
40X25 text n 16 sau 8 culori
2
80X25 text n 16 nuane de gri
3
80X25 text n 16 sau 8 culori
4
320X200 grafic n 4 culori
5
320X200 grafic n 16 nuane de gri
6
640X200 grafic n alb i negru
7
80X25 text n alb i negru
13
320X200 grafic n 16 culori
14
640X200 grafic n 16 culori
15
640X350 grafic n alb i negru
16
640X350 grafic n 4 sau 16 culori
17
640X480 grafic n alb i negru
18
640X480 grafic n 16 culori

Tipul de adaptor
CGA
CGA
CGA
CGA
CGA
CGA
CGA
Monochrom
EGA
EGA
EGA
EGA
VGA
VGA

691

19

320X200 grafic n 256 culori

VGA

Dac se dezvolt o aplicaie, mai nti trebuie determinat tipul adaptorului


grafic i ales cel mai bun mod video pe care hardware-ul l poate suporta.
Procedura DetVideoAdap face acest lucru i l ntoarce n registrul AX. Folosind
aceast informaie, se alege cel mai bun mod video din tabelul 22.1 care se
potrivete aplicaiei. De exemplu, dac se gsete VGA, se poate alege modul 8,
care va permite afiarea n 16 culori folosind rezoluie de 640X480. Dup ce se
alege modul video, se va folosi funcia BIOS de setare a modului video dup cum
urmeaz:
; In segmentul de date
modv db
0
.
.
; In segmentul de cod
.
.
mov ah, 0
; setarea modului video
mov al, modv
; folosind intreruperea 10h
int 10h
.
.
; determina modul video
;inainte de de a apela aceasta procedur, setati ES:DI cu adresa
;unui buffer de 64 octeti
;procedura returneaz una din urmatoarele constante n registrul
;AX
MDA
HGC
CGA
EGA
VGA

=
=
=
=
=

1;
2;
3;
4;
5;

.model SMALL
.code
Wich_adapter PROC
mov
ax, 1B00h
int
10h
cmp
al, 1Bh
; al va fi 1Bh pentru VGA
jne
TestIfEGA
mov
ax, VGA
jmp
SHORT DoneAdapter

692
TestIfEGA :
mov
mov
test
jz
mov
jmp

ax, 40h
es, ax
BYTE PTR es:[87h], 0FFh
TestIfCGAorHGC
ax, EGA
SHORT DoneAdapter

TestIfCGAorHCG:
; mai intai obtine flag-ul echipamentului
int
11h
and
al, 30h
; verifica modul video initial
cmp
al, 30h
jne
ItIsCGA
mov
cx, 800h
mov
dx, 3BAh
TestIfHGC:
in
al, dx
; in HGC, bit-ul 7 al port-ului 3BAh
test al, 80h
; va fi 1 in timpul retragerii
verticale
jnz
ItIsHGC
; cicleaz pentru a vedea dac bitul
devine 1
loop TestIfHGC
;altfel este MDA
mov
ax, MDA
jmp
SHORT DoneAdapter
ItIsHGC:
mov
ax, HGC
jmp
SHORT DoneAdapter
ItIsCGA:
mov
ax, CGA
DoneAdapter:
ret
WichAdapter ENDP
END

nainte de a apela procedura DetVideoAdap se va iniializa valoarea


registrului ES:DI cu adresa unui buffer (zone de memorie rezervat) de 64 octei.
Dac este detectat modul video VGA, funcia 1Bh a ntreruperii video BIOS 10h
returneaz 64 de octei de informaie in acest buffer.

22.3 Lucrul n mod grafic folosind un adaptor VGA


Modul video 13h, din VGA standard, este modul n care se
realizeaz cu cea mai mare uurin cele mai rapide rutine de
grafic color.

693

Acest mod folosete un singur segment de memorie liniar, mapat pe pixeli


n aa fel nct fiecare bait controleaz exact un pixel. Astfel, sunt posibile 256 de
culori simultan pe ecran, cu o rezoluie de 320x200 pixeli.
Acest mod este paletat, n sensul c nu se lucreaz cu valori absolute de
culoare. Atributul de culoare al fiecrui pixel este un deplasament n interiorul unei
palete care conine valori RGB reale. Schimbarea valorilor din paleta de culori este
o tehnic de animaie specific modurilor grafice paletate, deoarece schimbarea se
reflect imediat n imaginea prezentat pe ecran.

Folosind modul video VGA 13h se poate afia o


imagine bitmap de mrime 320x200 cu 256 de culori pe
ecran doar prin copierea acestei imagini la adresa
A000h:0000h. Acest mod de lucru face posibile tehnici de
animaie foarte rapide cu eliminarea fenomenului de
flickering (clipirea ecranului sau ruperea frame-urilor
datorit unui refresh video prea lent).
O astfel de tehnic este urmtoarea: presupunnd c exist un mic desen de
25x25 de pixeli care se dorete a fi mutat n diverse poziii pe ecran, metoda const
n punerea unei imagini de fond folosind tehnica prezentat anterior, copierea zonei
de 25x25 pixeli unde se dorete a fi desenul ntr-un buffer temporar, plasarea
desenului pe ecran n poziia salvat, ateptarea unui anumit timp dictat de viteza
sistemului i a animaiei dorite urmat de rescrierea bufferului salvat n vechea
poziie dup care se trece la o nou poziie. Folosind aceast metod nu se modific
n nici un fel imaginea de fond, iar calitatea animaiei este foarte bun.
Printre modurile VGA exist un mod nedocumentat, numit modul X, care
este foarte asemntor cu modul 13h cu excepia faptului c dispune de mai muli
pixeli pe vertical (320x240), la 256 de culori. Adresarea acestui mod presupune
folosirea regitrilor VGA, nemaifiind posibil adresarea direct prin scriere la
adresa A000h:0000h.
De asemenea se poate programa in VGA folosind o rezoluie de 320x400 cu
256 de culori. Acest mod este tot modul 13h dar se folosesc 4 plane de culoare.
Modul 13h are aceast rezoluie n mod nativ, dar designerii au dorit s foloseasc
numai 64k din motive de segmentare a memoriei n modul de adresare real, i astfel
fiecare linie este afiat de dou ori, de unde rezoluia vertical njumtit
(320x400). Dac se folosesc 4 plane de bii se poate controla fiecare a doua linie
ascuns.

694

Figura 22.1 Iluzie optic


Se prezint n continuare un program care realizeaz o iluzie optic,
folosind modul VGA 13h, 320x200 cu 256 de culori, figura 22.1.
Bara din centrul imaginii este realizat folosind o singura culoare, dar pare
construit dintr-un gradient datorit imaginii de fond.
; Acest cod a fost asamblat cu NBASM 00.23.xx
.model tiny
.code
org

100h

; adresa de inceput al unui .COM

.start
push ds
pop es
mov

PLoop:

;
;
ax,ax
;
di,offset
cx,64

xor
mov
stosb
stosb
stosb
inc ax
loop PLoop
mov

; asigur ds=es

setare palet de culori cu


256 nuane de gri incepnd
cu 0.0.0, 1.1.1, 2,2,2, ...
Palette
;
;
;
;
;
;

int

ax,0013h; setm modul video la


; rezoluia 320x200x256
10h
;

mov
xor

dx,offset Palette
bx,bx

; scriem paleta n DAC


;

695

ALoop:

mov
mov
int

cx,64
ax,1012h
10h

;
;
;

mov
mov

ax,0A000h ; pointer la mamoria VGA


es,ax
;

mov

di,14464

; plasm imaginea n centrul


; ecranului

call Fade

; afim partea superioar

mov

; afim bara din mijloc (10


; linii)
; culoarea din mijloc
;
;
;
;
;
;
;

cx,10

mov al,32
push cx
mov cx,128
rep
stosb
add di,192
pop cx
loop ALoop
call Fade

; afim a treia parte

xor
int

ah,ah
16h

; ateptm o tast

mov
int

ax,0003h
10h

; setm modul text(80x25)


;

.exit

; ieire n DOS

proc near

Fade

stosb
loop PLoop2
add di,192
pop cx
loop PLoop1
ret
endp

;
;
;
;
;
;
;
;
;
;
;
;
;
;
;
;

Palette

dup

; paleta de culori

Fade

PLoop1:
PLoop2:

mov cx,50
push cx
mov cx,64
mov al,cl
dec al
stosb

768,?

afiarm prima i a treia


parte
50 de linii
64 de culori

cte dou coloane pentru


fiecare culoare

696
.end

n continuare este prezentat o colecie de proceduri sunt folosite pentru


manipularea paletei de culori VGA. Sursa poate fi folosit numai cu
DOS-extender-ul DOS4GW i trebuie asamblat folosind Turbo
Assembler.
; Manipularea paletei de culori VGA
; se folosete modul protejat (numai pentru procesoare >=80386)
ideal
p386
radix 10
locals @@
model flat

;
;
;
;
;

modul TASM ideal


procesor 80386
folosim numere zecimale
etichete locale @@
mod protejat liniar pe 32 de bii

dataseg

; tabela de indeci VGA (mod cu 16 culori)


VGA

DB 0,1,2,3,4,5,20,7,56,57,58,59,60,61,62,63

; valori RGB implicite (16 culori)


VGACOLOR DB
0, 0, 0,
0, 0,42,
0,42, 0,
0,42,42
DB 42, 0, 0, 42, 0,42, 42,42, 0, 42,42,42
DB 21,21,21, 21,21,63, 21,63,21, 21,63,63
DB 63,21,21, 63,21,63, 63,63,21, 63,63,63
codeseg
PUBLIC SETRGB16, GETRGB16, SETDAC16, GETDAC16
PUBLIC RestoreVGA
PUBLIC SETRGB256, GETRGB256, SETDAC256, GETDAC256
; ateapt sincronizarea vertical
proc VerticalSync near
push
EAX EDX
mov
DX,03DAH
mov
AH,8
@@1: in
AL,DX
test
AL,AH
jnz
@@1
@@2: in
AL,DX
test
AL,AH
jz
@@2
pop
EDX EAX
ret
endp VerticalSync

;
;
;
;

registru de stare
bit de sincronizare vertical
citete starea
ateapt sincronizarea

; citete starea

697
; ateapt sincronizarea orizontal
proc HorizontalSync near
push
EAX EDX
mov
DX,03DAH
mov
AH,1
@@1: in
AL,DX
test
AL,AH
jnz
@@1
@@2: in
AL,DX
test
AL,AH
jz
@@2
pop
EDX EAX
ret
endp HorizontalSync

;
;
;
;

registru de stare
bit de sincronizare orizontal
citete starea
ateapt sincronizarea

; citete starea

; seteaz paleta RGB pentru o anumit culoare (mod cu 16 culori)


; parametri [ESI=culoare EAX=rou EBX=verde ECX=albastru]
;
modific [EDX]
proc SETRGB16 near
mov
AH,AL
add
ESI,OFFSET EGA
mov
AL,[ESI]
mov
DX,03C8h
out
DX,AL
inc
DX
mov
AL,AH
out
DX,AL
mov
AL,BL
out
DX,AL
mov
AL,CL
out
DX,AL
ret
endp SETRGB16

; tabela de culori VGA


; adresa registrului PEL VGA
; 03C9h = registru de date VGA PEL
; scrie valoare rou
; scrie valoare verde
; scrie valoare albastru

; regsete paleta RGB pentru o anumit culoare (mod cu 16 culori)


; parametri [ESI=culoare EAX=rou EBX=verde ECX=albastru]
;
modific [EDX]
proc GETRGB16 near
and
EAX,0Fh
add
EAX,OFFSET EGA
mov
AL,[EAX]
mov
DX,03C7h
out
DX,AL
add
DX,2
in
AL,DX
mov
[EBX],AL
in
AL,DX
mov
[ESI],AL

; tabela de culori VGA


; adresa registrului PEL VGA
; 03C9h = registru de date VGA PEL
; citete valoare rou
; citete valoare verde

698
in
AL,DX
mov
[EDI],AL
ret
endp GETRGB16
;
;
;
;

; citete valoare verde

seteaz valori RGB pentru un bloc consecutiv de culori (mod cu 16


culori)
parametri [EBX=culoare ECX=numr ESI=&sursa]
modific [EAX EDX]

proc SetDAC16 near


add
EBX,OFFSET VGA
call
VerticalSync
cli
@@1: mov
DX,03C8h
mov
AL,[EBX]
inc
EBX
out
DX,AL
inc
DX
outsb
outsb
outsb
dec
ECX
jnz
@@1
sti
ret
endp SetDAC16

; deactiveaz ntreruperile
; 03C8h = adresa registrului VGA PEL
; tabela de culori VGA

;
;
;
;

03C9h
scrie
scrie
scrie

= registru de date VGA PEL


valoare rou
valoare verde
valoare albastru

; activeaz ntreruperile

; regsete valori RGB pentru un bloc consecutiv de culori (mod cu


16
; culori)
; parametri [EBX=culoare ECX=numr ESI=&sursa]
; modific [EAX EDX]
proc GetDAC16 near
add
EBX,OFFSET VGA
call
VerticalSync
cli
@@1: mov
DX,03C7h
mov
AL,[EBX]
inc
EBX
out
DX,AL
add
DX,2
insb
insb
insb
dec
ECX
jnz
@@1
sti
ret
endp GetDAC16

; dezactiveaz ntreruperi
; tabela de culori EGA
;
;
;
;
;

adresa registrului de scriere


03C9h = registru de date VGA PEL
citete valoare rou
citete valoare verde
citete valoare albastru

; activeaz ntreruperi

699
; seteaz valori implicite RGB (mod cu 16 culori)
; modific [EAX EBX ECX EDX ESI]
proc RestoreVGA near
mov
EBX,0
mov
ECX,16
mov
ESI,OFFSET EGACOLOR
call SetDAC16
ret
endp RestoreVGA

;
;
;
;

index de start
numr de culori
tabela de culori implicit
seteaz palet culori

; seteaz valorile RGB pentru o anumit culoare (mod cu 256 de


culori)
; parametri [EAX=culoare EBX=rou ECX=verde EDI=albastru]
; modific [EDX]
proc SETRGB256 near
mov
DX,03C8h
out
DX,AL
inc
DX
mov
AL,BL
out
DX,AL
mov
AL,CL
out
DX,AL
mov
AX,DI
out
DX,AL
ret
endp SETRGB256
;
;
;
;

; adres registru scriere VGA PEL


; 03C9h = registru de date VGA PEL
; scrie valoare rou
; scrie valoare verde
; scrie valoare albastru

regsete valorile RGB pentru o anumit culoare (mod cu 256 de


culori)
parametri [EAX=culoare EBX=rou ECX=verde EDI=albastru]
modific [EDX]

proc GETRGB256 near


mov
DX,03C7h
out
DX,AL
add
DX,2
in
AL,DX
mov
[EBX],AL
in
AL,DX
mov
[ESI],AL
in
AL,DX
mov
[EDI],AL
ret
endp GETRGB256

; 03C9h = registru de date VGA PEL


; citete valoare rou
; citete valoare verde
; citete valoare albastru

; seteaz valorile RGB pentru un bloc consecutiv de culori (mod cu


256
; de culori)
; parametri [EAX=culoare ECX=numr de culori ESI=&sursa]
; modific [EBX EDX]

700
proc SetDAC256 near
mov
BX,CX
shl
CX,1
add
CX,BX
call
VerticalSync
cli
mov
DX,03C8h
PEL
out
DX,AL
inc
DX
rep
outsb
sti
ret
endp SetDAC256

; dezactiveaz ntreruperi
; 03C8h = adres registru scriere VGA

; 03C9h = registru de date VGA PEL


; activeaz ntreruperi

; seteaz valorile RGB pentru un bloc consecutiv de culori (mod cu


256
; de culori)
; parametri [EAX=culoare ECX=numr de culori ESI=&sursa]
; modific [EBX EDX]
proc GetDAC256 near
mov
BX,CX
shl
CX,1
add
CX,BX
call
VerticalSync
cli
mov
DX,03C7h
out
DX,AL
inc
DX
rep
insb
sti
ret
endp GetDAC256

; dezactiveaz ntreruperi

; 03C9h = registru de date VGA PEL


; activeaz ntreruperi

end

22.4 Lucrul n mod grafic folosind un adaptor SVGA


Modurile SVGA au fost standardizate de asociaia productorilor de
adaptoare video VESA. Exist n acest sens dou standarde larg implementate n
marea majoritate a plcilor video, i anume:
extensia BIOS VESA 1.2
extensia BIOS VESA 2.0
Foarte recent VESA a elaborat standardul 3.0, ale crui specificaii pot fi
regsite la adresa http://www.vesa.org.
Extensia BIOS VESA 1.2 ofer n comparaie cu VGA o mulime de noi
moduri video, n general cu rezoluii mari i moduri de culoare high color - true

701

color. Adresarea memoriei video se face printr-o operaie de paginare. Astfel,


poriuni de 64kbytes din memoria video sunt aduse in segmentul A000h-AFFFh,
modificate pentru a se afia seciunea de ecran corespunztoare i ulterior rescrise
n memoria video. Astfel, este posibil utilizarea VBE1.2 (VESA BIOS Extension)
folosind modul real de adresare specific 8086.
Extensia BIOS VESA 2.0 este destinat exclusiv modului de lucru protejat,
pentru procesoare din familia 80386, iar adresarea memoriei video se poate face
direct, n mod liniar. Astfel, standardul prevede o rutin BIOS cu care se poate
obine adresa fictiv (de obicei peste 2Gbytes) la care memoria video este mapat
peste memoria real adresabil n mod protejat.
Aceast seciune prezint modul de lucru folosind standardul VESA 1.2.
Codul inclus conine o procedur de desenare a unei linii, fiind bazat pe algoritmul
lui Bresenham.
Lucrul cu VBE 1.2 presupune urmtoarele:
memoria video de obicei peste 1Mbyte - nu poate fi accesat integral
memoria video se partajeaz in seciuni cu o anumit granularitate
pentru desenare pe ecran fiecare seciune trebuie adus la adresa A000h,
modificat conform algoritmului folosit, i transferat n memoria video
De exemplu, partajarea unei memorii video de 1Mbyte cu o granularitate de
64kbytes se face n exact 16 seciuni care sunt aduse la adresa A000h.
Dac se partajeaz aceeai memorie cu o granularitate de 4 kbytes se obin mai
multe mapri posibile. Astfel, fereastra adresabil este tot de 64 kbytes dar aceast
fereastr poate fi aliniat din 4 n 4 kbytes.
O granularitate mai fin mrete viteza de afiare. Se folosete exemplul de
mai jos pentru a demonstra acest fapt.
Folosind seciuni de 64kbytes, cuvntul semnificativ din adresa liniar a
pixelului este localizarea seciunii, iar cuvntul mai puin semnificativ este poziia
n cadrul seciunii.
Folosind seciuni de 4kbytes, cei mai nesemnificativi 12 bii sunt
deplasamentul, iar biii semnificativi care rmn sunt poziia seciunii n memoria
video.
Un avantaj important al granularitii de 4kbytes este faptul c seciunile se
pot alinia mult mai uor. Cu o rezoluie orizontal de 640 de pixeli, 32 de linii
folosesc 20 kbytes, care se divide la 4kbytes. Dac pentru afiarea unei linii
algoritmul se limiteaz la ferestre de 20kbytes atunci nu trebuie testat depirea
ferestrei.
O granularitate de 64kbytes se aliniaz cu ecranul doar la 512 linii, ceea ce
nseamn 320kbytes, deci trebuie testate depirile de fereastr pentru fiecare linie
de rastru orizontal.
Se schimb, folosind rutine VESA 1.2, lungimea liniei orizontale de rastru
la o mrime care este putere a lui 2 (de exemplu 1024). O astfel de lungime
garanteaz c o seciune se va termina ntotdeauna la marginea ecranului, dar dac

702

rezoluia orizontal este mai mic de 1024 se va pierde foarte mult memorie video
n acest mod.
Procedura de trasare a unei linii prezentat mai jos folosete, ca optimizare,
testarea faptului c ambele puncte extreme ale liniei sunt n aceeai seciune. Dac
ambele puncte sunt n aceeai seciune, atunci nu este necesar schimbarea
seciunii. Dac ele nu sunt n aceeai seciune, atunci pentru fiecare punct se
testeaz depirea seciunii curente.
.486
code

segment para public use16


assume
cs:code

PgDown
push
push
xor
mov
add
mov
call
pop
pop
endm
PgUp

macro
bx
dx
bx,bx
dx,cs:winpos
dx,cs:disp64k
cs:winpos,dx
cs:winfunc
dx
bx

macro
push
push
xor
mov
sub
mov
call
add
inc
pop
pop

bx
dx
bx,bx
dx,cs:winpos
dx,1
cs:winpos,dx
cs:winfunc
di,cs:granmask
di
dx
bx

mov
mov
mov

ax,seg stk
ss,ax
sp,200h

; seteaz stiva

call

GetVESA

; iniializeaz variabile VESA

mov
mov
int

ax,4f02h
bx,0101h
10h

;
; modul VESA 101h (640x480, 256 culori)
;

mov
mov

ax,0a000h
ds,ax

endm

703
mov
mov
mov
mov
mov
call

eax,10h
ebx,13h
ecx,20bh
edx,1a1h
ebp,21h
Lin

mov
int

ax,4c00h
21h

; afieaz linie

GetVESA
proc
; se iniializeaz variabile n funcie de granularitatea ferestrei
mov
ax,4f01h
mov
cx,0101h
lea
di,buff
; folosim rutina VESA pentru
push cs
; a regsi parametrii modului 101h
pop
es
int
10h
add
di,4
mov
ax,word ptr es:[di] ;granularitatea ferestrei (n KB)
shl
ax,0ah
dec
ax
mov
cs:granmask,ax
; = granularitatea - 1 (n Bytes)
not
ax
clc
GVL1:
inc
cs:bitshift
rcl
ax,1
jc
GVL1
add
cs:bitshift,0fh
inc
ax
mov
disp64k,ax
add
di,8
mov
eax,dword ptr es:[di]
; adresa ferestri de control
mov
cs:winfunc,eax
ret
buff
label byte
db
100h dup (?)
endp
Lin
proc
; Date de intrare: eax: x1, ebx: y1, cx: x2, dx: y2, bp: culoare
; Modific: ax, bx, cx, edx, si, edi
; Folosete:
;
winfunc(dd),winpos(dw),page(dw),granmask(dw),disp64k(dw),bitshift(d
b)
; eax, ebx trebuie s aib cuvintele semnificative setate pe 0
cmp
ja

dx,bx
LinS1

; sortare vrfuri

704
xchg
xchg

ax,cx
bx,dx

LinS1:
sub
ja
neg
xor

cx,ax
LinS2
cx
cs:xinc1[1],28h

LinS2:
sub
neg
dec

dx,bx
dx
dx

; calcul delta_x
; modific bucla intern dup semn

;delta_y

shl
add
lea

bx,7
ax,bx
edi,[eax][ebx*4]

mov
xor
mov
shl
add
mul
push
mov
shld
pop
add
and
mov
call
mov

si,dx
bx,bx
ax,cs:page
ax,2
; pageOffset=page*5*disp64K
ax,cs:page
cs:disp64k
cx
; iniializeaz fereastr CPU
cl,cs:bitshift
; la punctul superior al liniei
edx,edi,cl
cx
dx,ax
di,cs:granmask
cs:winpos,dx
cs:winfunc
dx,si

mov
mov

ax,bp
bx,dx

; calcul adres liniar de start

;ax:culoare, bx:err-acumulator, cx:deltaX, dx:lungime vertical


;di:localizare n fereastra CPU, si:deltaY, bp:culoare
LinL1:
mov
add
jns
LinE1:
add
jc
inc
jnz
jmp
LinL2:
mov

[di],al
bx,cx
LinS3
di,280h
LinR2
dx
LinL1
LinOut
[di],al

; rutina de desenare

705
xinc1
LinS3:
add
jc
LinE2:
add
jns
jmp

label byte
; trecerea la urmtorul pixel pe
; orizontal

di,1
LinR1
bx,si
LinL2
LinE1

LinR1:
js
LinS7
PgDown
mov
ax,bp
jmp
LinE2
LinS7:
PgUp
mov
ax,bp
jmp
LinE2

; mut pagina n jos cu 64k

; sau n sus cu granularitatea

LinR2:
PgDown
mov
ax,bp
inc
dx
jnz
LinL1
LinOut:
mov
ret
endp

cs:xinc1[1],0c7h

winfunc
winpos
granmask
ferestrei
disp64k
page
video)
bitshift
a
ends
stk

; mut pagina n jos cu 64k

dd
dw
dw

?
?
?

; pointer la funcia VESA setwindow


; locaia ferestrei CPU
; masca de adres in interiorul

dw
dw

?
0

;numr de segmente de 64k


; pagina video (0,1,2 pentru

db

; pentru extragerea biilor de adres


; ferestrei

1MB

segment para stack use16 'STACK'


dw
100h dup (?)

ends
end

22.5 Concluzii
Acest capitol ofer informaii introductive i exemple n domeniul
programrii grafice folosind limbajul de asamblare. Trebuie precizat faptul c toate
aceste exemple ruleaz numai sub sistemul de operare DOS.

706

Programarea grafic in mediul Windows folosete n mod obinuit un strat


de abstractizare care este specific fiecrui adaptor grafic, livrat de productorul
plcii sub forma unui driver. La un nivel mai nalt este interfaa Microsoft DirectX,
care folosete numeroasele funcii de accelerare grafic prezente n plcile grafice
moderne.
Se remarc faptul c standardele VESA nu ofer suport pentru accelerare
grafic, fiecare productor de plci video avnd propriul set de funcii API de nivel
sczut, la marea majoritate nedocumentate.
Resurse suplimentare se regsesc pe World Wide Web la site-ul VESA,
http://www.vesa.org.

23
PROGRAME REZIDENTE
23.1 Caracteristicile programelor rezidente
Pe microcalculatoarele care folosesc sistemul de operare DOS, la un
moment dat poate rula un singur program. Acesta ocup memorie RAM i deine
controlul sistemului de calcul. La ncheierea sa, memoria ocupat este eliberat i
sistemul de operare DOS preia controlul. Exist ns posibilitatea de a realiza
programe care odat ncheiate s rmn n memorie, dnd totodat posibilitatea
altor programe s ruleze n spaiul de memorie rmas liber. Ele pot fi activate de
anumite evenimente externe sau interne sau pot fi activate de ctre un alt program
ce este activ n memorie, n acel moment. Aceste programe se numesc programe
rezidente sau programe TSR (Terminate and Stay Resident).
Bryan Pfaffenberger n Dicionar explicativ de calculatoare definete
programul rezident ca fiind un program accesoriu sau utilitar realizat pentru a
rmne n memoria cu acces aleatoriu (RAM) n permanen, astfel c poate fi
activat cu o comand, chiar dac mai este un alt program n memorie.
Programele rezidente pot fi folosite n operaii de monitorizare a sistemului.
n acest caz programul poate fi activat la intervale de timp stabilite pentru a verifica
starea sistemului sau este activat de evenimente cum sunt solicitrile de resurse,
avnd astfel posibilitatea de a msura diferii parametri sau de a impune un control
suplimentar la acordarea de resurse aplicaiei solicitante. n acest sens se
implementeaz sisteme de securitate care s permit accesul la anumite resurse
doar a persoanelor sau aplicaiilor autorizate. Un exemplu din aceast categorie l

707

reprezint programele antivirus care instaleaz un modul rezident ce supravegheaz


sistemul i declaneaz alarma la orice activitate suspect.
O alt categorie de utilizri a programelor rezidente o constituie utilitarele
ce sunt apelate n mijlocul unei aplicaii prin acionarea unei combinaii de taste.
De exemplu, se poate activa un mic program de tip calculator de buzunar ori de
cte ori se dorete efectuarea unor calcule. Sau se apeleaz un program de
comunicaii care s permit transfer de date de la sau ctre aplicaia activ. Sau pur
i simplu se poate apela o baz de date ce conine informaii utile pentru
soluionarea problemelor ivite n timpul rulrii unei aplicaii.
Tot programele rezidente ofer i posibilitatea de a realiza mbuntiri ale
sistemului de operare. De exemplu se adaug anumite funcii care permit
programelor s lucreze cu dispozitive sau cu structuri de date diferite de
standardele DOS. De asemenea se pot aduga noi comenzi sau mici utilitare celor
oferite de sistemul original de operare, n funcie de nevoile practice.
23.2 ntreruperi pentru programe rezidente
ntreruperile se clasific dup urmtoarea schem:
Mascabile
Externe
Nemascabile

Hardware
Interne
ntreruperi

BIOS
Sistem
DOS

Software
Utilizator

Figura 23.1 Clasificarea ntreruperilor


ntreruperile hardware sunt cablate n circuitele procesorului, ale plcii de
baz i ale perifericelor. Cele externe sunt provocate de diferite echipamente ale
sistemului de calcul, care solicit procesorului tratarea unor evenimente. Ele sunt
de dou tipuri:
mascabile, care pot fi inhibate. Dac indicatorul de condiie IF
(Interrupt Flag) al procesorului este 0, atunci procesorul nu mai ia n
considerare solicitarea echipamentului respectiv. Exemple: ntreruperi

708

solicitate de tastatur, porturile seriale i cele paralele, discul hard,


unitatea de floppy disk.
nemascabile, care nu pot fi inhibate. Procesorul ia ntotdeauna n
considerare aceste ntreruperi. De regul, astfel de ntreruperi sunt
solicitate cnd apare o eroare n memoria sistemului (Parity Check
Error).

ntreruperile hardware interne sunt generate de ctre evenimente interne ale


procesorului, cum ar fi tentativa de a executa o mprire la 0 sau dup execuia
fiecrei instruciuni atunci cnd indicatorul de condiie TF (Trap Flag) are valoarea
1.
ntreruperile software sunt generate de programele n execuie care solicit
procesorului execuia unei instruciuni int n sau into. Aceste ntreruperi sunt
asociate unor servicii BIOS (ntreruperile software BIOS), unor funcii DOS
(ntreruperile software DOS) sau unor rutine scrise de utilizator (ntreruperile
software ale utilizatorului).
Pentru a ti crei rutine trebuie s predea controlul la producerea unei
ntreruperi, sistemul de calcul folosete o tabel numit tabela vectorilor de
ntrerupere. Aceast tabel ncepe ntotdeauna la adresa absolut 00000h, i
conine pentru fiecare dintre cele 256 de ntreruperi un pointer de tip FAR ctre
rutina ntreruperii respective, pointer care refer vectorul pointeri ai ntreruperii.
Primul pointer FAR conine adresa rutinei de tratare a ntreruperii cu numrul 0, al
doilea pointer conine adresa rutinei de tratare a ntreruperii cu numrul 1, al treilea
pointer conine adresa rutinei pentru ntreruperea cu numrul 2 i aa mai departe.
offset rutin INT 0
segment rutin INT 0
offset rutin INT 1
segment rutin INT 1
offset rutin INT 2
segment rutin INT 2

offset rutin INT 255


segment rutin INT 255

0000:0000h
0000:0004h
0000:0008h
0000:000Ch

0000:03FCh
0000:0400h

Figura 23.2 Tabela vectorului de pointeri ai ntreruperilor


Deci adresa pointerului ce conine adresa rutinei de tratare a ntreruperii cu
numrul n este:

709

adresa vector INT n = 4n


La solicitarea unei ntreruperi, procesorul execut urmtoarele operaii:
pune n stiv registrele FLAGS, CS i IP, n aceast ordine;
pune pe valoarea 0 indicatorii de condiie IF i TF;
primete un ntreg pe 8 bii care reprezint numrul ntreruperii;
execut un salt la adresa indicat n tabela vectorilor de ntreruperi, la
poziia corespunztoare numrului ntreruperii primit de procesor.
Codul ntreruperii este furnizat procesorului n una din urmtoarele
modaliti:
n cazul ntreruperilor software numrul este precizat n instruciune;
n cazul ntreruperilor hardware interne sau al celor externe nemascabile
numrul este implicit (este cablat n procesor);
n cazul ntreruperilor hardware externe mascabile procesul este
controlat de un circuit special numit PIC (Programable Interrupt
Controller) i se desfoar n felul urmtor:
o PIC primete de la periferice cereri de ntrerupere, dintre care o
selecteaz pe cea de nivel cel mai ridicat i apoi emite ctre
procesor o cerere de ntrerupere pe linia INTR (Interrupt
Request);
o procesorul verific starea indicatorului IF;
o dac IF este 0 atunci cererea este ignorat;
o dac IF este 1 atunci procesorul emite ctre PIC un semnal pe
linia INTA (Interrupt Acknowledge);
o la primirea semnalului INTA, PIC transmite pe magistrala de
date numrul ntreruperii.
Revenirea din rutina de tratare a ntreruperii se face cu o instruciune IRET
care ncheie rutina de tratare a ntreruperii. Aceast instruciune red controlul la
adresa CS:IP din stiv i reface indicatorii de condiie pe baza coninutului
registrului FLAGS pstrat n stiv. Exist ns i ntreruperi care nu refac
indicatorii de condiie la starea iniial, deoarece ele comunic programului
ntrerupt un rezultat prin intermediul acestor indicatori. O astfel de rutin se ncheie
cu o instruciune RETF 2.
Pentru ntreruperile interne ale procesorului revenirea se face la
instruciunea ce a provocat ntreruperea. Excepie face ntreruperea provocat de
mprirea la 0 pentru procesoarele 8086/8088, la care revenirea se face la
instruciunea urmtoare instruciunii DIV sau IDIV care a provocat ntreruperea. n
cazul celorlalte ntreruperi revenirea se face la instruciunea urmtoare.
Orice rutin de tratare a unei ntreruperi trebuie s ndeplineasc minimum
urmtoarele condiii:
s aib grij s pstreze contextul nealterat;

710

s evite generarea de noi ntreruperi;


s minimizeze timpul de tratare a ntreruperii. Acest lucru este necesar
pentru a nu bloca sistemul, deoarece pot exista foarte multe solicitri de
ntreruperi care trebuie s fie rezolvate. De asemenea, este de preferat ca
timpul de tratare a unei ntreruperi s fie independent de contextul n
care s-a generat ntreruperea (n sistemele de execuie n timp real este
necesar s cunoatem cu precizie timpul necesar fiecrei rutine);
nainte de a reveni la programul ntrerupt trebuie s asigure scoaterea de
pe stiv a tuturor datelor temporare folosite n tratarea ntreruperii
(unele ntreruperi las pe stive anumite informaii; dac a fost apelat o
astfel de ntrerupere, trebuie asigurat eliberarea stivei);
ntreruperea nu trebuie s fie apelat din nou n timpul tratrii ei.

23.3 Sistemul de operare MS-DOS


Sistemul de operare MS-DOS a fost realizat pentru microcalculatoare de tip
PC, bazate pe procesoarele Intel 80x86. El este un sistem de operare monouser i
monotasking. Permite rularea unui singur proces la un moment dat, proces ce are
controlul total al sistemului. Procesul activ poate utiliza orice resurs a sistemului
i poate accesa orice zon de memorie, inclusiv zona sistem. Pn la terminarea sa,
programul activ nu poate fi ntrerupt dect de ntreruperile hardware. Dup
ncheierea programului activ, sistemul de operare primete controlul, putnd
ncrca i lansa n execuie un alt program.
Sistemul de operare MS-DOS asigur urmtoarele mari categorii de
activiti:
controlul ncrcrii n memorie, al lansrii n execuie i al terminrii
activitii pentru programele utilizator;
gestiunea operaiilor de intrare/ieire;
gestiunea coleciilor de date pe supori magnetici.
Dup cum arat i numele su (Disk Operating System), MS-DOS este un
sistem de operare stocat pe disc. La pornirea sistemului, el se ncarc de pe disc, se
autoconfigureaz i rmne rezident n memoria intern pn la oprirea sau
resetarea sistemului. Pe disc, sistemul de operare MS-DOS este organizat n trei
fiiere de baz, IO.SYS, MSDOS.SYS i COMMAND.COM, i mai multe fiiere
ce conin comenzi externe ale sistemului (fiiere executabile), drivere suplimentare
sau diverse utilitare.
Componentele de baz ale sistemului de operare MS-DOS sunt
urmtoarele:
DOS-BIOS este memorat pe disc n fiierul IO.SYS (IBMBIO.COM
sau IBMIO.SYS n alte versiuni ale sistemului de operare). Conine
drivere pentru dispozitivele CON (tastatur i display), PRN
(imprimant), AUX (interfaa serial) i CLOCK (ceasul de timp real).

711

De asemena, aceast component mai conine i drivere pentru discurile


flexibile i pentru discul hard.
DOS-Kernel (nucleul DOS) este memorat pe disc n fiierul
MSDOS.SYS (IBMDOS.COM n alte versiuni). Aceast component
conine proceduri de tratare a operaiilor de intrare/ieire la nivel logic,
precum i funcii de control al alocrii memoriei, de control al
proceselor i altele. Toate acestea sunt accesibile prin intermediul
ntreruperilor DOS, n special INT 21h care permite accesul la funciile
DOS prin punerea n registrul AH a numrului funciei, la apelul
ntreruperii.
DOS-Shell (interpretorul de comenzi standard) este memorat pe
disc n fiierul COMMAND.COM. Interpretorul este cel ce afieaz
prompterul DOS la consol i accept i execut comenzi de la
tastatur. El cuprinde urmtoarele pri:
rutina de iniializare, care este ncrcat n memorie i utilizat doar n
procesul de ncrcare a sistemului de operare de pe disc;
partea rezident, care conine rutine de tratare a erorilor critice, a
situaiei de acionare a tastelor CTRL-BREAK sau CTRL-C, precum i
a ncheierii programului n execuie;
partea tranzitorie, care afieaz prompter-ul la consol, citete comanda
de la consol i o execut. Aceast parte conine comenzile DOS
interne. Cnd se execut un program utilizator, aceast parte a
interpretorului de comenzi poate fi suprascris. Partea rezident
primete controlul la ncheierea execuiei programului i verific o sum
de control pentru a determina dac partea tranzitorie a fost suprascris
sau nu. Dac a fost suprascris, atunci partea rezident rencarc partea
tranzitorie de pe disc.

23.4 Resurse ale programelor rezidente


Organizarea memoriei
Dup instalarea sistemului de operare MS-DOS, memoria este structurat n
felul urmtor:

712

Memoria
convenional
(640ko)

Tabela vectorilor de
ntrerupere
Zona de date BIOS
Nucleul sistemului de
operare
Zona System Data
Zona System Code
Partea rezident a
COMMAND.COM

0000:0000h
0040:0000h

Zona proceselor
tranzitorii

Memoria
superioar
(384ko)

Memoria video
BIOS video
BIOS periferice
ROM-BIOS

A000:0000h
C000:0000h
C800:0000h
F000:0000h
FFFF:000Fh

Figura 23.3 Organizarea primului megaoctet de memorie intern sub sistemul de


operare MS-DOS
Aceasta este structura pentru primul megaoctet al memoriei interne. El este
urmat de memoria extins. Primul megaoctet de memorie mpreun cu primul
segment (64ko) din memoria extins (numit zona de memorie nalt) pot fi accesate
direct n modul de lucru real al procesorului. Pentru a accesa restul memoriei
extinse este nevoie de un driver special.
Tabela vectorilor de ntrerupere i zona de date BIOS sunt rezervate nc
nainte de ncrcarea sistemului de operare i ncep ntotdeauna la locaii fixe. n
continuarea lor se ncarc nucleul sistemului de operare, format din coninutul
fiierelor IO.SYS i MSDOS.SYS (pentru versiunea Microsoft). Urmeaz zona
System Data care conine structurile interne ale sistemului de operare: buffere,
stive, tabela fiierelor deschise, drivere, tabelele cu blocurile de control a fiierelor
(FCB), tabela directoarelor curente.
Zona ocupat de sistemul de operare se ncheie cu zona System Code i
partea rezident a interpretorului de comenzi COMMAND.COM.
Restul memoriei convenionale reprezint memoria aflat la dispoziia
programelor utilizator. Pentru a putea rula, un program trebuie s ncap n aceast
zon de memorie, din care o parte poate s fie rezervat de ctre programele
rezidente. Dac are nevoie de mai mult memorie, un program poate folosi
memoria extins (dac este instalat driver-ul corespunztor), dar numai pentru
segmente suplimentare de date. Partea de cod trebuie s se ncadreze n zona de
memorie convenional.

713

Memoriei convenionale i urmeaz un spaiu de adrese de 384 kilooctei ce


formeaz memoria superioar (Upper Memory). n acest spaiu de adrese sunt
mapate memoria video, memoriile ROM de pe plcile de extensie (care conin
BIOS aferent perifericelor respective: placa video, discul fix sau alte echipamente),
memoria ROM de pe placa de baz (care conine ROM-BIOS, rutinele POST i
secvena ROM Bootstrap), precum i alte extensii ROM. Tot aici se mapeaz
memoria expandat i, n spaiul rmas liber, Upper Memory Blocks.
Adresele exacte la care sunt localizate diferitele zone de memorie n cadrul
memoriei superioare difer de la o generaie la alta de echipamente, dar limitele
generale sunt cele prezentate n figura de mai sus.
Blocul de control al memoriei
ncepnd cu locaia de memorie imediat urmtoare nucleului sistemului de
operare, orice zon de memorie este precedat de un bloc de 16 octei, numit
Memory Control Block, care ofer informaii privind zona de memorie ce i
urmeaz. Structura unui astfel de bloc este urmtoarea:

Offset
0
1

Lungime
1 octet
1 cuvnt

1 cuvnt

5
8

3 octei
8 octei

Tabelul 23.1.
Semnificaie
identificatorul blocului (M sau Z)
adresa de segment a PSP al
proprietarului
dimensiunea zonei de memorie
asociate (n paragrafe)
rezervat
numele proprietarului

Identificatorul blocului este ntotdeauna caracterul M, cu excepia


ultimului MCB din memoria convenional, care are caracterul Z la
deplasamentul 0. Pentru memoria superioar, blocurile MCB au de asemenea ca
identificator caracterul M, cu excepia ultimului MCB din memorie, care este
identificat prin caracterul Z.
La deplasamentul 8 se gsete numele programului proprietar, doar dac
zona de memorie rezervat este ocupat de un program. Dac zona de memorie este
rezervat pentru environment sau pentru date suplimentare, atunci aici nu se va gsi
numele programului.
Se observ c aceste blocuri de tip MCB formeaz un lan: cunoscnd
coninutul unui astfel de bloc se poate determina adresa de segment a urmtorului
bloc de tip MCB, adunnd la adresa de segment a blocului curent, dimensiunea n
paragrafe a zonei de memorie pe care o precede, plus 1:

714

adr_seg_MCBn+1=adr_seg_MCBn+dim+1
unde dim este dimensiunea n paragrafe a zonei de memorie pe care o precede
MCBn .
Adresa de segment a primului MCB din lan se afl la deplasamentul -2, n
tabela INVARS a sistemului de operare MS-DOS. Adresa acestei tabele se
determin cu ajutorul funciei DOS 52h.
Dac adresa de segment a PSP al proprietarului, care se gsete n MCB la
deplasamentul 1, este 0, atunci zona de memorie precedat de ctre acel MCB este
liber.
Dac valoarea de la deplasamentul 1 este 8, atunci avem de-a face cu o zon
sistem. n acest caz, dac la deplasamentul 8 gsim numele SD nseamn c zona
ce urmeaz acelui MCB este zona SYSTEM DATA. Dac aici gsim numele SC,
atunci este vorba de zona SYSTEM CODE.
Zona SYSTEM DATA este la rndul ei organizat pe subblocuri de
memorie, fiecare subbloc fiind precedat de ctre un MCB. Primul MCB de subbloc,
din aceast zon se afl imediat dup blocul MCB ce marcheaz ntreaga zon
SYSTEM DATA. Subblocurile acestei zone se recunosc dup identificatorul al
MCB care le precede (deplasament 0). Acest caracter poate fi:
D pentru subblocul ce aparine unui driver ncrcat printr-o
comand DEVICE din CONFIG.SYS. n acest caz, numele de la
deplasamentul 8 este chiar numele driver-ului.
F pentru subblocul OPEN FILE TABLES;
X pentru subblocul FILE CONTROL BLOCKS;
B pentru subblocul BUFFERS;
L pentru subblocul CURRENT DIRECTORIES;
S pentru subblocul STACKS.

715

Dac valoarea aflat la deplasamentul 1 al MCB ce precede o zon de


memorie este diferit i de 0 i de 8, atunci aceast valoare este adresa de segment
a PSP al programului proprietar. n acest caz, putem avea una din urmtoarele
subvariante:
adresa de segment a PSP al proprietarului este egal cu adresa de
segment a MCB curent plus 1. n acest caz, zona de memorie precedat
de MCB curent este ocupat chiar de ctre programul proprietar, iar la
deplasamentul 8 al MCB se gsete numele programului.
valoarea cuvntului de la deplasamentul 1 din MCB curent este egal cu
valoarea cuvntului gsit la deplasamentul 2Ch n PSP al programului
proprietar. n acest caz, zona de memorie precedat de MCB curent este
ocupat de blocul de environment al programului indicat ca proprietar,
prin intermediul PSP propriu.
dac valoarea de la deplasamentul 1 din MCB curent nu verific nici
una din relaiile de mai sus, atunci este vorba de un bloc de date alocat
suplimentar de ctre programul indicat ca proprietar.
23.5 Controlul proceselor
ncrcarea n memorie i lansarea n execuie a unui program se poate face
de ctre un alt program prin apelul funciei DOS 4Bh (EXEC) sau direct de la
consol prin introducerea la prompterul interpretorului de comenzi a numelui
programului. Interpretorul de comenzi caut programul specificat n directorul
curent i, dac nu l gsete acolo, n directoarele coninute n variabila PATH a
sistemului de operare. Cnd l gsete l ncarc n memorie i l lanseaz n
execuie tot prin intermediul funciei EXEC.
Programele executabile au extensiile BAT, COM sau EXE. Fiierele cu
extensia BAT sunt de fapt fiiere text ce conin comenzi DOS. Dac la prompterul
interpretorului se introduce numele programului fr extensie i n acelai director
se gsesc mai multe fiiere cu numele respectiv, dar cu extensii diferite, atunci
ordinea n care interpretorul de comenzi le ia n considerare este urmtoarea: mai
nti extensia COM, apoi cea EXE i n final extensia BAT.
Programele de tip COM sau EXE sunt precedate n memorie de o zon de
256 de octei numit PSP (Program Segment Prefix). Aceast zon de memorie are
urmtoarea structur:

716

Tabelul 23.2.
Offset
00h
02h

Lungime
1 cuvnt
1 cuvnt

04h
05h

1 octet
5 octei

0Ah
0Eh
12h
16h

2 cuvinte
2 cuvinte
2 cuvinte
1 cuvnt

18h
2Ch

20 octei
1 cuvnt

2Eh
5Ch
6Ch
80h

46 octei
36 octei
20 octei
1 octet

81h

127 octei

Semnificaie
codul unei instruciuni INT 20h
adresa de segment a vrfului
memoriei de baz ocupate
rezervat
codul unei instruciuni CALL
seg_int21h:off_int21h
adresa rutinei de tratare INT 22h
adresa rutinei de tratare INT 23h
adresa rutinei de tratare INT 24h
adresa de segment a PSP al
procesului printe
rezervat
adresa de segment a blocului de
environment
rezervat
primul FCB standard, nedeschis
al doilea FCB standard, nedeschis
lungimea irului cu parametrii
programului
parametrii programului din linia de
comand

Instruciunea INT 20h de la deplasamentul 0 reprezint o modalitate


perimat de a ncheia execuia programului (prin salt la aceast adres).
La deplasamentul 5 se gsete o instruciune de apel FAR a rutinei de
tratare a ntreruperii 21h, care este dispecerul funciilor DOS.
ncepnd cu deplasamentul 0Ah se gsesc adresele de revenire la terminarea
programului (identic cu vectorul ntreruperii 22h), a rutinei de tratare a acionrii
combinaiei de taste CTRL-BREAK sau CTRL-C (vectorul ntreruperii 23h),
respectiv a rutinei de tratare a erorilor critice (vectorul ntreruperii 24h). Aceste
adrese sunt cele valabile pe parcursul execuiei programului proprietar al PSP. Ele
se folosesc pentru restaurarea vectorilor de ntrerupere 22h, 23h, respectiv 24h,
atunci cnd se revine dintr-un proces fiu.
Adresa procesului printe, de la deplasamentul 16h este pentru
COMMAND.COM, 0 sau adresa propriului PSP.
Blocul de environment al programului, a crui adres de segment este
precizat la deplasamentul 2Ch, conine setri de variabile sistem cu valabilitate
local (modificarea lor nu influeneaz procesul printe). Aceste setri apar sub
forma unei succesiuni de iruri ASCIIZ (ir ASCII terminat printr-un octet de
valoare 0), de forma variabila=valoare. Aceast succesiune se termin printr-un
octet 0 suplimentar (deci la sfrit vom avea doi octei cu valoarea 0). Dup aceasta
urmeaz un cuvnt cu valoarea 1, urmat de numele programului proprietar

717

specificat cu ntreaga cale i cu extensie. Specificatorul programului se ncheie


printr-un octet de valoare 0.
Cele dou structuri FCB implicite, de la deplasamentele 5Ch i 6Ch se
suprapun parial, deci nu se va putea lucra cu ambele n acelai timp. Oricum FCB
reprezint o modalitate perimat de a lucra cu fiiere. n locul lor se folosesc
identificatori de fiiere.
La deplasamentul 81h se gsete linia de comand ce a apelat programul
proprietar, mai puin numele fiierului executabil ce conine programul i
redirectrile (aici pot fi gsii parametrii programului). Lungimea irului astfel
rmas este specificat la deplasamentul 80h. Peste aceast zon, ncepnd de la
deplasamentul 80h, pe o lungime de 128 octei se ntinde zona DTA implicit.
Aceast zon este folosit de ctre anumite funcii DOS ce lucreaz cu discul (cele
ce folosesc FCB i funciile FIND FIRST i FIND NEXT). Pentru a nu pierde
informaiile din linia de comand, nainte de a realiza operaii cu discul, trebuie fie
salvat linia de comand ntr-o alt zon de memorie, fie schimbat adresa zonei
DTA (folosind funcia DOS 1Ah).
Aspecte specifice ale formatului COM
Programele de tip COM sunt cele cu model de memorie tiny. Acestea
folosesc un singur segment, unde se gsesc datele, codul i stiva. n cadrul unui
astfel de program se fac doar apeluri de tip NEAR, deci adresa de segment a
programului nu apare n mod explicit n nici o instruciune din program (codul
programului rmne neschimbat indiferent de adresa de segment la care este
ncrcat n memorie).
La scrierea programului trebuie marcat n mod explicit spaiul pentru PSP,
care este i el inclus n acelai segment cu restul programului, printr-o directiv
ORG 100h. Aceasta are rolul de a asigura calculul corect al deplasamentelor n
cadrul segmentului (toate deplasamentele se mresc cu 100h din cauza PSP, care
ocup primii 256 de octei din segment).
n fiierul cu extensia COM nu se rezerv spaiu pentru PSP. PSP este creat
i iniializat de ctre sistemul de operare, care ncarc n continuarea sa ntreg
coninutul fiierului COM, fr nici o modificare. Apoi iniializeaz regitrii de
segment DS, ES i SS cu adresa segmentului programului; SP este iniializat cu
valoarea FFFEh, deplasament la care este pus un cuvnt cu valoarea 0. Acest lucru
este fcut n ideea de a putea ncheia execuia programului printr-o instruciune
RET, care ar extrage de pe stiv valoarea 0 i s-ar executa n felul acesta un salt la
deplasamentul 0 din cadrul segmentului programului, care este de fapt
deplasamentul 0 al PSP i care conine ntotdeauna codul unei instruciuni INT
20h. Aceasta este o modalitate nvechit de a ncheia execuia programului.
n finalul procesului de ncrcare a programului n memorie se iniializeaz
regitrii CS i IP cu adresa de segment a programului, respectiv valoarea 100h,

718

pentru a executa un salt la locaia de memorie imediat urmtoare PSP. Acesta este
ntotdeauna punctul de intrare ntr-un program de tip COM.
Aspecte specifice ale formatului EXE
Programele executabile n format EXE folosesc orice model de memorie,
deci nu exist restricii privind numrul de segmente. De asemenea, codul, datele i
stiva se pot gsi n segmente separate, chiar mai multe pentru fiecare n parte, sau
se pot combina ntre ele. ntr-un astfel de program coexist att apeluri de tip
NEAR, ct i apeluri de tip FAR. Aceasta face ca programele de tip EXE s fie
dependente de locul unde se ncarc n memorie, adic vor exista n program
simboluri a cror valoare depinde de adresa de segment ncepnd de la care se
ncarc programul. De aceea este nevoie ca la ncrcarea acestor programe n
memorie s se fac o operaie de relocare, adic de recalculare a acelor valori
dependente de adresa de segment ncepnd de la care se face ncrcarea
programului n memorie.
Punctul de intrare n program nu mai este fix, el putndu-se gsi oriunde
dorete programatorul, care precizeaz acest punct n cadrul directivei END.
Dei programul se ncarc tot imediat dup PSP propriu, acesta nu mai este
inclus n nici unul din segmentele programului i de aceea, la scrierea programului
nu mai este nevoie s se precizeze locul pe care l va ocupa PSP.
Fiierul ce conine un program n format EXE conine pe lng imaginea
programului n memorie, mai puin PSP i un header ce conine o serie de
informaii necesare la ncrcarea i lansarea n execuie a programului. Acest
header are urmtoarea structur:

719

Tabelul 23.3.
Offset
00h
02h

Lungime
2 octei
1 cuvnt

04h

1 cuvnt

06h

1 cuvnt

08h

1 cuvnt

0Ah

1 cuvnt

0Ch

1 cuvnt

0Eh

1 cuvnt

10h

1 cuvnt

12h
14h
16h

1 cuvnt
1 cuvnt
1 cuvnt

18h
1Ah

1 cuvnt
1 cuvnt

TablOff

2*ReloCnt
cuvinte
? octei

Semnificaie
MZ (semntura fiierelor .EXE)
PartPag = lungime fiier modulo
512
PageCnt = lungime fiier n pagini
de 512 octei
ReloCnt = numr de elemente din
tabela de relocare
HdrSize = dimensiune header n
paragrafe de 16 octei
MinMem = necesar minim de
memorie dup sfritul programului
(n paragrafe)
MaxMem = necesar maxim de
memorie dup sfritul programului
(n paragrafe)
ReloSS = deplasament segment
stiv
ExeSP = offset vrf stiv la
lansarea n execuie
ChkSum = sum de control
ExeIP = offset adres de start
ReloCS = deplasament segment de
cod
TablOff = offset tabel de relocare
indicator de overlay (0 pentru
modulele de baz)
tabela de relocare
caractere pn la limita de paragraf

Necesarul minim de memorie dup sfritul programului este determinat de


regul de stiv, care nu este inclus n fiier. Necesarul maxim de memorie dup
sfritul programului este implicit FFFFh. De aceea, de regul, programele aflate n
execuie ocup toat memoria disponibil.
Deplasamentele segmentelor de stiv i de cod sunt fa de factorul de
relocare (adresa de segment la care se ncarc programul).
Valorile regitrilor SP i IP la lansarea n execuie a programului (ExeSP i
ExeIP) sunt valorile precizate n directivele STACK, respectiv END, din sursa
programului.
Tabela de relocare conine cte un dublu cuvnt pentru fiecare element al
tabelei. Un astfel de dublu cuvnt este format din deplasamentul i deplasamentul
segmentului fa de factorul de relocare corespunztoare elementului din program
cruia trebuie s i se aplice operaia de relocare.

720

ncrcarea i lansarea n execuie a unui program n format EXE presupune


urmtoarele operaii:
se citesc 1Ch octei din fiierul .EXE (poriunea formatat a headerului), ntr-o zon local de memorie.
se determin lungimea modulului inclus n fiierul .EXE:
lg_modul = (PageCnt - 1) 512 + PartPag HdrSize 16
n cazul n care coninutul variabilei PartPag este diferit de 0 sau
lg_modul = PageCnt 512 HdrSize 16,
n cazul n care PartPag = 0.
se aloc memorie conform cu lungimea astfel determinat i cu valorile
MinMem i MaxMem. Dac nu se pot aloca minimum 256 +
lung_modul + MinMem*16 octei, atunci ncrcarea i lansarea n
execuie a programului nu este posibil.
se creeaz PSP.
se determin deplasamentul n fiier al modulului: HdrSize*16 .
se citete modulul de program n memorie, la adresa START_SEG:0000,
unde START_SEG este uzual adresa de segment a PSP plus 10h.
se seteaz poziia de citire din fiier la nceputul tabelei de relocare
(TablOff).
pentru fiecare element al tabelei de relocare (ReloCnt) se execut
urmtoarele operaii:
se citete elementul tabelei din fiier (dou cuvinte: I_OFF i I_SEG).
se determin adresa actual a elementului ce trebuie realocat:
RELO_SEG = (START_SEG + I_SEG).
se adun START_SEG la cuvntul de la adresa RELO_SEG:I_OFF.
se iniializeaz regitrii semnificativi i se d controlul programului:
o ES = DS = adresa de segment a PSP;
o SS = START_SEG + ReloSS;
o SP = ExeSP;
o CS = START_SEG + ReloCS;
o IP = ExeIP.
23.6 Probleme specifice n realizarea programelor rezidente
Structura unui program rezident
Pentru ca un program activ n memoria intern a calculatorului s rmn
rezident este nevoie ca acesta s apeleze funcia TSR a sistemului fie prin INT 27h,

721

fie prin funcia DOS 31h. Aceast funcie menine rezervat prima parte a zonei de
memorie ocupat de program, parte a crei dimensiune este transmis rutinei de
tratare a ntreruperii apelate. Zona de memorie imediat urmtoare prii marcate ca
rezident este eliberat i apoi controlul este redat sistemului de operare sau
programului ce a lansat n execuie programul rezident, dac exist un astfel de
program.
Orice program rezident este constituit din dou mari pri: o parte rezident
i o parte nerezident. Partea nerezident trebuie s fie plasat n program dup
partea rezident, deoarece funcia TSR pstreaz n memorie partea de nceput a
programului i elibereaz memoria ocupat de partea final a programului.
0
P.S.P.
100h

jmp etichet_nerezident
Date modul rezident
Rutine de tratare a
ntreruperilor
int_x1:

int_x2:

............
etichet_nerezident:

Bloc decizie
instalare/dezinstalare/alte
operaii
Date modul nerezident
Modul de instalare
apel funcie TSR
Modul de dezinstalare

Alte module (configurare)


apel funcie EXIT

Figura 23.4 Schema general a imaginii n memorie a unui program


rezident, nainte de apelul funciei TSR

722

Partea nerezident a programului


Partea nerezident conine modulul de instalare a programului rezident i,
eventual, cel de dezinstalare, module care nu se justific s fie pstrate rezidente n
memorie, deoarece ele se execut o singur dat n procesul de utilizare a unui
program rezident. Aceasta nseamn c dup ncrcarea i predarea controlului
programului, partea nerezident este cea care trebuie s se execute. Ca atare la
punctul de intrare n program, care se gsete la deplasamentul 100h, imediat dup
PSP, va trebui s existe o instruciune de salt necondiionat la adresa de nceput a
prii nerezidente.
La nceputul prii nerezidente va trebui s existe un modul care s decid
aciunea ce se va executa n continuare. De regul, acest modul ncepe prin a
verifica dac n memoria RAM se gsete deja o instan a programului rezident,
dup care decide ce aciune s ntreprind, n funcie de rezultatul acestei verificri:
dac n memorie nu se mai gsete o alt instan a programului
rezident, se va trece la instalarea programului rezident;
dac n memorie se gsete deja o instan a programului rezident,
atunci n continuarea se poate face o dezinstalare a programului rezident
aflat n memoria RAM (de fiecare dat cnd se ntlnete aceast
situaie sau doar cnd utilizatorul specific n mod explicit c dorete
acest lucru).
Alegerea ntre execuia instalrii sau a dezinstalrii se poate face i altfel: de
exemplu, prin specificarea unor parametri n linia de comand, atunci cnd este
lansat n execuie programul sau prin alegerea unei opiuni dintr-un meniu.
Partea rezident a programului
Partea rezident a programului conine PSP al programului, urmat de o
instruciune de salt la nceputul prii nerezidente i apoi de datele i codul
modulului rezident.
n zona de date se poate gsi i o stiv a modulului rezident. Aceasta nu este
obligatoriu s existe. Dac exist, ea trebuie foarte atent dimensionat deoarece n
cazul programelor rezidente risipa de spaiu nu este permis, dar n acelai timp
stiva trebuie s fie suficient de mare pentru a nu se produce n nici un caz depire
de stiv. O astfel de depire de stiv ar duce cu o foarte mare probabilitate la
blocarea sistemului.
Partea de cod este format din rutinele de tratare a ntreruperilor deturnate
de ctre programul rezident. n raport cu rutinele existente n sistem la momentul
deturnrii, rutinele programului rezident pot veni n completarea acestora sau
urmeaz a fi executate alternativ cu vechile rutine, n funcie de satisfacerea sau
nesatisfacerea anumitor condiii la momentul apariiei ntreruperii, sau pot s

723

nlocuiasc complet vechile rutine. n fapt, indiferent de varianta aleas, noua


rutin o nlocuiete pe cea veche, dar dac se dorete i executarea vechii rutine,
atunci rutina nou instalat trebuie s apeleze rutina nlocuit prin simularea unui
apel INT:
pushf
cli
call dword ptr CS:vechea_rutina

Toate rutinele coninute de ctre partea rezident a programului trebuie s


respecte urmtoarele condiii:
pstrarea nealterat a contextului;
respectarea modului de transmitere a parametrilor existent n rutina
original (dac este cazul);
evitarea generrii de noi ntreruperi;
evitarea activrilor multiple;
minimizarea timpului de execuie.
n ceea ce privete revenirea la programul ntrerupt, aceasta se poate face n
dou moduri:
cu o instruciune IRET, care este varianta normal de ntoarcere i care
presupune restaurarea automat a tuturor indicatorilor de condiie la
starea n care se aflau imediat nainte de ntrerupere;
cu o instruciune RETF 2, variant n care indicatorii de condiie nu mai
sunt restaurai. Aceast variant este folosit de anumite ntreruperi
software care comunic programului apelant anumite informaii privind
modul de ncheiere a tratrii ntreruperii, prin intermediul indicatorilor
de condiie. La deturnarea unei ntreruperi, programatorul trebuie s
respecte convenia de comunicare ntre rutina original i programele
apelante i s foloseasc metoda adecvat de revenire n programul
apelant.
Comutarea contextului
Comutarea contextului este obligatorie pentru orice rutin de tratare a unei
ntreruperi, deoarece aceasta trebuie s pstreze contextul nealterat. De aceea,
nainte de a ncepe tratarea propriu-zis a ntreruperii, orice rutin trebuie s se
ngrijeasc de salvarea contextului programului ntrerupt i de comutarea ctre
contextul rutinei, iar dup ncheierea tratrii ntreruperii trebuie s comute napoi
pe contextul salvat al programului.
Urmtoarele elemente trebuie s fie avute n vedere atunci cnd se face
comutarea contextului:
regitrii procesorului;

724

comutarea pe stiva proprie a modulului rezident acest lucru este


necesar dac modulul rezident a fost prevzut cu o stiv proprie i se
realizeaz prin iniializarea corespunztoare a regitrilor SS i SP, care
anterior trebuie s fie salvai ntr-o zon de memorie special rezervat n
modulul rezident. La ncheierea tratrii ntreruperii este necesar
comutarea napoi pe stiva programului ntrerupt.
salvarea stivei programului ntrerupt salvarea se va face ntr-o zon
rezervat special n modulul rezident. Salvarea stivei curente n
momentul ntreruperii este justificat doar pentru acele rutine care
apeleaz alte ntreruperi sau care nu se asigur de dezactivarea
ntreruperilor pe tot parcursul rutinei. Se recomand salvarea a 64 de
cuvinte din stiva programului ntrerupt.
PSP i DTA este necesar s fie salvate adresele acestor structuri ale
programului ntrerupt atunci cnd se fac operaii cu discul folosind
funcii DOS. Dup salvarea acestor adrese, trebuie s fie marcate ca
active PSP i DTA ale modulului rezident. La ncheierea tratrii
ntreruperii trebuie setate PSP i DTA active, la valorile salvate.
coninutul memoriei video, modul video, poziia i tipul cursorului,
poziia pointerului mouse-ului (dac exist driver de mouse).

Instalarea programelor rezidente


Instalarea programelor rezidente presupune iniializarea corespunztoare a
datelor necesare modulului rezident i realizarea legturilor necesare acestuia i se
ncheie prin apelul funciei TSR. De regul nu este necesar prezena simultan n
memorie a mai multor instane ale aceluiai program rezident. De aceea, nainte de
a se trece la instalarea programului este necesar verificarea existenei unei instalri
anterioare. Dup ce a fost verificat existena unei instalri precedente i s-a
confirmat lipsa ei, deci posibilitatea realizrii unei instalri, se trece la realizarea
urmtoarelor operaii necesare pentru instalarea programului rezident:
iniializri ale parametrilor programului, salvarea n zona de date a
modulului rezident a datelor necesare i alte operaii de iniializare, n
funcie de particularitile programului rezident;
salvarea adreselor rutinelor de tratare a ntreruperilor ce vor fi deturnate;
deturnarea ntreruperilor;
eliberarea, dac este cazul, a blocurilor de date alocate suplimentar de
ctre modulul de iniializare i nenecesare modulului rezident;
eliberarea blocului de environment (opional);
determinarea zonei de memorie ce va fi rezervat pentru modulul
rezident i pregtirea regitrilor pentru apelul funciei TSR;

725

Modulul de instalare se ncheie prin apelul funciei Terminate and Stay


Resident care rezerv memoria pentru modulul rezident i apoi red controlul
sistemului de operare sau programului apelant dac este cazul.
Verificarea unei instalri precedente
Aceast metod se bazeaz pe faptul c programul rezident instalat
deturneaz anumite ntreruperi, astfel nct noii vectori ai ntreruperilor respective
indic rutine care sunt incluse n modulul rezident. De aceea, dac programul
rezident a fost instalat, atunci adresele rutinelor de tratare a ntreruperilor pe care le
folosete programul rezident vor indica locaii de memorie din interiorul
segmentului ocupat de acesta.
Pentru a stabili dac n segmentul indicat de vectorul unei anumite
ntreruperi se afl programul nostru rezident este suficient s verificm coninutul
unei anumite zone de memorie aflat la un deplasament bine precizat n interiorul
segmentului n cauz i s vedem dac gsim acolo semntura programului
rezident. Aceast semntur const ntr-un ir de valori prestabilite, pe care
programul rezident le va conine ntotdeauna la acel deplasament.
n consecin, determinarea existenei unei instalri precedente a
programului rezident presupune urmtoarele operaii:
n zona de date a modulului rezident, programatorul va rezerva un
numr de octei ce vor conine un ir de valori prestabilite.
n partea nerezident, blocul de verificare a unei instalri precedente va
conine urmtoarele operaii: determinarea adresei de segment a uneia
din ntreruperile cunoscute ca fiind deturnate de ctre programul
rezident; adugarea la adresa de segment astfel obinut a
deplasamentului semnturii; extragerea de la adresa fizic astfel
obinut a irului de valori i apoi compararea sa cu semntura
programului rezident. Dac sunt identice, atunci programul a fost deja
instalat, altfel programul nu este instalat.
Verificarea n lanul de blocuri MCB
O alt metod de testare a existenei unei instalri precedente a programului
rezident este aceea de a verifica toate blocurile de memorie MCB (Memory Control
Blocks) i a vedea dac vreunul dintre ele este rezervat pentru programul nostru
rezident.
Orice bloc de memorie ce urmeaz nucleului sistemului de operare este
precedat de un bloc MCB de 16 octei, care conine la deplasamentul 8 un ir de 8
caractere ce reprezint numele proprietarului zonei respective de memorie, dac
zona este rezervat (vezi 2.1.2.). Deci aici se gsete numele programului ce ocup

726

respectiva zon de memorie. Adresa de segment a primului MCB este gsit


folosind funcia DOS 52h.
Adresa de segment a primului MCB se gsete la deplasamentul negativ -2
n tabela INVARS. Dup apelul funciei DOS 52h, adresa de segment a primului
MCB este dat de cuvntul indicat prin pointerul ES:BX-2.
Adresa de segment a urmtorului MCB se determin adunnd la adresa de
segment a MCB curent valoarea dim (dimensiunea n paragrafe a zonei de memorie
referite) a cuvntului de la deplasamentul 3 din cadrul MCB curent i valoarea 1,
care reprezint dimensiunea n paragrafe a unui MCB (vezi 2.1.2., formula (2)).
Ultimul MCB din lan are caracterul Z la deplasamentul 0.
Folosirea ntreruperii multiplex
Aceast metod se bazeaz pe ntreruperea 2Fh, numit ntrerupere
multiplex, care este pus la dispoziie de ctre sistemul de operare MS-DOS.
Aceast ntrerupere s-a intenionat a fi o modalitate de comunicare ntre procese.
Fiecare modul (proces) rezident trebuie s aib un identificator multiplex, care
pentru procesele utilizator poate fi orice numr ntre C0h i FFh. Numerele
cuprinse ntre 00h i BFh sunt rezervate sistemului de operare DOS. Toate
modulele rezidente trebuie s intercepteze aceast ntrerupere. n rutina de tratare
trebui s verifice identificatorul multiplex din registrul AH i dac acesta este
identificatorul propriu, atunci execut funcia solicitat prin registrul AL, pe care ar
ncheia-o printr-o instruciune IRET. Dac n AX nu este gsit identificatorul
propriu, atunci trebuie s predea controlul urmtorului handler din lan apelnd
rutina a crei adres era pus n tabela vectorilor de ntrerupere nainte ca
programul s fi deturnat ntreruperea.
Orice program rezident ce intercepteaz aceast ntrerupere trebuie s
implementeze mcar funcia 00h care determin dac un program rezident a fost
sau nu instalat. Aceast funcie trebuie s returneze n AL 00h dac programul nu
este instalat sau FFh dac programul este instalat.
n concluzie, este necesar ca programul rezident s primesc un numr
propriu de identificare cuprins ntre C0h i FFh i s prevad o rutin de tratare a
ntreruperii 2Fh care s realizeze urmtoarele operaii:

727

testeaz coninutul registrului AH;


dac acesta este identic cu numrul propriu de identificare multiplex,
execut urmtoarele operaii; testeaz coninutul registrului AL; dac
acesta este 00h, pune n AL valoarea FFh; dac este alt numr dect
00h, apeleaz procedura de tratare a funciei respective, dac exist;
dac AH nu conine numrul propriu de identificare multiplex, apeleaz
vechea rutin de tratare a ntreruperii prin simularea unei instruciuni
INT.
Blocul din modulul nerezident, care testeaz dac programul rezident a fost
sau nu instalat trebuie doar s apeleze ntreruperea 2Fh (dup ce a fost pus n AH
identificatorul multiplex al programului, iar n AL valoarea 00h) i s testeze
rezultatul:
dac AL are valoarea 00h, programul nu a fost instalat;
dac AL are valoarea FFh, programul a fost instalat.
Dezinstalarea programelor rezidente
Dezinstalarea programelor rezidente nu este obligatorie, dac realizatorul
programului consider c este justificat prezena programului rezident n memoria
calculatorului pn la sfritul sesiunii curente de lucru.
Dac este prezent, modulul de dezinstalare trebuie mai nti s verifice dac
este posibil s se recurg la dezinstalare fr a afecta buna funcionare a sistemului.
Aceast verificare este necesar deoarece este posibil ca dup instalarea
programului nostru s mai fi fost instalate i alte programe rezidente ce au deturnat
aceleai ntreruperi. n acest caz, tentativa de refacere a vechilor legturi va duce la
tierea legturilor programelor rezidente instalate ulterior programului nostru.
Verificarea posibilitii de dezinstalare se va face comparnd toi vectorii de
ntrerupere ce au fost interceptai de programul nostru, cu adresele rutinelor din
modulul rezident.
Dac n urma acestei verificri a rezultat c este posibil dezinstalarea,
modulul de dezinstalare va reface vechii vectori de ntrerupere pe baza adreselor
salvate la instalare, dup care va elibera blocurile de memorie alocate pentru
eventuale date suplimentare ale modulului rezident, pentru environment i pentru
modulul rezident al programului.
23.7 Activarea programelor rezidente
Activarea programelor rezidente presupune preluarea controlului de ctre
programul rezident i realizarea de ctre acesta a funciei proprii, atunci cnd sunt
ndeplinite anumite condiii.

728

Un program rezident, pentru a-i putea ndeplini funcia, intercepteaz una


sau mai multe ntreruperi. n felul acesta, la orice solicitare a uneia dintre
ntreruperile respective, de ctre sistem sau de ctre un program utilizator,
programul rezident primete controlul. Apoi el decide n funcie de ndeplinirea sau
nendeplinirea anumitor condiii, dac s activeze rutina proprie sau s apeleze doar
vechea rutin de tratare a ntreruperii respective sau s fac alte operaii. Aceste
condiii se refer la a testa dac este necesar activarea programului rezident, dar
trebuie s se refere i la a testa dac este posibil activarea programului rezident
fr a afecta buna funcionare a sistemului. Cu alte cuvinte, exist anumite restricii
cu privire la momentul n care un program rezident se poate activa.
Restricii care trebuie s fie avute n vedere nainte de activarea
programului rezident
Interdicia ntreruperii unei funcii DOS se datoreaz faptului c funciile
DOS nu sunt reentrante. Cu alte cuvinte, dac execuia unei funcii DOS este
ntrerupt, i apoi este apelat din nou aceeai funcie sau alt funcie DOS, atunci
datele primei funcii pot fi suprascrise de noua funcie apelat. Funciile DOS nu
prevd posibilitatea unor apeluri multiple i folosesc aceleai zone de date.
Pentru acest motiv, o rutin ce apeleaz funcii DOS nu are voie s fie
activat n cursul execuiei unei funcii DOS. Interdicia poate fi extins asupra
tuturor rutinelor ce apeleaz alte ntreruperi sau care nu menin ntreruperile
dezactivate pe tot parcursul execuiei indiferent dac e vorba de apelarea unor
funcii DOS sau nu. Aceast precauie trebuie luat deoarece este posibil ca
ntreruperile apelate n timpul execuiei rutinei s apeleze ele funcii DOS sau este
posibil ca aceste ntreruperi s fie interceptate de alte programe rezidente ce
folosesc funcii DOS.
Pentru a evita activarea programului rezident cnd a fost ntrerupt o funcie
DOS, se va testa la intrarea n rutina de tratare a ntreruperii un indicator intern al
sistemului de operare DOS, indicator numit INDOS, care este diferit de 0 atunci
cnd este n curs de execuie o funcie DOS. Adresa acestui indicator se poate
obine cu ajutorul funciei DOS 34h.
Aceast funcie se va apela la instalarea programului rezident i se va
memora adresa indicatorului INDOS ntr-o locaie din zona de date a modulului
rezident. n felul acesta se va evita apelul funciei DOS pe parcursul tratrii
ntreruperii interceptate. Adresa indicatorului INDOS se stabilete la instalarea
sistemului de operare i nu se modific pe parcursul sesiunii de lucru (pn la
resetarea sistemului).
Acest indicator nu rezolv complet problema deoarece aproape ntotdeauna
el este diferit de 0. Acest lucru se ntmpl deoarece toate operaiile pe care le
execut sistemul de operare folosesc funcii DOS. De exemplu, interpretorul de
comenzi COMMAND folosete o funcie DOS pentru a citi comanda de la

729

prompter. Ceea ce nseamn c mai mereu aceast funcie este activ. Pentru a
rezolva aceast problem, sistemul de operare MS-DOS pune la dispoziie
ntreruperea INT 28h pe care sistemul o apeleaz de fiecare dat cnd se afl n
ateptare (de exemplu cnd interpretorul COMMAND ateapt introducerea unei
comenzi).
Aceast ntrerupere indic faptul c programele rezidente se pot activa n
siguran. Rutina original a ntreruperii execut un simplu IRET. Programele
rezidente pot intercepta aceast ntrerupere pentru a se activa la apelul ei. Pe
parcursul tratrii acestei ntreruperi pot fi apelate n siguran toate funciile DOS al
cror numr este mai mare dect 0Ch, cu meniunea c funciile DOS 3Fh i 40h nu
trebuie s foloseasc un handler ce refer dispozitivul CON.
Interdicia ntreruperii activitilor critice n timp
Programelor rezidente le este interzis s se activeze n timp ce se execut o
rutin critic din punct de vedere al timpului de execuie. Dac nu se respect
aceast interdicie, atunci datorit interveniei programului rezident vor apare
ntrzieri n execuia rutinei critice, deci desincronizri n lucrul cu perifericul la
care se refer rutina i ca urmare pot apare pierderi de date.
Pentru a preveni acest lucru, programul rezident va trebui s intercepteze
toate rutinele critice n timp i s execute urmtoarele operaii n noua rutin:
setare indicator de execuie rutin critic n timp;
apel rutin original;
resetare indicator de execuie rutin critic n timp.
n felul acesta, pe parcursul execuiei rutinei critice, programul rezident va
avea un indicator propriu setat corespunztor i care i va spune c nu se poate
activa. Deci, la orice tentativ de activare, programul rezident va trebui s verifice
mai nti situaia acestui indicator.
Interdicia ntreruperii tratrii erorilor critice
Programele rezidente nu trebuie s ntrerup rutina care trateaz o eroare
critic pentru a nu provoca modificarea codului de eroare i a nu afecta astfel
execuia programului ntrerupt. Pentru a ti cnd are loc tratarea unei erori critice,
programul rezident poate testa un indicator a crui adres se obine cu ajutorul
funciei DOS 5Dh, subfuncia 6.
Indicatorul de eroare critic se reprezint pe un cuvnt i este diferit de 0
dac este n curs de tratare o eroare critic.
La instalarea programului rezident se va apela funcia DOS 5Dh, subfuncia
6h i se va memora adresa coninut n DS:SI la o locaie din modulul rezident. n
felul acesta se va evita apelarea funciei DOS de ctre rutina de tratare a ntreruperii
interceptate. La apariia unei tentative de activare a programului rezident, se va

730

testa indicatorul de eroare critic i dac acesta este diferit de 0 se va renuna la


activarea programului rezident.
Evitarea activrilor multiple
Trebuie avut n vedere i posibilitatea ca n timp ce se execut programul
rezident s mai apar o cerere de activare a sa. Pentru ca i aceast cerere s fie
satisfcut fr a afecta execuia corect a programului de la prima activare ar
trebui ca programul rezident s fie reentrant. Dar cum scrierea unui cod reentrant
ridic probleme mult mai dificile, este preferat varianta mai simpl de a mpiedica
o a doua activare a programului rezident n timp ce se execut deja o instan a sa.
Acest lucru se realizeaz folosind un indicator propriu al programului
rezident care se seteaz naintea fiecrei activri a programului i se reseteaz la
ncheierea execuiei. nainte de a activa programul, se va testa acest indicator. Dac
este setat nseamn c exist deja n execuie o instan a programului, care a fost
ntrerupt. n acest caz se va renuna la activarea programului.
23.8 Program rezident pentru afiarea ceasului
Acest program rezident i propune s ofere programelor utilizator un
serviciu de afiare a unui ceas de timp real i servicii de cronometrare.
Programul rezident va pune la dispoziia programelor o ntrerupere software
de utilizator care va cuprinde urmtoarele funcii:
determinarea strii ceasului sau a cronometrului;
afiarea ceasului;
dezactivarea ceasului;
activarea cronometrului pentru o numrtoare n sens cresctor;
activarea cronometrului pentru o numrtoare invers;
oprirea cronometrului;
repornirea cronometrului;
Funcionarea ceasului sau a cronometrului se va face n paralel cu execuia
oricrui program utilizator. Programul rezident va permite funcionarea alternativ
a ceasului sau a cronometrului.
Funcia pentru determinarea strii ceasului sau cronometrului va returna
modul de funcionare a programului rezident (ceas, cronometru sau dezactivat), iar
pentru cronometru va returna i timpul indicat de acesta.
Cronometrul va fi iniializat cu un timp de start, iar pentru cronometrul
cresctor se va preciza i limita maxim de timp de funcionare. Repornirea
cronometrului dup o oprire se va face de la momentul la care fusese oprit.
Afiarea ceasului sau a cronometrului nu este obligatorie dac sistemul
video funcioneaz n mod grafic sau dac este n execuie o rutin critic, dar este
obligatoriu ca scurgerea timpului s fie msurat i n aceste condiii.

731

Precizia oferit de aceste servicii va fi la nivel de secund.


Modul de utilizare a programului
Pentru a oferi serviciile solicitate, programul rezident pune la dispoziia
programelor utilizator ntreruperea 88h, a crei rutin nou va oferi urmtoarele
servicii:
serviciul 0 determinarea strii ceasului: la apel AH=0; returneaz n
CX numrul total de secunde reprezentat de timpul indicat de
cronometru, n AL returneaz modul de lucru al programului rezident,
iar n AH returneaz modul de lucru anterior ultimei opriri a
cronometrului;
serviciul 1 oprirea ceasului sau cronometrului: la apel AH=1; nu
returneaz nimic;
serviciul 2 activarea cronometrului: la apel AH=2, AL=0 pentru
cronometru cresctor sau AL=1 pentru cronometru descresctor, CX
conine numrul total de secunde reprezentat de timpul de start al
cronometrului, iar pentru AL=0 DX conine numrul total de secunde
reprezentat de timpul final de funcionare a cronometrului; nu
returneaz nimic;
serviciul 3 activarea afirii ceasului de timp real: la apel AH=3; nu
returneaz nimic;
serviciul 4 repornirea cronometrului din punctul n care a fost oprit: la
apel AH=4; returneaz AL=0 dac cronometrul a fost pornit sau AL=1
dac cronometrul nu poate fi repornit.
Modul de lucru al programului rezident poate avea una din urmtoarele
valori:
0 dezactivat prin serviciul 1;
1 dezactivat automat la expirarea timpului de funcionare a cronometrului;
2 cronometru cresctor activ;
3 cronometru descresctor activ;
4 afiarea ceasului de timp real activat.
Timpul maxim de funcionare pentru cronometru este de 65535 de secunde
(18 ore, 12 minute i 15 secunde).
Solicitarea afirii ceasului de timp real n timpul funcionrii unui
cronometru duce la oprirea cronometrului. Acesta poate fi repornit ulterior.
Repornirea cronometrului este posibil doar dac exist un cronometru oprit
din funcionare nainte de expirarea timpului su de funcionare, prin serviciul 1
sau prin activarea afiajului ceasului de timp real. Activarea unui cronometru n
timpul funcionrii altui cronometru duce la distrugerea cronometrului care era n
funciune (care nu mai poate fi repornit). Pentru a obine detalii privind cauza ce

732

face imposibil folosirea serviciului 4 (cnd returneaz AL=1) se poate apela


servicul 0, care indic att modul de lucru curent, ct i modul de lucru salvat la
ultima oprire a unui cronometru.
Pentru a beneficia de aceste servicii, programul trebuie s fie instalat n
memorie. Acest lucru se face lansnd n execuie programul executabil
CEAS.COM.
Pentru dezinstalarea programului se lanseaz nc odat n execuie
programul CEAS.COM care va solicita confirmarea inteniei de dezinstalare:
Programul este deja instalat!
Doriti dezinstalarea lui? (d/n)

Dac se apas d sau D, atunci se ncearc dezinstalarea programului


rezident, dup care se afieaz rezultatul tentativei de dezinstalare: programul a fost
dezinstalat sau acest lucru nu este posibil.
Modul de realizare a programului
Modulul rezident al programului conine datele acestuia (indicatorii
modului de lucru, indicatori pentru timpul scurs, indicatori de activare, adresele
rutinelor deturnate, regitrii SS i SP salvai), o stiv proprie de 32 de cuvinte i
rutinele de tratare a ntreruperilor 8h, 10h, 13h i 88h:
org 100h
;specificare zona ocupata de PSP
intrare:
jmp nerezident
mod_lucru db 0 ;mod de functionare
mod_oprit db 0 ;mod de lucru inaintea dezactivarii
semnatura db "CEAS/CRONOMETRU"
lung_sem equ $-semnatura
fract_secunda db 0
;fractiuni de secunda
corector db 0 ;corecteaza fractiunile pierdute
crono_crt dw ? ;timp indicat de cronometru (s)
crono_max dw ? ;timp functionare cronometru (s)
inbios db 0
;indicator de rutina critica activa
activ db 0
;indicator de TSR curent activ
int8_veche label dword ;adresa rutina tratare INT 8
int8_veche_ofs dw ?
int8_veche_seg dw ?
int10h_veche label dword
;adresa rutina tratare INT 10h
int10h_veche_ofs dw ?
int10h_veche_seg dw ?
int13h_veche label dword
;adresa rutina tratare INT 13h
int13h_veche_ofs dw ?
int13h_veche_seg dw ?
ceas db ?,112,?,112,':',112,?,112,?,112,':',112,?,112,?,112

733
sp_int dw ?
;SP al programului intrerupt
ss_int dw ?
;SS al programului intrerupt
sp_int2 dw ?
;SP al TSR-ului
stiva dw 64 dup(?)
;stiva TSR-ului
varf_stiva label word
int_8:
;codul
int_10h:
;codul
int_13h:
;codul
int_88h:
;codul

rutinei de tratare int 8


rutinei de tratare int 10h
rutinei de tratare int 13h
rutinei de tratare int 88h

nerezident:
;modulul nerezident

irul de octei ceas conine caracterele care reprezint timpul ce trebuie


afiat. irul cuprinde pentru fiecare caracter doi octei: primul conine codul ASCII
al caracterului i cellalt conine atributul de culoare al caracterului, care a fost
iniializat n acest caz cu valoarea 7*16 + 0 = 112, care nseamn fond gri (7) i
caractere negre (0). Acest format este cerut de serviciul video INT 10h, funcia 13,
subfuncia 2, care este folosit n acest program pentru afiarea timpului:
afis_sir:
mov
mov
mov
mov
mov
mov
mov
int
mov

;afisez timpul curent obtinut


cs:sp_int2,sp
;salvez SP curent
ax,cs
es,ax
bp,offset ceas
;ES:BP=pointer la sirul de afisat
cx,8
;sirul are 8 caractere
dx,0000h
;randul 0, coloana 0
ax,1302h
;sir cu atribute, nu modific cursor
10h
;afisez
sp,cs:sp_int2
;restaurez SP

Salvarea i restaurarea registrului SP nainte, respectiv dup apelul


serviciului video este necesar deoarece acesta distruge coninutul registrului SP.
ntreruperile 10h i 13h au fost interceptate pentru a putea seta
corespunztor indicatorul inbios al programului rezident, pe parcursul execuiei
rutinelor de tratare a acestor ntreruperi, rutine care sunt critice din punctul de
vedere al timpului de execuie:
int10h:
;rutina de tratare a INT 10h
mov cs:inbios,1
pushf
call cs:int10h_veche
mov cs:inbios,0
iret

734
int13h:
;rutina de tratare a INT 13h
mov cs:inbios,1
pushf
call cs:int13h_veche
mov cs:inbios,0
retf 2

Rutina de tratare a ntreruperii 88h nu a fost prevzut cu nici una din


restriciile de activare specifice programelor rezidente, deoarece nu ea este rutina
de baz a programului rezident. ntreruperea 88h nu este nici ntrerupere hardware,
nici ntrerupere software de sistem. De aceea ea nu este apelat dect de
programele utilizator i este practic ca o procedur a programului ce o folosete.
Rutina de tratare a ntreruperii 88h nu poate ntrerupe nici o alt rutin i de aceea
nu sunt necesare precauii suplimentare. n plus ea nu execut dect operaii
secundare, de setare a parametrilor ceasului, conform cu solicitrile programelor
utilizator, realizate prin intermediul celor 5 servicii puse la dispoziie.
n schimb, s-a avut grij ca la intrarea n rutina de tratare a ntreruperii 88h
s fie reactivate ntreruperile, pentru ca s nu fie mpiedicat buna funcionare a
sistemului pe parcursul execuiei acestei rutine.
Rutina principal a programului rezident este rutina de tratare a ntreruperii
hardware 8h, generat de ceasul sistem de 18,2 ori pe secund. Aceast rutin
ncepe cu un apel necondiionat al rutinei originale, dup care sunt actualizai
indicatorii de scurgere a fraciunilor de secund dac programul este activat (fie
ceasul, fie cronometrul):
;rutina de tratare a INT 8
int8:
pushf
call cs:int8_veche
;apel rutina veche (simulare INT)
push ax
cmp cs:mod_lucru,2
jb sf_int8
;mod=0 sau 1 ->program inactiv
inc cs:fract_secunda
;mod=2, 3 sau 4 ->program activ
cmp cs:fract_secunda,18 ;s-au facut 18 timer ticks ?
jnz sf_int8
;... NU->salt sfirsit
inc cs:corector
;... DA->sec. noua in corector
cmp cs:corector,5 ;s-au adunat 5 sec. in corector ?
jnz sec_noua
;... NU->tratez cazul de sec. noua
mov cs:corector,0FFh
;... DA->aplic corectie
dec cs:fract_secunda
jmp sf_int8
sec_noua:
mov cs:fract_secunda,0 ;resetez fractiunile de secunda

Indicatorul fract_secunda marcheaz fiecare timer tick scurs. Cnd se fac


18 de timer ticks avem o nou secund, la care indicatorul fract_secunda este
resetat. Dar un timer tick este generat de 18,2 ori pe secun i nu de 18 ori. De

735

aceea trebuie aplicat o corecie de 1 timer tick la fiecare 5 secunde. Pentru


aceasta se folosete indicatorul corector care este incrementat de fiecare dat cnd
indicatorul fract_secunda ajunge la 18. Cnd indicatorul corector ajunge la 5
(secunde), atunci din fract_secunda se scade un timer tick (corecia) i se amn
tratarea noii secunde pn la urmtorul timer tick. n acest caz, indicatorul
corector este pus pe valoarea 0FFh pentru c la urmtorul timer tick
fract_secunda devine iar 18 i corector este iar incrementat. n felul acesta este
adus la valoarea corect 0 (resetare).
Dac nu s-a produs trecerea la o secund nou, atunci rutina se ncheie aici.
Dac s-a produs trecerea la o secund nou, atunci trebuie tratat acest caz. Aceasta
nseamn c trebuie actualizat cronometrul, dac e activ, i afiat timpul n varianta
solicitat de modul curent de lucru.
Dac este activ cronometrul, atunci n continuare trebuie incrementat sau
decrementat locaia cronometrului, n funcie de tipul su i apoi testat dac a
expirat timpul de funcionare a cronometrului:
cmp mod_lucru,4
;testez modul de lucru
jz afis
;mod=4 ->nu e cronometru
cmp mod_lucru,3
jz crono_j
;mod=3 ->cronometru desc.
inc cs:crono_crt ;mod=2 ->cronometru cresc.
mov ax,cs:crono_max
cmp ax,cs:crono_crt
;verific final
jnz afis
;... NU->afisez cronometru crt.
mov cs:mod_lucru,1
;... DA->dezactivez (timp expirat)
jmp afis
;afisez ultima sec. a cronom.
crono_j:
dec cs:crono_crt ;cronometru descrescator
cmp cs:crono_crt,0
;verific final
jnz afis
;... NU->afisez cronometru crt.
mov cs:mod_lucru,1
;... DA->dezactivez (timp expirat)
afis:
;afisare timp curent

Dup aceasta urmeaz afiarea timpului curent. De aici nainte, rutina


apeleaz alte ntreruperi. De aceea trebuie s fie verificate restriciile de activare
nainte de a putea merge mai departe. Problema ntreruperii funciilor DOS sau a
rutinelor de tratare a unei erori critice nu se pune deoarece nu sunt utilizate nici un
fel de funcii DOS, respectiv ntreruperi care s genereze erori critice. Rmn
restriciile privind ntreruperea unei rutine critice n timp i problema activrii
multiple:
cmp
jnz
cmp
jnz

cs:activ,0 ;tentativa de activare multipla ?


rel_sf_int8
cs:inbios,0
;intrerupere rutina critica ?
rel_sf_int8

736

Dac este posibil activarea afirii, atunci trebuie realizat comutarea


contextului, care const n comutarea stivei i salvarea regitrilor. DTA sau stiva
programului ntrerupt nu sunt alterate, deci nu trebuie s fie protejate. De
asemenea, cursorul video nu este afectat, deci nu trebuie salvat, iar coninutul
ecranului nu este afectat dect prin cele 8 caractere ale ceasului, dar aceast zon
oricum nu se justific a fi salvat. Comutarea contextului este realizat astfel:
cli
mov ax,ss
;salvez SS al prog. intrerupt
mov cs:ss_int,ax
mov cs:sp_int,sp ;salvez SP al prog. intrerupt
mov ax,cs
mov ss,ax
mov sp,offset varf_stiva
;comut pe stiva TSR-ului curent
mov cs:activ,1 ;marchez TSR-ul curent activ
sti
;reactivez intreruperile
push bx
push cx
push dx
push es
push bp
push si
push di
;salvez registrii contextului

Reactivarea ntreruperilor este realizat deoarece partea de cod ce urmeaz


necesit un timp de execuie ceva mai mare.
Dup salvarea contextului se mai impune o restricie privind modul video
care trebuie s fie text ca s se fac afiarea. Dac aceast restricie este satisfcut,
atunci se poate trece la pregtirea irului ce va fi afiat i apoi la afiarea propriuzis a acestuia:
mov ah,0Fh
int 10h
;det. mod video si pag. activa
cmp al,3
jbe afiseaza
cmp al,7
je afiseaza
jmp sf_afiseaza
;mod video <> text, nu mai afisez
afiseaza:

Pentru a determina cifrele orelor, minutelor i secundelor indicate de


cronometru se aplic dou mpriri succesive la 60 a numrului total de secunde
coninut de contorul cronometrului crono_crt, dup care, fiecare rest, respectiv
ultimul ct sunt mprii la 10 pentru a determina cifrele n baza 10. Aceast
extragere a cifrelor n baza 10 este fcut cu ajutorul macroinstruciunii urmtoare:

737
det_cifre
mov
div
add
mov
add
mov
endm

macro cifra_ofs
;;det. cifrele sec., min. sau orelor
cl,10
cl
;;impart nr. la 10 (se afla in AX)
ah,'0'
;;fac conversia la ASCII
cs:ceascifra_ofs+2,ah
;;in AH se afla cifra unitatilor
al,'0'
;;fac conversia la ASCII
cs:ceascifra_ofs,al ;;in AL se afla cifra zecilor

Ceasul de timp real este citit la fiecare secund cu ajutorul serviciului 2 al


ntreruperii 1Ah, care returneaz ora, minutul i secunda n format BCD
mpachetat:
mov ah,02h
int 1Ah
;citesc ceasul de timp real
jc defect
;CF=1 -> ceas defect
det_cifre_BCD ch,0
;determin cifrele orelor
det_cifre_BCD cl,6
;determin cifrele minutelor
det_cifre_BCD dh,12
;determin cifrele secundelor

Pentru conversia la ASCII se folosete macroinstruciunea urmtoare:


det_cifre_BCD macro reg,cifra_ofs
;;det. 2 cifre din BCD
impachetat
mov ah,0F0h
and ah,reg
;;extrag semioctetul sup. din reg
shr ah,1
shr ah,1
shr ah,1
shr ah,1
;;mut semioctetul in partea inf.
add ah,'0'
;;convertesc cifra la ASCII
mov cs:ceascifra_ofs,ah ;;scriu cifra zecilor
mov ah,0Fh
and ah,reg
;;extrag semioctetul inf. din reg
add ah,'0'
;;convertesc cifra la ASCII
mov cs:ceascifra_ofs+2,ah
;;scriu cifra unitatilor
endm

Dup afiarea efectiv a irului de caractere astfel obinut, rutina se ncheie


cu restaurarea contextului i IRET.
Partea nerezident a programului este format dintr-un prim bloc ce verific
existena unei instalri precedente, urmat de modulul de instalare i de modulul de
dezinstalare.
Verificarea existenei unei instalri precedente se face prin metoda
verificrii semnturii. n acest scop, n blocul de date al modulului rezident a fost
prevzut semntura CEAS/CRONOMETRU. Se compar irurile de 15
caractere de la deplasamentul semnatura, din cadrul adresei de segment a rutinei
de tratare a ntreruperii 88h, care este egal cu adresa de segment a programului

738

rezident dac acesta este instalat, respectiv din cadrul adresei de segment a
programului curent. Dac irurile sunt identice, atunci programul este deja instalat
i se apeleaz modulul de dezinstalare, iar dac irurile difer, atunci programul nu
a fost instalat i se apeleaz modulul de instalare:
mov ax,cs
mov ds,ax
mov ax,3588h
int 21h
;ES:BX=adresa rutina INT 88h
mov di,offset semnatura
mov si,di
;DI si SI = offset semnatura
cld
mov cx,lung_sem
repe cmpsb
;compar sirurile DS:SI si ES:DI
jne instalare ;daca diferite, instalare
jmp dezinstalare ;daca identice, dezinstalare

Modulul de instalare salveaz adresele rutinelor originale ale ntreruperilor


8h, 10h i 13h, dup care deturneaz ntreruperile 8h, 10h, 13h i 88h, apoi
elibereaz memoria ocupat de blocul de environment i n final apeleaz funcia
TSR.
Eliberarea blocului de environment se face innd cont de faptul c adresa
sa de segment se gsete la deplasamentul 2Ch n cadrul PSP al programului:
mov es,cs:2Ch
;adr. seg. bloc de environment
mov ah,49h
int 21h
;eliberare environment

Calculul numrului de paragrafe ocupate de modulul rezident se face astfel:


mov ax,offset nerezident
;det. nr. paragrafe modul
rezident
xor dx,dx
mov cx,16
div cx
;AX=paragrafe,DX=octeti suplim.
cmp dx,0
jz fix_paragraf
;DX=0 ->nr. fix de paragrafe
add ax,1
;DX>0 ->plus 1 paragraf incomplet
fix_paragraf:
mov dx,ax
mov ax,3100h
int 21h
;apel functie TSR

Modulul de dezinstalare d posibilitatea utilizatorului s aleag dac s fie


executat dezinstalarea, iar dac acesta dorete, atunci testeaz dac este posibil
dezinstalarea. Pentru aceasta verific dac adresa de segment a rutinelor curente de
tratare a ntreruperilor 8h, 10h i 13h este egal cu adresa de segment a

739

programului rezident instalat, gsit prin intermediul ntreruperii 88h. Dac o


singur rutin dintre cele menionate are o adres de segment diferit, atunci
nseamn c un alt program rezident a deturnat acea ntrerupere i n acest caz nu
mai este posibil dezinstalarea:
mov
mov
int
mov
cmp
jnz
mov
int
mov
cmp
jnz
mov
int
mov
cmp
jnz

cx,es
ax,3508h
21h
ax,es
cx,ax
nu_posibil
ax,3510h
21h
ax,es
cx,ax
nu_posibil
ax,3513h
21h
ax,es
cx,ax
nu_posibil

;CX=adr. seg. prog. rezident


;citire vector int. 8
;ES=adr. seg. rutina crt. INT 8
;INT 8 deturnat de alt TSR
;citire vector int. 10h
;ES=adr. seg. rutina crt. INT 10h
;INT 10h deturnat de alt TSR
;citire vector int. 13h
;ES=adr. seg. rutina crt. INT 13h
;INT 13h deturnat de alt TSR

Dac dezinstalarea este posibil, atunci se refac vectorii de ntrerupere la


vechile lor valori, memorate n zona de date a programului rezident instalat, dup
care este eliberat memoria ocupat de programul rezident:
mov
mov
mov
int
mov
mov
mov
int
mov
mov
mov
int
mov
mov
mov
mov
int
mov
int

ds,es:int8_veche_seg
dx,es:int8_veche_off
ax,2508h
21h
;restaurare int. 8
ds,es:int10h_veche_seg
dx,es:int10h_veche_off
ax,2510h
21h
;restaurare int. 10h
ds,es:int13h_veche_seg
dx,es:int13h_veche_off
ax,2513h
21h
;restaurare int. 13h
ax,0
ds,ax
dx,0
ax,2588h
21h
;dezactivare int. 88h
ah,49h
21h
;eliberare memorie TSR

Modulul de dezinstalare se ncheie prin apelul funciei DOS 4Ch.

740

23.9 Concluzii
Din coninutul acestui capitol se poate constata faptul c realizarea de
programe rezidente ridic probleme deosebite fa de programele clasice. Se
remarc faptul c este necesar respectarea riguroas a unor reguli suplimentare de
programare, precum i luarea n considerare a mai multor detalii tehnice privind
sistemul de calcul i sistemul de operare. n felul acesta programatorul are mai
puin libertate de aciune, iar programul rezultat este mult mai strns legat de
mediul de operare pentru care a fost creat.
Programele rezidente sunt programe cu grad foarte redus de portabilitate.
Ele pot rula doar pe acea clas de maini pentru care au fost realizate (n cazul de
fa este vorba de maini de tip PC), ce folosesc una din versiunile sistemului de
operare DOS. De asemenea, ele funcioneaz doar n modul real al procesorului,
specific pentru funcionarea sistemului de operare DOS. Mai mult dect att, este
posibil ca domeniul de funcionalitate al unui anumit program rezident s fie i mai
restrns dac acesta se folosete de caracteristici particulare ale unei anumite
versiuni de sistem de operare sau de detalii tehnice specifice unei anumite maini.
O alt meniune ce trebuie fcut este aceea c nu orice program rezident
funcioneaz n bune condiii, concomitent cu oricare alt program, fie el rezident
sau nu. Acest lucru se datoreaz faptului c sistemul de operare DOS este
monotasking i nu a fost prevzut s trateze conflictele ce pot apare ntre dou
procese active, care solicit aceleai resurse. Conflictele apar, de regul, ntre un
program rezident i un alt program, rezident sau nu, care se folosete de anumite
particulariti tehnice, ocolind interfaa standard oferit de sistemul de ntreruperi.
La realizarea programelor rezidente este nevoie s se acorde o mai mare
atenie optimizrii codului, deoarece, pe de o parte, un program rezident trebuie s
ocupe un minimum de memorie intern, iar pe de alt parte, rutinele programului
rezident trebuie s aib timpi minimi de execuie pentru a nu ncrca prea mult
procesorul cu operaii suplimentare. Aceast problem se pune cu att mai mult
atunci cnd programul rezident intervine asupra unor rutine critice ale sistemului.
Efortul suplimentar depus n realizarea programelor rezidente este justificat
deoarece aceste programe ofer o mbuntire a utilizrii unor programe cu
frecven mare de utilizare, n condiii de utilizare redus a resurselor
calculatorului, precum i posibilitatea de a realiza lucruri imposibil sau foarte
dificil de obinut cu ajutorul programelor clasice.

24

741

PROGRAMARE IN MODUL PROTEJAT


24.1 Moduri de operare ale procesoarelor 80x86
Existena celor trei moduri de lucru a procesoarelor 80x86: modul real,
modul protejat i modul virtual 8086, se datoreaz cerinei de pstrare a
compatibilitii n rularea programelor de ctre procesoarele mai noi fa de
primele procesoare ale familiei. Astfel procesoarele 8086, 8088 i 80186 rulau doar
n mod real. ncepnd de la procesorul 80286 s-a introdus i modul de operare
protejat, pentru ca procesoarele 80386 i 80486 s ruleze nativ n mod protejat cu
faciliti extinse de memorie virtual, multitasking i protecie a spaiului de adrese,
pstrndu-se pentru acestea i modul real de operare. De asemenea, ncepnd cu
aceste procesoare s-a mai introdus un mod de funcionare: modul virtual 8086.
Cele trei moduri de operare se caracterizeaz prin:
Modul protejat n acest mod sunt disponibile toate facilitile oferite de
procesoarele 80386/80486: posibilitatea extinderii memoriei fizice prin
alocarea de memorie virtual pe hard-disk, sistem multitasking implementat
hardware, protejarea contextului de execuie al unui program de aciunile
celorlalte programe care se execut pe sistem.
Modul real este modul de lucru nativ al procesoarelor 8086,8088 i
80186. n acest mod de lucru memoria disponibil pentru un program este
limitat la 1Mb, instruciunile folosesc regitri pe 16 bii, modul de adresare
a memoriei este bazat pe segmentare iar multitasking-ul nu este suportat de
hardware. Procesoarele 80386/80486 pot emula acest mod de lucru pentru a
permite programelor scrise n acest fel s ruleze. Pentru aceste procesoare,
modul real este independent de modul protejat. La pornirea calculatoarelor
echipate cu procesoare i386/i486 acestea intr n mod real deoarece
programele BIOS sunt scrise pentru acest mod de lucru. Comutarea ntre
modul real i modul protejat se face explicit, procesoarele i386/i486
neputnd lucra simultan n aceste dou moduri.
Modul virtual 8086 reprezint tot o emulare a procesoarelor 8086, dar sub
modul protejat. Astfel, procesoarele i386/i486, aflate n mod de lucru
protejat, pot simula maini virtuale 8086. Toate facilitile modului protejat
sunt disponibile i sub modul virtual 8086. Un program scris s ruleze sub
modul virtual 8086 este identic cu un program scris pentru un procesor
8086, dar este posibil multitasking-ul controlat hardware. Pentru a se realiza
acest lucru este necesar s existe un program care s monitorizeze execuia
n modul virtual 8086 pentru iniializare i tratarea excepiilor n stilul
modului protejat.
24.2 Regitrii procesoarelor i386/i486
Majoritatea regitrilor procesoarelor i386/i486 sunt pe 32 de bii, astfel
nct regitrii procesoarelor din generaiile anterioare (8086, 80186, 80286) sunt

742

subseturi ai acestora. Civa regitri sunt accesai direct prin nume, ceilali fiind
setai i citii prin instruciuni specifice. n continuare sunt reluate unele elemente
privind resursele sistemelor de calcul (regitri, indicatori de stare) dar n contextul
lucrului protejat.

Regitrii de segment
Adresele de segment ale modului real i selectorul de segment din modul
protejat sunt stocate n 6 regitri pe 16 bii. Registrul selector de segment este
folosit n modul protejat pentru a selecta descriptorul de segment definit n tabela
descriptorilor.
15
CS
DS
ES
SS
FS
GS

Figura 24.1 Regitrii de segment


Regitrii de segment se iniializeaz cu urmtoarele valori:
Registrul CS adresa segmentului de cod sau selectorul segmentului de
cod curent.
Registrul SS adresa segmentului de stiv sau selectorul segmentului
de stiv curent.
Regitrii DS, ES, FS, GS adresa segmentelor de date sau selectorii
segmentelor de date ai programului.

Registrul Instruction Pointer


Registrul pe 32 de bii EIP (Instruction Pointer) stocheaz offset-ul
urmtoarei instruciuni de executat relativ la adresa de segment CS. Primii 16 bii
ai registrului EIP pot fi accesai sub numele de IP i sunt folosii pentru adresarea
pe 16 bii.

Regitrii de uz general
Regitrii de uz general pe 32 de bii sunt numii EAX, EBX, ECX, EDX,
ESI, EDI, EBP i ESP. Primii 16 bii ai lor pot fi accesai sub numele de AX, BX,
CX, DX, SI, DI, BP, i respectiv SP i sunt folosii de ctre programele pe 16 bii
pentru procesoarele din generaiile inferioare. Octeii regitrilor AX, BX, CX, DX

743

pot fi referii ca AH, AL, BH, BL, CH, CL, DH i respectiv DL. Aceti regitri sunt
folosii pentru manipularea datelor n instruciuni.
31
16

15
8
AH
BH
CH
DH
SI
DI
BP
SP
IP

EAX
EBX
ECX
EDX
ESI
EDI
EBP
ESP
EIP

A
B
C
D

X
X
X
X

AL
BL
CL
DL

Figura 24.2 Regitrii de uz general

Registrul EFLAGS
Reprezint extinderea pe 32 de bit a registrului FLAGS de la procesoarele
8086, primii 12 bii avnd aceeai funcie ca la procesoarele pe 16 bii.
31
Rezervat

17
V

16 15
R
0 N IO

O D

7
I T S Z

F F

F F F F

T PL

A 0

0
1 C

Figura 24.3 Registrul EFLAGS la procesoarele i386

31
Rezervat

18 17 16
A V R

T PL F

IO O D I
F

7
S

A 0 P
F

0
C
F

Figura 24.4 Registrul EFLAGS la procesoarele i486


Semnificaia biilor suplimentari este urmtoarea:
IOPL (biii 12-13) (Input/Output Privilege Level) indic prioritatea
execuiei operaiilor de intrare/ieire. Aceast prioritate poate lua valori

744

ntre 0 i 3, valoarea 0 semnificnd cel mai nalt nivel de prioritate iar


valoarea 3 nivelul cel mai sczut.
NT (bitul 14) (Nested Flag) dac este setat task-ul curent este ncapsulat
ntr-un alt task
RF (bitul 16) (Resume Flag) este folosit mpreun cu instruciunea de
breakpoint pentru excepii. Dac este setat interzice tratarea de excepii
multiple pentru o instruciune.
VM (bitul 17) (Virtual-8086 mode) cnd este setat procesorul intr n
modul virtual 8086. Acest bit poate fi setat doar de o instruciune IRET
sau prin permutarea ntre task-uri n modul protejat.
Pentru procesoarele i486 se mai definete un flag:
AC (bitul 18) (Alignment Check) foreaz verificarea alinierii datelor.
Procesorul i486 genereaz o eroare de aliniament cu cod de eroare 0 n
momentul n care ntlnete date incorect aliniate. Doar programele care
ruleaz cu prioritatea 3 pot genera eroare de aliniament. Acest bit este
activat de bitul AM definit n registrul CR0.

Regitrii de control
Procesoarele i386/i486 au trei regitri de control: CR0, CR2 i CR3,
registrul CR1 este rezervat pentru utilizri viitoare. Aceti trei regitri stocheaz
starea global sau controlul operaiilor procesoarelor i386/i486.
Formatul registrului de control al mainii (CR0) este dat n figura 24.5
31
PG

4
ET

Rezervat

3
TS

2
EM

1
0
MP PE

Figura 24.5 Registrul CR0 al procesorului i386

31
PG

30
CD

29
NW

18
AM

16
WP

5
NE

4
ET

3
TS

2
EM

1
0
MP PE

Figura 24.6 Registrul CR0 al procesorului i486


Semnificaia biilor este urmtoarea:
PG (bitul 31) (Paging Enable) cnd este setat permite folosirea
modelului de memorie bazat pe pagini.
ET (bitul 4) (Processor Extension Type) cnd este setat se folosete
modul de operare pe 32 de bii compatibil 80387, altfel este folosit

745

modul pe 16 bii compatibil 80287 pentru funcionarea coprocesorului


matematic. La procesoarele i486 este ntotdeauna setat.
TS (bitul 3) (Task Switched) este automat setat atunci cnd se comut
ntre task-uri, pentru a permite coprocesorului s-i salveze contextul n
timpul comutrii.
EM (bitul 2) (Emulate Coprocessor) cnd este setat genereaz excepia
coprocesor indisponibil. Instruciunea WAIT ignor setarea acestui
bit.
MP (bitul 1) (Math Present) cnd sunt setai biii TS i MP, execuia
instruciunii WAIT sau a instruciunilor de coprocesor genereaz
excepia coprocesor indisponibil.
PE (bitul 0) (Protection Enable) cnd este setat procesorul funcioneaz
n mod protejat, altfel lucreaz n mod real.
Procesoarele i486 mai definesc urmtorii bii:
CD (bitul 30) (Cache Disabled) cnd este setat umplerea memoriei
cache intern a procesorului este dezactivat.
NW (bitul 29) (Not Write-Through) controleaz procesul de
remprosptare a memoriei cache, mpreun cu bitul CD.
AM (bitul 18) (Alignment Mask) controleaz verificarea alinierii. Cnd
este setat i prioritatea este 3, procesorul verific alinierea potrivit cu
valoarea bitului AC definit n EFLAGS.
WP (bitul 16) (Write Protect) cnd memoria este organizat la nivel de
pagini, procesele aflate pe nivele prioritare pot citi i scrie pagini aflate
pe nivele neprioritare. La procesoarele i486, dac acest bit este setat,
paginile nivelelor neprioritare sunt read-only.
NE (bitul 5) (Numeric Error) datorit faptului c procesorul i486
conine coprocesor matematic, poate efectua operaii n virgul mobil.
Cnd acest bit este setat procesorul genereaz o eroare nemascat prin
excepia 16 pentru a reporta o eroare de calcul n virgul mobil.
Registrul CR2 (Page Fault Linear Address Register) stocheaz adresa pe 32
de bii care a cauzat o eroare de pagin.
Registrul CR3 (Page Directory Base Address Register) conine adresa
fizic de referin a tabelei de pagini, atunci cnd mecanismul de paginare a
memoriei este activat. Primii 12 bii ai acestui registru sunt ntotdeauna 0 deoarece
dimensiunea unei pagini este de 4K. n cazul procesoarelor i386 aceti bii sunt
rezervai.

Registrul adreselor de sistem


Procesoarele i386/i486 creeaz urmtoarele tabele de sistem atunci cnd
lucreaz n mod protejat:
GDT (Global Descriptor Table) Tabela descriptorilor globali
LDT (Local Descriptor Table) Tabela descriptorilor locali

746

IDT (Interrupt Description Table) Tabela descriptorilor ntreruperilor


Regitrii GDTR i IDTR stocheaz adresa liniar i limita tabelelor CDT i
IDT. Registrul LDTR stocheaz selectorul de segment al tabelei LDT curente, iar
partea invizibil, figura 24.7 (aria haurat din figur stocheaz adresa de baz i
limita acestei tabele)
LDTR (selector)

Base Register

Limit Register

TR (selector)

Base Register

Limit Register

Figura 24.7 Utilizarea regitrilor LDTR i TR


Registrul proceselor (TR task register) stocheaz selectorul de segment al
segmentului de stare (TSS task state segment) pentru procesul curent. n
segmentul de stare se salveaz contextul procesului curent pe timpul comutrii ntre
task-uri. Partea invizibil a registrului TR stocheaz adresa de baz i limita
segmentului de stare a procesului (TSS).

Registrul descriptorului de segment


Pentru fiecare registru de segment exist cte un registru de descriptor de
segment. Aceti descriptori sunt invizibili i nu pot fi accesai n nici un fel. Cnd
se ncarc un selector de segment ntr-un registru de segment, descriptorul asociat
definit n tabela descriptorilor se ncarc n registrul descriptor asociat. Aceti
regitri permit referirea mai rapid a segmentelor i contribuie la implementarea
mecanismului de protecie la memoria segmentului.

Structuri de date ale modului protejat


Mediul de execuie a programelor n modul protejat difer semnificativ de
execuia lor n modul real. Pentru a lansa n execuie un program n mod protejat
este necesar construirea de structuri de date ale sistemului.
Tabela de descriptori globali, GDT este un vector de descriptori pe 8 octei
i este necesar pentru toate programele care se execut n mod protejat.
Segmentele de date, de cod i de sistem sunt definite n modul protejat. Fiecare
descriptor de segment are propriul lui format dup cum urmeaz, figura 24.8.
31
I/O Map Base
Reserved
Reserved
Reserved

16

15

0
Reserved
LDT
GS
FS

64
60
5C
58

747

Reserved
Reserved
Reserved
Reserved
EDI
ESI
EBP
ESP
EBX
EDX
ECX
EAX
EFLAGS
EIP
CR3
Reserved
ESP2
Reserved
ESP1
Reserved
ESP0
Reserved

DS
SS
CS
ES

SS2
SS1
SS0
Back link to previous TSS

54
50
4C
48
44
40
3C
38
34
30
2C
28
24
20
1C
18
14
10
0C
8
4
0

Figura 24.8 Formatul segmentului de stare a proceselor(TSS)

Base
G B 0 V Limit
P DPL 1 0 E W A Base
31..24
19..16
23..16
Segment Base 15..0
Segment Limit 15..0
G Granulaia
B Segment mare
V Disponibil pentru utilizare
P Existena segmentului
DPL Nivelul de prioritate al
E Expandare
descriptorului
A Accesat
W Permite scriere
Figura 24.9 Formatul descriptorului segmentului de date
Base
G D 0 V Limit
31..24
19..16
Segment Base 15..0

P DPL 1 1 C
Segment Limit 15..0

R A

Base
4
23..16
0

4
0

748

D dimensiunea
operaiilor

implicit

R permite citirea
C bit de conformitate

Figura 24.10 Formatul descriptorului segmentului de cod


Rezervat
Segment Base 15..0

P DPL 0 0 1 0
Segment Limit 15..0

Rezervat

4
0

Figura 24.11 Formatul descriptorului Task Gate


Offsetul n segment 31..16
Segment Base 15..0

P DPL 0 X 1 0 0 0 0 0 Count
Segment Limit 15..0

4
0

Figura 24.12 Formatul descriptorului Call Gate


Offsetul n segment 31..16
Segment Base 15..0

P DPL 0 X 1 1 1 T 0 0 Rezerved
Segment Limit 15..0

4
0

T 0 : interrupt gate, 1: trap gate


Figura 24.12 Formatul descriptorului Interrupt/Trap Gate
Base
G 0 0 V Limit
31..24
19..16
Segment Base 15..0

P DPL 0 0 0

Base
23..16

Segment Limit 15..0

4
0

Figura 24.13 Formatul descriptorului LDT

Base
G 0 0 V Limit
31..24
19..16
Segment Base 15..0

P DPL 0 X 0

B 1

Base
23..16

Segment Limit 15..0

4
0

X 0: procesor 80286, 1:procesor i386


B busy
Figura 24.14 Formatul descriptorului segmentului sistem

Instruciuni
Procesoarele i486 suport toate instruciunile procesorului i386, punnd la
dispoziie nc ase instruciuni.

Instruciuni utilizator

BSWAP (Byte Swap) aceast instruciune inverseaz ordinea datelor


stocate ntr-un registru pe 32 bii.
XADD (Exchange and Add) aceast instruciune ncarc datele din
operandul destinaie n operandul surs, calculeaz suma ntre valoarea
original a operandului surs i operandul destinaie i o stocheaz n
operandul destinaie.
CMPXCHG (Compare and Exchange) aceast instruciune compar
datele stocate n acumulator cu operandul destinaie, dac sunt egale
ncarc operandul surs n operandul destinaie, altfel ncarc datele din
acumulator n operandul destinaie.

Instruciuni de sistem

INVD (Invalidate Cache) aceast instruciune golete memoria cache


intern i trimite semnal ctre memoria cache extern pentru golire.
INVLPG (Invalidate TLB Cache) instruciunea invalideaz o intrare din
TLB.
WBINVD (Write-Back and Invalidate Cache) aceast instruciune
golete memoria cache intern i trimite semnale de write-back i de
golire ctre cea extern.
24.3 Moduri de gestiune a memoriei
Procesoarele i386/i486 suport dou tipuri de gestiune a memoriei;
segmentarea i paginarea. Ambele mecanisme ofer protecie pentru un program
mpotriva interaciunilor nedorite cu alte programe. Exemplul clasic este al
sistemului de operare care trebuie protejat mpotriva funcionarii aleatorii a
programelor de aplicaie.
Prin mecanismul de segmentare, procesorul convertete adresa logic de tip
segment:offset n adres liniar. Apoi, prin mecanismul de paginare convertete
adresa liniar n adres fizic, atunci cnd paginarea este activ. Adresa liniar
coincide cu adresa fizic atunci cnd paginarea nu este activ. Mecanismul de
paginare este folosit pentru extinderea memoriei fizice prin alocarea de memorie
virtual pe hard-disk.

Mecanismul de segmentare
Segmentarea ofer o modalitate simpl dar nestructurat de gestiune a
memoriei. Un program poate avea cteva spaii de adres protejate independente.
Un segment este un bloc de memorie a crei dimensiune este variabil.
Dimensiunea segmentelor folosite de ctre un program poate fi orict de mare, cu
condiia s nu depeasc memoria total disponibil n sistem. nainte de a accesa

un segment trebuie setate adresa liniar de baz a segmentului, dimensiunea, tipul


segmentului i atributele acestuia.
Atunci cnd procesorul acceseaz un segment, verific definirea acestuia
din descriptorul de segment pentru a asigura faptul c accesul nu ncalc regulile de
definire ale segmentului. Aceast procedur previne interaciunea dintre segmente
sau programe diferite. Politica de alocare a segmentelor depinde de sistemul de
operare care ruleaz pe main. Mai multe segmente diferite pot mpri acelai
bloc de segment prin definirea descriptoarelor cu aceeai adres de baz i aceeai
dimensiune.

Mecanismul de translatare a adresei la segmentare


n modul protejat selectorul de segment puncteaz ctre descriptorul de
segment. Fiecare selector de segment trebuie s aib o intrare n tabela
descriptorilor(fie n cea global GDT, fie n cea local LDT). Fiecare referin
de memorie este asociat cu un selector de segment. Descriptorul de segment
trebuie s includ toate informaiile despre segment. Procesorul i386/i486 obine
adresa liniar de baz din descriptorul corespunztor segmentului la care adaug
deplasamentul pentru a forma o adres liniara pe 32 de bii. n acelai timp
procesorul verific tipul segmentului, existena acestuia i dimensiunea
segmentului. Se genereaz o excepie n cazul n care referina ncalc definiia din
descriptor, de exemplu, dac deplasamentul este dincolo de limita segmentului.
Limita maxim pentru fiecare segment este de 1Gb (dac bitul granulaie este setat
pe valoarea 0) sau 4 Gb (dac bitul granulaie este setat pe valoarea 1).
Cei mai puin semnificativi bii ai selectorului de segment sunt considerai
cu valoarea 0 n timpul indexrii n tabela descriptorilor. Procesorul interpreteaz
aceti trei bii, figura 24.15.
15

2
TI

1 0
RPL

TI indicator de tabel
RPL (Requested Privilege Level) nivelul de prioritate solicitat
Figura 24.15 Selectorul de segment
Dac TI = 0 descriptorul se selecteaz din GDT, dac TI = 1 descriptorul se
selecteaz din LDT.

Paginarea
Spre deosebire de segmentare, paginarea mparte memoria sistemului n
blocuri de memorie de dimensiune fix, fiecare bloc fiind numit pagin. Pe
sistemele i386/i486, o pagin ocupa 4Kb. O adres liniar, obinut prin

10

translatarea la segmentare dintr-o adres utilizator de tip segment:offset, este


translatat la adresa fizic corespunztoare prin mecanismul de traslatare a adresei
la paginare, atunci cnd paginarea este activat.
Prin mecanismul de translatare, o parte a capacitii de stocare a hard diskului poate fi tratat ca spaiu de adrese de memorie. Atunci cnd procesorul trebuie
s acceseze o pagin care nu se afl n memoria fizic, genereaz o excepie pentru
a permite sistemului de operare s ncarce pagina cerut, apoi reia execuia din
punctul de ntrerupere.
24.4 Comutarea n modul protejat

Intrarea n modul protejat


La pornirea unui sistem i386 sau i486 programul de boot se ruleaz n mod
real. Pentru a rula programe n mod protejat trebuie executate cteva proceduri
pentru a comuta sistemul din mod real n mod protejat. Aceste proceduri se ruleaz
n mod real i trebuie s iniializeze structurile de date i regitrii specifici modului
protejat.
Cea mai important structur care trebuie iniializat este tabela
descriptorilor globali (GDT). Aceast structur trebuie s aib definite cel puin un
descriptor de segment pentru segmentul de cod i un descriptor de segment pentru
segmentul de date pentru a permite accesarea instruciunilor i a datelor conform cu
regulile din modul protejat. De asemenea adresa de baz i limita de adres a
tabelei GDT trebuie ncrcate n registrul GDTR nainte de intrarea n modul
protejat.
Dac se dorete lucrul cu vectori de ntreruperi mai trebuie construit i
ncrcat tabela descriptorilor de ntreruperi (IDT). n acest caz adresa de baz i
limita de memorie a tabelei IDT se ncarc n registrul IDTR.
Dup setarea acestor structuri se poate intra n modul protejat prin setarea
bitului PE n registrul CR0. Dup setarea acestui bit se execut o instruciune de
salt necondiionat pentru golirea cozii de instruciuni.
La intrarea n modul protejat toi regitrii de segment conin valori setate n
modul real. De aceea programul trebuie s rencarce selectorul de segment cu
regitrii de segment. n acest moment programul a comutat n modul protejat cu
nivelul de prioritate 0.

Ieirea din modul protejat


Procesorul i386 poate reintra n modul real prin setarea bit-ului PE al
registrului CR0 la valoarea 0. Pentru a continua execuia programului
n mod real anumite structuri de date ale sistemului trebuie resetate
pentru a permite programului s ruleze n mediul de execuie al
modului real. Pentru reintrarea n modul real se execut urmtorii pai:
Se seteaz prioritatea de execuie a procesului curent la valoarea 0
prioritatea modului real.

11

Se schimb limita segmentului CS la valoarea 0ffffh prin transferarea


controlului ctre un segment de cod cu limita 0ffffh limita
segmentului de cod CS n mod real.
Se ncarc toi regitrii de segment cu excepia registrului CS cu un
selector de segment pentru care descriptorul este de forma: DPL = 0,
writable = 1, expand = 0, present = 1, granular = 0, big = 0 i limit =
0ffffh.
Se dezactiveaz ntreruperile.
Se seteaz bitul PE din registrul CR0 la valoarea 0.
Se execut o instruciune de salt necondiionat pentru a goli coada de
instruciuni.
Se seteaz registrul IDTR pentru a puncta ctre tabela vectorilor de
ntrerupere a modului real.
Se activeaz ntreruperile.
Programul se afl acum n mod real. Dac este nevoie se reiniializeaz
regitrii de segment n modul real.
Descriptorii segmentelor de cod i de date pentru modul real sunt:
;formatul descriptorului segmentului de cod de nivel 0
code_sel

dw
dw
db
db
db
db

0ffffh
?
?
9ah
0
0

;limita(0-15)
;adresa de baza(0-15)
;adresa de baza(16-23)
;present=1,readable=1
;limit
a(16-19), G=0, D=0
;baza(24-31)

;formatul descriptorului segmentului de date


dmy_selec

dw
dw
db
db
db
db

0ffffh
?
?
92h
0
0

;limita(0-15)
;adresa de baza(0-15)
;adresa de baza(16-23)
;present=1, writable=1
;limita(16-19), G=0, D=0
;baza(24-31)

Reintrarea n modul real se realizeaz astfel :


;program n
db
dw
dw
real_l:
mov
mov
mov

modul protejat executat cu prioritatea 0


0eah
;salt neconditionat
offset
real_l
;ip
code_sel
;selector cs
ax,dmy_selec
es,ax
ds,ax

;selector fictiv
;resetarea registrilor de segment

12
mov
mov
mov
cli
mov
and
mov
db
dw
dw
read_mode:
mov
mov
lidt

fs,ax
gs,ax
ss,ax
;dezactivarea intreruperilor
eax,cr0
eax,not prot_enable ;dezactivarea modului protejat
cr0,eax
0eah
;salt neconditionat
offset real_mode ;EIP
code
;CS

ax,data
ds,ax
[oldidt]

;reincarcarea tabelei de
;intreruperi pentru modul real
;reactivarea intreruperilor

sti

Exemplu
Urmtorul exemplu demonstreaz comutarea ntre mod real i modul
protejat. Acest program pregtete structurile de date de baz pentru intrarea n
modul protejat. Programul nu include paginare, multitasking sau protecie n modul
protejat.
n cadrul acestui program se folosesc dou fiiere incluse:
STRUCT definete majoritatea structurilor de date folosite n modul
protejat
MACRO1 definete cteva macrodefiniii folosite n programul
principal.
Fiierul STRUCT:
;Structura descriptorului de segment
dscp

dscp

struct
D_lim1
D_base1
D_base2
D_type
D_lim2
D_base3
ends

db

dw
dw
db
db
db
0

0
0
0
0
0

;Structura stivei dupa intreruperea procesului n mod real


stkdef
oldeip

struct
dw
dw
0

13
oldcs

dw
dw

oldflg
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
dw
ends

oldsp
oldss
oldes
oldds
oldfs
oldgs
stkdef

0
0
dw
0
0
0
0
0
0
0
0
0
0
0
0
0

;Structura tabelei de pagini


page_tbl
struc
pg_stat
db
pg_avail
db
pg_limit
db
page_tbl
ends

?
?
?

Fiierul MACRO1
;Macrodefinitie pentru definirea stivei n TSS
TSS_stack
dd
dd
dd
dd
dd
dd
dd
endm

macro ss0,esp0,ss1,esp1,ss2,esp2
0
offset esp0
ss0
offset esp1
ss1
offset esp2
ss2

;Macrodefinitie pentru definirea CR3 n TSS


TSS_cr3
dd
endm

macro
0

;Macrodefinitie pentru definirea registrilor generali n TSS


TSS_regs macro teip,tflg,teax,tebx,tecx,tedx,tesi,tedi,tebp,tesp
dd
offset teip
dd
tflg

14
dd
dd
dd
dd
dd
dd
dd
dd

teax
tecx
tedx
tebx
offset tesp
tebp
tesi
tedi

endm
;Macrodefinitie pentru definirea registrilor de segment n TSS
TSS_seg
dd
dd
dd
dd
dd
dd
endm

macro tes,tcs,tss,tds,tfs,tgs
tes
tcs
tss
tds
tfs
tgs

;Macrodefinitie pentru salt far neconditionat


callf macro
db
dw
dw
endm

selector
9ah
0
selector

Program: EN.ASM
Acest program demonstreaz trecerea din modul real al sistemului de
operare DOS n modul protejat i rentoarcerea din modul protejat n modul real
DOS. Programul seteaz, mai nti, structurile de date ale modului protejat (GDT,
IDT i TSS) apoi intr n modul protejat, unde afieaz un mesaj, dup care
prsete modul protejat i restaureaz contextul modului real. Paii de execuie ai
programului sunt:
Pasul 0:

Definirea EQU.

Pasul 1:

Definirea tabelei descriptorilor globali (GDT).

Tabela descriptorilor locali nu este folosit n acest program, astfel nct toi
descriptorii sunt definii n tabela descriptorilor globali. n aceast tabel se
definete doar dimensiunea i tipul fiecrui descriptor, adresa de baz urmnd a fi
setat la momentul execuiei.

15

Primul descriptor trebuie s fie un descriptor NULL.


Descriptorul segmentului video, neiniializat la momentul execuiei, are
adresa de baz B8000h.

Pasul 2:

Definirea tabelei de ntreruperi(IDT).

n acest program se definesc 21 de ntreruperi n IDT. Selectorul de


segment a acestor ntreruperi este int_selec. Offset-ul ntreruperilor este iniializat
la momentul execuiei.
Pasul 3:

Definirea variabilelor.

pGDT este un pointer ctre o structur de ase octei coninnd adresa


de baz i dimensiunea GDT.
pIDT este un pointer ctre o structur de ase octei coninnd adresa de
baz i dimensiunea IDT.
pold este un pointer ctre o structur de ase octei coninnd adresa de
baz i dimensiunea tabelei vectorilor de ntrerupere definii n modul
real DOS.

Pasul 4:
Definirea tabelei de mapare pentru fiecare selector ctre
segmentul corespunztor.
Aceast tabel conine acei selectori pentru care adresa de baz trebuie
iniializat n descriptor. Segmentul corespunztor este definit folosind selectorul
asociat.
gdt_tab-size conine numrul de intrri ale tabelei GDT.
Pasul 5:

Definirea mesajelor.

Pasul 6:

Definirea segmentelor de stiv de nivel 0, 1 i 2.

Pasul 7:

Setarea TSS.

Pasul 8:
Definirea unui segment fictiv folosit pentru obinerea valorii
registrului descriptor de segment la ntoarcerea n modul real.
Pasul 9:
Iniializarea punctului de intrare pentru fiecare descriptor de
ntrerupere definit n IDT. Pentru fiecare rutin de ntrerupere se rezerv 4 octei
ntr-un vector n memorie.

16

Pasul 10: Programul obine adresa liniar de baz (32 de bii) i


dimensiunea pentru GDT i IDT i le stocheaz.
Pasul 11: Pe baza adresei de segment definit n tabela gdt_phys_tab obine
adresa liniar de baz i o seteaz n descriptorul corespunztor selectorului de
segment.
Pasul 12: Comut n modul protejat:

ncarc adresa liniar de baz i dimensiunea GDT n registrul GDTR


ncarc adresa liniar de baz i dimensiunea IDT n registrul IDTR.
Seteaz bitul PF n registrul CR0.
Apeleaz o instruciune de salt necondiionat pentru a goli coada de
instruciuni.

Pasul 13: Seteaz regitrii LDTR, SS, SP, DS, ES, FS i GS.
Pasul 14: Afieaz mesajul pe ecran.
Datorit faptului c funciile de sistem DOS nu sunt disponibile n modul
protejat, programul scrie mesajul direct n memoria video, n secvena:
scrie spaii n memoria video pentru a terge ecranul
afieaz mesajul
Pasul 15: ncarc selectorul segmentului procesului curent n registrul
proceselor (TS)
Pasul 16: Apeleaz o ntrerupere software prin intermediul descriptorilor de
ntreruperi definii n IDT. Rutina ntreruperii afieaz numrul ntreruperii i
comut napoi n modul real DOS.
Fiierul EN.ASM
.386p
include struct
include macro1
;Pasul 0: definire EQU
INTNO
DSCPSIZE
INTSIZE
TWO
prot_enable

equ
equ
equ
equ
equ

21
8
4
2
01h

17
attribute
space

equ
equ

;Pasul 1:

GDT

07h
20h

GDT segment para public


gdt_tab
label qword
null_selec
dscp

equ
$-gdt_tab
<,,,,,>

code_selec

equ $-gdt_tab

dscp

<0ffffh,,,09h,,>

use16

GDT

;descriptorul selectorul
;segmentului de
;cod

task0_TSS_selec
equ
$-gdt_tab
;descriptorul selectorului
dscp
<task0_TSS_limit,,,089h,,>
;segmentului TSS
stk0_selec
dscp
0

equ
$-gdt_tab
<stk0_limit,,,92h,,>

;descriptorul selectorului
;segmentului de stiva de nivel

stk1_selec
dscp

equ
$-gdt_tab or 1
<stk1_limit,,,0b2h,,>

;descriptorul selectorului
;segmentului de stiva de
;nivel 1

stk2_selec
dscp

equ
$-gdt_tab or 2
<stk2_limit,,,0d2h,,>

;descriptorul selectorului
;segmentului de stiva de
;nivel 2

dmy_selec
dscp

equ
$-gdt_tab
<0ffffh,,,92h,,>

video_selec equ
$-gdt_tab or 3
dscp
<0ffffh,8000h,0bh,0f2h,,>
gdata_selec equ
$-gdt_tab
dscp
<gdata_limit,,,0f2h,,>
int_selec
dscp

equ
$-gdt_tab
<0ffffh,,,09ah,,>

gdt_limit
GDT
ends

equ

;Pasul 2:

IDT

$-gdt_tab

IDT
segment para
public use 16 idt
idt_tab
equ
$
REPT INTNO
dscop <,int_selec,0,0eeh,,>
ENDM

18
idt_limit
IDT
ends

equ

;Segmentul de date
Gdata segment para public use16 Gdata
;Pasul 3:

Definirea variabilelor

pGDT
pGDT_limit
pGDT_addr

label fword
dw
?
dd
?

pIDT
pIDT_limit
pIDT_addr

label fword
dw
?
dd
?

pold
dIDT_limit
dIDT_addr

label fword
dw
03ffh
dd
0

;Pasul 4:

tabela maparilor intre descriptori i segmente

gdt_phys_tab
label word
dw
task0_TSS_selec
dw
task0_TSS
dw
stk0_selec
dw
stk0
dw
stk1_selec
dw
stk1
dw
stk2_selec
dw
stk2
dw
dmy_selec
dw
dmy
dw
code_selec
dw
code
dw
gdata_selec
dw
gdata
dw
int_selec
dw
code
gdt_tab_size
equ
($ - gdt_phys_tab) / 4
;Pasul 5:

Definirea mesajelor

in_protected
int_msg
int_num

Gdata_limit equ
Gdata ends

db
dw
db
$

db
MOD PROTEJAT,0
Intreruperea:
?
H,0

19
;Pasul 6:

Definirea segmentelor de stiva de nivel 0, 1 i 2

stk0

segment
para public use16 stk0
db
100h dup(0)
stk0_limit equ $
stk0 ends
stk1

segment
para public use16 stk1
db
100h dup(0)
stk1_limit equ $
stk1 ends
stk2

segment
para public use16 stk2
db
100h dup(0)
stk2_limit equ $
stk2 ends
;Pasul 7:

TSS

task0_TSS
TSS_stack

segment
para public use16 task0
stk0_selec,stk0_limit,stk1_selec,
stk1_limit,stk2_selec,stk2_limit
TSS_cr3
0
TSS_regs
0,0,0,0,0,0,0,0,0,stk0_limit
TSS_seg
gdata_selec,code_selec,stk0_selec,
gdata_selec,gdata_selec,gdata_selec
dd
0
;LDT
dw
0
;task trap flag
dw
68h
;adresa de I/O
task0_TSS_limit
equ
$
task0_TSS
ends
;Pasul 8:
dmy
dmy

Segmentul fictiv

segment
db
128
ends

para public
dup(0)

use16 dmy

;Segmentul de cod
code segment
assume
main

proc
mov
mov

;Pasul 9:
mov
mov
mov

para public use16 code


cs:code,ds:gdata

far
ax,gdata
ds,ax
Initializarea IDT
ax,IDT
es,ax
di,offset

idt_tab

20
mov

ax,offset

int_entry

mov
fillidt:
mov
add
axx
loop

cx,INTNO

;Pasul 10:

Obtinerea adresei i dimensiunii GDT/IDT

es:[di],ax
di,DSCPSIZE
ax,INTSIZE
fillidt

mov
mov
xor
mov
shl

ax,offset
gdt_kimit
pGDT_limit,ax
eax,eax
ax,GDT
eax,4

mov

pGDT_addr,eax

mov
mov
xor
mov
shl

ax,offset
idt_limit
pIDT_limit,ax
eax.eax
ax,idt
eax,4

mov

pIDT_addr,eax

;Pasul 11:Pe baza gdt_phys_tab se seteaza adresa


;de baza pentru fiecare descriptor
mov
mov
mov

ax,GDT
es,ax
si,offset gdt_phys_tab

mov

cx,gdt_tab_size

bdt1:
lodsw
mov
bx,ax
and
bx,0fff8h
lodsw
push
shl
mov

ax
ax,4
es:[bx][d_base1],ax

pop
shr
mov

ax
ax,12
es:[bx],d_base2],al

loop

bdt1

;Pasul 12: comutarea n mod protejat

21
cli
lgdt
lidt

[pGDT]
[pIDT]

mov
or
mov

eax,cr0
al,prot_enable
cr0,eax

jmp

dword ptr

cs:[enter_prot]

enter_prot:
dw
offset
dw
code_selec

now_in_prot

;Pasul 13: Executie n mod protejat


; - setare LDTR,SS,SP,DS,ES,FS,GS
now_in_prot:
xor
lidt
mov
mov
mov
mov
mov
mov
mov
mov

ax,ax
ax
ax,stk0_selec
ss,ax
sp,offset stk0_limit
ax,gdata_selec
ds,ax
es,ax
fs,ax
gs,ax

;Pasul 14: Afisarea mesajului

mov
mov
mov
xor
mov
mov
rep
mov

ax,video_selec
es,ax
cx,4000h
di,di
ah,attribute
al,space
stosw
si,offset
in_protected

mov
call

di,320
disp_it

;Pasul 15:
mov
ltr

Incarcarea TSS n registrul TR


ax,task0_TSS_selec
ax

22
;Pasul 16:
int

int_entry:
REPT
call
iret
ENDM

Intoarcerea n modul real DOS


20

INTNO
disp

disp:
pop
mov
mov
sub

ax
bx,gdata_selec
ds,bx
ax,offset
int_entry

shr
mov
mov
call
mov
mov
call

ax,TWO
si,offset
cx,TWO
htoa
si,offset
di,5*160
disp_it

cli
mov
mov
mov
mov
mov
mov
mov
and
mov

ax,dmy_selec
es,ax
ds,ax
fs,ax
gs,ax
ss,ax
eax,cr0
eax,not
prot_enable
cr0,eax

db
dw
dw

0eah
offset
code

next_instruction:
mov
ax,Gdata
mov
ds,ax
mov
ax,stk0
mov
ss,ax
mov
sp,offset
lidt

[pold]

sti
mov

ax,4c00h

int_num

int_msg

next_instruction

stk0_limit

23
main

int
endp

21h

disp_it
mov
mov
mov
disp_itl:
lodsb
stosw
cmp
jne
ret
disp_it

proc near
ax,video_selec
es,ax
ah,attribute

htoa_tab
htoa proc
xor
add
dec
htoal:
mov
and
mov

db
0123456789ABCDEF
near
ebx,ebx
si,cx
si

htoa

mov
dec
shr
loop
ret
endp

code

ends

al,0
disp_itl
endp

bl,al
bl,0fh
bl,cs:[htoa_tab][ebx]
byte ptr
esi
eax,4
htoal

[esi],bl

end main

24.5 Implementarea modului de lucru multitasking


n sistemele multitasking, este necesar salvarea strii mainii n timpul
comutrii ntre procese. Procesoarele i386/i486 suport aceast operaie n mod
nativ, putnd comuta rapid ntre dou procese. Atunci cnd este solicitat
comutarea ntre procese, procesorul salveaz starea procesului curent n segmentul
de stare a procesului (TSS), ncarc contextul noului proces din segmentul su de
stare, verific respectarea integritii datelor folosite de acesta i ncepe execuia
noului proces.
Comutarea ntre procese poate fi invocata printr-o instruciune de tip CALL
sau JMP ctre un descriptor de segment TSS sau ctre un descriptor de tip Task
Gate. De asemenea mai poate fi invocat prin intermediul unei ntreruperi prin
iniializarea unui element din IDT cu descriptorul unui proces. Un descriptor de

24

segment TSS poate fi stocat doar n GDT. Dac este invocat o comutare ctre un
proces al crui descriptor este stocat n LDT, procesorul genereaz o excepie.
Dac a fost invocat o comutare prin intermediul unei instruciuni CALL sau
INT, ntoarcerea ctre procesul iniial se realizeaz printr-o instruciune IRET.
Exemplul care urmeaz realizeaz comutarea ntre dou procese numite:
task0 i task1 folosind o instruciune JMP ctre descriptorul TSS al procesului
task1. Dup ce se realizeaz comutarea, procesul task1 realizeaz ntoarcerea
ctre procesul task0 folosind o ntrerupere software. Aceast ntrerupere are
descriptorul definit n IDT fiind ceea ce se numete un descriptor de tip task gate
ctre descriptorul TSS al procesului task0.
Program: mult.asm
Mai nti se definesc cele dou procese:
TSS0

dd
dd
dd
dd
dd
dd
dd
dd
dd
dd
TSS0_limit

0
0,0
0,0
0,0
0
0
0
0,0,0,0,0,0,0,0
0,0,0,0,0,0
0
equ
$

;
;esp0,ss0
;esp1,ss1
;esp2,ss2
;cr3
;eip
;eflags
;eax,ecx,ebx,edx,esp,ebp,esi,edi
;es,cs,ss,ds,fs,gs
;LDT

TSS1

dd
0
dd
task1_esp0,task1_ss0
;esp0,ss0
dd
task1_esp1,task1_ss1
;esp1,ss1
dd
task1_esp2,task1_ss2
;esp2,ss2
dd
0
;cr3
dd
task1_eip
;eip
dd
task1_eflags
;eflags
dd
task1_eax,task1_ecx,task1_ebx,task1_edx
;eax,ecx,ebx,edx
dd
task1_esp,task1_ebp,task1_esi,task1_edi
;esp,ebp,esi,edi
dd
task1_es,task1_cs,task1_ss,task1_ds
;es,cs,ss
dd
task1_ds,task1_fs,task1_gs
;ds,fs,gs
dd
0
TSS1_limit equ
$

Apoi se definesc descriptorii pentru cele dou procese:


task0_TSS_selec
label word
dw
TSS0_limit
dw
TSS0_base1

25
db
db
db
db

TSS0_base2
89h
0
0

task1_TSS_selec
label word
dw
TSS1_limit
dw
TSS1_base1
db
TSS1_base2
db
89h
db
0
db
0

Fa de exemplul precedent mai intervin urmtorii pai suplimentari:


Pasul 1.1
Definirea descriptorului, selectorului segmentului de cod i
TSS pentru procesul task1:
task1_TSS_selec
equ
$-gdt_tab or 1
dscp
<task1_TSS_limit,,,09ah,,>
task1_code_selec equ
$-gdt_tab or 1
dscp
<task1_seg_limit,,,0bah,,>

Pasul 2.1
Definirea descriptorului task gate n IDT, punctnd ctre
TSS-ul procesului task0:
dscp

<,task0_TSS_selec,0,0e5h,,>

Pasul 4.1

;intreruperea 21

Definirea maprii ntre descriptor i segment pentru procesul

task1
dw

task1_TSS_selec
dw
task1_TSS
dw
task1_code_selec
dw
task1_seg

Pasul 7.1
task1_TSS
TSS_stack
TSS_cr3
TSS_regs
TSS_seg

Definirea TSS pentru procesul task1.


segment
para public use16 task1
stk0_selec,stk0_limit,stk1_selec,
stk1_limit,stk2_selec,stk2_limit
0
task1_entry,2,0,0,0,0,0,0,0,stk1_limit
gdata_selec,task1_code_selec,stk1_selec,
gdata_selec,gdata_selec,gdata_selec
dd
0
dw
0

26
task1_TSS_limit
task1_TSS

dw
equ
ends

68h
$

Pasul 15.1
Comutarea ctre procesul task1 prin salt necondiionat
ctre selectorul segmentului TSS al procesului task1
jmpf

Pasul 17:

task1_TSS_selec

Segmentul de cod al procesului task1

task1_seg
segment
para public use16 task1_seg
assume
cs:task1_seg,ds:gdata
task1_entry proc near
mov
si,offset task1_msg
mov
di,160*3
call disp2
int21
task1_entry endp
disp2 proc
mov
mov
mov
disp21:
lodsb
stosw
cmp
jne
ret
disp2 endp

near
ax,video_selec
es,ax
ah,attribute

al,0
disp21

task1_seg_limit
task1_seg
ends

equ

24.6 Concluzii
Spre deosebire de modul real, modul protejat ofer programatorului ntreaga
capacitate a procesoarelor i386/i486. n modul protejat multitasking-ul, memoria
virtual i protejarea spaiului alocat unui program fiind asigurate n mod nativ,
prin hardware.
n contextul tendinei de pe piaa software-ului ctre aplicaii care necesit
un volum tot mai mare de resurse, precum i datorit existenei sistemelor de
operare care lucreaz n mod protejat (sistemele MS Windows) cunoaterea
principiilor de programare n acest mod este obligatorie pentru realizarea de
programe performante sub aceste platforme.

27

25
PROGRAMAREA APLICAIILOR WINDOWS N
LIMBAJ DE ASAMBLARE
25.1 Interfaa de programare a aplicaiilor Windows
API (Application Programming Interface) pentru sistemele Win32 este
implementat n biblioteci cu legare dinamic.. Aceste biblioteci sunt separate de
programul executabil. Spre deosebire de DOS, API-urile nu sunt accesate prin
ntreruperi.

Codul funciilor Windows este stocat n fiiere din afara


programului, numite DLL (Dynamic Link Libraries) - biblioteci cu
legturi dinamice. Atunci cnd este rulat un program Windows,
interconectarea acestuia cu sistemul de operare se face prin
procesul de legare dinamic. Un fiier executabil al unui program
Windows conine referine la biblioteci cu legturi dinamice.
Atunci cnd un program pentru Windows este ncrcat n
memorie, apelurile de funcii sunt rezolvate astfel nct s indice
intrrile n funciile din DLL-urile utilizate, care sunt ncrcate n
memorie, n cazul n care nu se afl deja acolo.
Principalele biblioteci cu legare dinamic sunt kernel32.dll,
user32.dll i gdi32.dll. Biblioteca cu legare dinamic kernel32.dll
conine funciile API pentru gestionarea memoriei i a
proceselor. Biblioteca cu legare dinamic user32.dll controleaz
aspectele interfeei cu utilizatorul ale programului. Biblioteca cu
legare dinamic gdi32.dll este responsabil cu operaiile grafice.
n afar de aceste biblioteci principale se pot utiliza n program i
alte biblioteci cu legare dinamic.
Exist dou categorii de funcii API: unele pentru ANSI i altele pentru
Unicode. irurile ANSI sunt vectori de caractere terminate cu NULL. Un caracter
ANSI are dimensiunea de 1 byte. Un caracter Unicode are dimensiunea de 2 octei.
Numele funciilor API pentru ANSI se termin cu caracterul "A" (de exemplu

28

MessageBoxA), iar numele funciilor API pentru Unicode se termin cu W


(MessageBoxW). n mod nativ Windows 95 suport ANSI iar Windows NT
Unicode. n general n fiierele cu prototipurile funciilor exist declaraii
echivalente ale acestora n care se elimin caracterul A, respectiv W (de exemplu
MessageBox).

25.2 Organizarea memoriei n Windows 9x


Programele Win32 ruleaz n modul protejat, acest mod
existnd ncepnd cu microprocesorul 80286. Windows ruleaz
fiecare program Win32 n spaii virtuale separate. Aceasta
nseamn c fiecare program Win32 va avea propriul spaiu de
adresare de 4 GB. Deoarece programele Win32 au 4 GB de
memorie adresabil, pointerii pot adresa zone de memorie
cuprinse ntre 00000000H i FFFFFFFFH. n Windows 9x ,
fiecare proces obine propriul spaiu de memorie de 4 GB, spaiu
care este n totalitate al su. De fapt el partajeaz mpreun cu
alte aplicaii care ruleaz, primii 2 GB de memorie. Este
important s se considere c cei 4GB ai spaiului procesul sunt
numai i numai ai acestuia. Acest model de memorie se
numete flat.
Seciunea cea mai joas a memoriei (regiunea de 64 KB)
este rezervat n Windows 95 pentru atribuirile de pointeri nuli.
Restul memoriei, pn la 4 MB este rezervat de sistem pentru
compatibilitatea cu aplicaiile Win16 i cu aplicaiile MS-DOS.
Programele Win32 sunt ncrcate la adresa 00400000H
(adresa de baz a aplicaiilor Win32 n memorie), deci spaiul de
lucru al programului este pn la 7FFFFFFFH. ncepnd cu
adresa 80000000H, Windows 9x ncarc propriile DLL-uri de
sistem. ncepnd cu adresa C0000000H pn la sfritul celor 4
GB se ncarc sistemul de operare Windows 9x precum i
programele pentru dispozitive virtuale.
Puine calculatoare au 4GB de memorie. Datorit acestui
lucru, proiectanii de hardware au introdus ideea de memorie

29

virtual i memorie fizic. Memoria virtual corespunde celor 4


GB de memorie adresabil, memoria fizic este limitat de
memoria RAM disponibil n calculator i de spaiul pe hard disk.
Memoria este mprit n pagini, dimensiunea paginii fiind
optimizat n funcie de suportul hardware, pe sistemele 80x86,
mrimea unei pagini fiind de 4 KB.
FFFFFFFFH
Sistemul de operare Windows 9x
Drivere
C0000000H
4GB
BFFFFFFFH
DLL-uri Win32 partajate
Fiiere mapate n memorie
80000000H
7FFFFFFFH
Programul Win32
2GB
00400000H
003FFFFFH
Compatibilitate cu Win16

00001000H
00000FFFH
Protejata, atribuiri de pointeri NULL
Compatibilitate cu Win16

4MB

00000000H

Figura 25.1 Organizarea memoriei n Windows 9x


Sistemul de gestiune a memoriei determin paginile
localizate n memoria virtual i n RAM i furnizeaz un

30

mecanism de conversie a adreselor din memoria virtual n


adrese fizice. Programul de gestiune a memoriei poate muta sau
comuta paginile de memorie dac este nevoie de spaiu
suplimentar de memorie fizic. Windows schimb memorie n i
afar din fiierul de paginare de pe hard disk. Dimensiunea
fiierului de paginare mpreun cu dimensiunea memoriei RAM
este considerat memoria fizic.
Cnd este rulat un program, fiierul EXE de pe disc (numit
imaginea programului) este considerat ca fcnd parte din
fiierul de paginare de pe hard disk. n acest fel se economisete
timpul necesar ncrcrii fiierului executabil n memoria RAM.
Imaginea fiierului EXE de pe disc este considerat parte a
fiierului de paginare i seciunile de cod (nu i de date) sunt
citite de pe disc atunci cnd este nevoie de ele.
25.3 ncrcarea programelor Win32
Aplicaiile Win32 ruleaz n segmente cu adresare pe 32
de bii, utiliznd modelul de memorie FLAT. Astfel, programul
este n mod automat n modul protejat. Adresele generate i
utilizate de program se numesc adrese liniare. Registrele de
segment CS, DS, ES i SS sunt iniializate astfel c nu mai
conteaz ce segment este utilizat pentru a adresa o locaie dat
(o adres liniar). Adresa de baz la care este ncrcat
programul n memorie este 0040000h.
La lansarea n execuie a programelor, valorile iniiale ale regitrilor sunt:

CS:EIP nceputul programului


SS:ESP nceputul stivei
DS=ES=SS selectorul de date
FS=TIB (Thread Information Block)
GS=0, selectorul nul
CS i DS sunt mapate pe aceeai adres liniar
Indicatorul de direcie, DF, este ters.

Sistemul Windows utilizeaz intern regitrii ESI, EDI, EBP i EBX i de


aceea presupune c valorile acestor regitri nu se vor schimba. Se recomand deci
n cazul utilizrii acestor regitri n cadrul unor funcii callback s se salveze

31

coninutul lor nainte de modificare i s se restaureze nainte de a da controlul


sistemului Windows. O funcie callback este o funcie scris de programator,
funcie ce este apelat de Windows. Un exemplu de astfel de funcie este funcia
fereastr.

25.4 Structura unui program n limbaj de asamblare


Un program Win32 scris n limbaj de asamblare are
urmtoarea structur:
.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
includelib \masm32\lib\user32.lib
.data
;
;datele iniializate
;
.data?
;
;datele neiniializate
;
.const
;
;constantele
;
.code
eticheta_de_inceput
;
;codul propriu zis
;
end eticheta_de_inceput

Directiva .386 anun asamblorul c se va utiliza setul de


instruciuni specifice procesorului 80386. Se pot utiliza i
directivele .486, .586. Pentru fiecare model al microprocesorul
sunt dou forme aproape identice ale acestei directive:
.386/.386p, .486/.486p. Versiunile cu p sunt necesare atunci
cnd programul utilizeaz instruciuni privilegiate. Instruciunile
privilegiate sunt rezervate de microprocesor/sistem de operare

32

n modul protejat. Ele pot fi utilizate numai de cod protejat, cum


ar fi programele pentru echipamente virtuale.
Directiva .model specific modelul de memorie al
programului. Sub Win32 exist numai modelul de memorie flat.
n directiva .model mai este precizata i convenia de
transmitere a parametrilor (stdcall). Convenia de transmitere a
parametrilor specific ordinea de transmitere a parametrilor (de
la stnga la dreapta sau de la dreapta la stnga) i de
asemenea cine va echilibra stiva dup apelul funciei.
Sub Win16 exist dou tipuri de convenii de apel: C i
PASCAL.
Convenia de apel C transmite parametri de la dreapta la
stnga, cel mai din dreapta parametru fiind pus primul pe stiv.
Apelatorul este responsabil cu echilibrarea stivei dup apel. De
exemplu apelul unei funcii f(int a, int b) utiliznd convenia C de
transmitere a parametrilor n limbaj de asamblare va fi:
push [b]
push [a]
call f
add sp, 8 ; apelatorul echilibreaz stiva

Convenia de apel PASCAL presupune transmiterea


parametrilor de la stnga la dreapta, funcia apelat fiind
responsabil cu echilibrarea stivei dup apel.
Convenia de apel C este util atunci cnd nu se tie exact
numrul de parametri ce vor fi transmii funciei. O astfel de
funcie este wsprinf. Nu se tie dinainte ci parametri vor fi pui
pe stiv, deci n cadrul funciei nu se poate realiza echilibrarea
stivei.
STDCALL este un hibrid ntre conveniile de transmitere a
parametrilor C i PASCAL. Parametri sunt pui pe stiv de la
dreapta la stnga (ca n convenia C), ns funcia apelata este
responsabil cu echilibrarea stivei (convenia PASCAL).
Platforma Win32 utilizeaz exclusiv convenia STDCALL cu
excepia funciei wsprintf.

33

Directiva option casemap :none anun MASM c


etichetele sunt case-sensitive.
Directiva
include
\masm32\include\windows.inc
insereaz fiierul windows.inc n acest punct n programul surs.
Acest fiier conine declaraiile pentru majoritatea constantelor i
structurilor utilizate de API. Dup aceast directiv se urmeaz
includerea fiierelor ce conin antetele funciilor utilizate din
bibliotecile respective. De exemplu dac se utilizeaz funcia
MessageBox
se
va
scrie
include
\masm32\include\user32.inc, avnd n vedere c aceast
funcie exist n user32.dll.
Directiva includelib \masm32\lib\user32.lib informeaz
asamblorul ce biblioteci de import sunt utilizate. Cnd
asamblorul ntlnete aceast directiv, el pune o comand a
editorului de legturi n fiierul obiect astfel nct editorul de
legturi s tie ce biblioteci utilizeaz programul i de unde s le
ia.
Seciunea .data conine datele iniializate ale programului.
Seciunea .data? conine datele neiniializate ale programului.
Aceasta are avantajul c fiierul executabil nu i mrete
dimensiunea corespunztor cu mrimea datelor neiniializate. Ea
doar informeaz asamblorul ct spaiu de memorie este necesar
cnd programul este ncrcat n memorie. Seciunea .const
conine declaraiile de constante din program. Aceste nu pot fi
modificate n program.
Seciunea
.code
conine
codul
programului.
Eticheta_de_inceput este o etichet ce marcheaz nceputul
codului programului. Prima instruciune executabil se afl dup
eticheta_de_inceput.
Codul
trebuie
s
fie
ntre
eticheta_de_inceput i end eticheta_de_inceput.
Pe lng programul surs, dac n program se utilizeaz
resurse ca meniuri, pictograme, csue de dialog, acestea se
definesc ntr-un fiier special, numit fiier de resurse, fiier ce
are extensia .rc. Acesta este un fiier text n care se descriu
resursele i se face asocierea cu fiiere existente pe disc. De
exemplu, pentru resursa pictogram este linia:

34

ID_ICON ICON "WHAT1.ICO"

25.5 Programarea sub Windows


Majoritatea programelor Windows au o fereastr principal asociat. Atunci
cnd programul este lansat n execuie, Windows creeaz o coad de mesaje pentru
programul respectiv. n aceast coad de mesaje sunt pstrate mesajele trimise ctre
toate ferestrele pe care le creeaz programul. Programul conine o mic secven de
cod numit bucla de mesaje care preia mesajele din coada de mesaje i le distribuie
funciilor fereastr corespunztoare. Anumite mesaje sunt trimise direct funciei
fereastr fr a mai fi puse n coada de mesaje.
Paii necesari crerii unei ferestre sunt:
obinerea identificatorului instanei programului
obinerea liniei de comand (opional)
nregistrarea clasei fereastr (window class)
crearea ferestrei
afiarea ferestrei
actualizarea zonei client a ferestrei
intrarea n bucla de mesaje infinit
dac sunt mesaje pentru fereastr ele sunt prelucrate de o funcie
specializat numit i funcia fereastr
terminarea programului
Obinerea identificatorului instanei programului se realizeaz prin apelul
funciei GetModuleHandle. Funcia returneaz identificatorul instanei curente a
programului. Prototipul funciei este:
HMODULE GetModuleHandle(LPCTSTR lpModuleName);

Prin transmiterea ca parametru a valorii NULL se obine identificatorul


instanei curente. Dup apelul funciilor API, rezultatul returnat se gsete n
registrul EAX.
.data?
;...
hinst dd
?
;...
.code
;...
push 0
call GetModuleHandle
mov hinst,eax
;...

35

Obinerea liniei de comand se face cu funcia GetCommandLine. Obinerea


liniei de comanda nu este necesar dect dac programul prelucreaz parametrii din
linia de comand.
nregistrarea clasei fereastr se realizeaz avnd n vedere faptul c o
fereastr este ntotdeauna creat pe baza unei clase de fereastr. Aceasta identific
procedura de fereastr care prelucreaz toate mesajele transmise ctre fereastr. Pe
baza aceleiai clase se pot crea mai multe ferestre.
nainte de crearea ferestrei programului trebuie nregistrat clasa fereastr
prin apelul funciei RegisterClassEx ce are un singur parametru: un pointer la o
structur de tipul WNDCLASSEX.
Structura WNDCLASSEX are urmtorii membri:
WNDCLASSEX struc
cbSize
style
lpfnWndProc
cbClsExtra

dd
dd
dd
dd

?
?
?
?

cbWndExtra

dd ?

hInstance

dd ?

hIcon

dd ?

hCursor
hbrBackground

dd ?
dd ?

lpszMenuName

dd ?

lpszClassName

dd ?

hIconSm

dd ?

; dimensiunea structurii WNDCLASSEX


; stilul clasei fereastr
; pointerul la funcia fereastr
; informaii suplimentare
;pentru clas
; informaii suplimentare
;pentru fereastr
; identificatorul instanei
;curente
; identificatorul pictogramei
;asociata clasei
; cursorul asociat clasei
; culoarea de fundal a
;ferestrelor din clas
; pointer la irul cu denumirea
;meniului
; pointer la irul cu numele
;clasei
; identificatorul pictogramei
;aplicatiei

WNDCLASSEX ends

Al treilea i penultimul cmp (lpfnWndProc i lpszClassName) sunt cele


mai importante, ele coninnd adresa procedurii fereastr folosit de toate ferestrele
create pe baza acestei clase, respectiv numele clasei fereastr. Celelalte cmpuri
descriu caracteristicile tuturor ferestrelor create pe baza acestei clase.
nainte de apelul funciei RegisterClassEx trebuie iniializate cmpurile
variabilei de tip WNDCLASSEX. Iniializarea cmpurilor se realizeaz n
urmtoarea secven de cod:
;...
.data?
;...
wcex WNDCLASSEX <?>;var de tip structura clasa fereastra
NumeFer
db 'Programare sub Windows',0 ;Numele ferestrei

36
hinst
;...

dd

? ;identificatorul instantei curente

.code
;...
;completarea cimpurilor structurii fereastra
mov wcex.cbSize, size WNDCLASSEX
mov wcex.style, CS_VREDRAW or CS_HREDRAW or CS_DBLCLKS
mov wcex.lpfnWndProc, offset WndProc
mov wcex.cbClsExtra,0
mov wcex.cbWndExtra,0
push hinst
pop wcex.hInstance
;se incarca pictogtama, definita in fisierul .rc
push ID_ICON ;icon id
push hinst
call LoadIcon
mov wcex.hIcon,eax
;se incarca cursorul sageata standard
push IDC_ARROW
push NULL
call LoadCursor
mov
mov
mov
mov
mov

wcex.hCursor,eax
wcex.hbrBackground,COLOR_WINDOW+1
wcex.lpszMenuName,0
wcex.lpszClassName,offset NumeFer
wcex.hIconSm,0

Se observ c pentru iniializarea cmpurilor hIcon i hCursor ale structurii


WNDCLASSEX s-au apelat funciile LoadIcon i LoadCursor. Funcia
LoadIcon are prototipul:
HICON LoadIcon( HINSTANCE hInstance, // identificatorul
instantei aplicatiei
LPCTSTR lpIconName // numele identificatorul resursei
pictograma
);

Funcia returneaz un identificator al pictogramei asociat resursei


pictogram definit n fiierul de resurse. n program se transmite ID_ICON,
definit n fiierul de resurse.
Funcia LoadCursor:
HCURSOR LoadCursor( HINSTANCE hInstance, // identificatorul
instantei aplicatiei
LPCTSTR lpCursorName // numele/identificatorul resursei
cursor
);

37

returneaz identificatorul de cursor asociat cursorului definit n fiierul de resurse,


sau unuia din cursoarele standard. n aplicaie s-a utilizat cursorul standard de tip
sgeat, identificat prin IDC_ARROW. Atunci cnd se utilizeaz cursoare
standard, parametrul hInstance al funciei LoadCursor va fi 0.
Apelul funciei RegisterClassEx prin care se nregistreaz clasa fereastr:
.code
;...
;Inregistrarea clasei fereastra
push offset wcex
call RegisterClassEx
;...

n cazul n care nu s-a reuit nregistrarea clasei de fereastr, funcia


RegisterClassEx returneaz valoarea 0.

Sunt definite cteva clase standard de ferestre nregistrate: "BUTTON",


"EDIT", "LISTBOX" i altele, clase fereastr ce nu mai trebuie nregistrate, ele
avnd predefinite funciile fereastr i tratarea anumitor mesaje. Pe baza acestor
clase de ferestre standard se pot crea ferestre de acel tip, modificndu-se anumite
caracteristici, modul de funcionare rmnnd acelai.
Clasa fereastr definete caracteristicile generale ale unei ferestre,
permind folosirea acesteia pentru crearea mai multor ferestre. Cnd se creeaz o
fereastr cu funcia CreateWindowEx se pot specifica mai multe detalii despre
fereastra respectiv (cum ar fi titlul ferestrei, stilul acesteia, poziia, meniul asociat
i dimensiunea iniial).
Prototipul funciei CreateWindowEx este:
HWND CreateWindowEx(
DWORD dwExStyle,
//
LPCTSTR lpClassName, //
nregistrate
LPCTSTR lpWindowName,//
DWORD dwStyle,
//
int x,
//
int y,
//
int nWidth,
//
int nHeight,
//
HWND hWndParent,
//
printe
HMENU hMenu,
//
fereastra copil
HINSTANCE hInstance, //
programului
LPVOID lpParam
//
a ferestrei

stilul extins al ferestrei


pointer ctre numele clasei
pointer ctre numele ferestrei
stilul ferestrei
poziia orizontal a ferestrei
poziia vertical a ferestrei
limea ferestrei
nlimea ferestrei
indicator ctre fereastra
indicator ctre meniu sau
indicatorul instanei curente a
pointer ctre datele de creare

38
);

Funcia returneaz identificatorul ferestrei create.


Apelul funciei CreateWindowEx este:
.data?
;...
hwnd
dd ?
;identificatorul de fereastra
hinst
dd ?
;identificatorul instantei curente
hmeniu dd ?
;identificatorul meniului
;...
.const
;...
NumeFer
db 'Programare sub Windows',0 ;Numele ferestrei
NumeApp
db 'Programare in Win32 ASM',0;Numele aplicatiei
;...
.code
;...
;Crearea ferestrei
push ID_MENIU
push hinst
call LoadMenu
mov hmeniu,eax
push 0
push hinst
push hmeniu
push 0
push CW_USEDEFAULT
push CW_USEDEFAULT
push CW_USEDEFAULT
push CW_USEDEFAULT
push WS_OVERLAPPEDWINDOW
push offset NumeApp
push offset NumeFer
push WS_EX_OVERLAPPEDWINDOW
call CreateWindowEx
mov hwnd,eax

;
;
;
;
;
;
;
;
;
;
;
;

lpParam
hInstance
identificator meniu
identificator parinte
inaltime
latime
y
x
stilul
titlul ferestrei
numele clasei
stilul extins

;...

Pentru a asocia resursa meniu definit n fiierul de resurse se apeleaz


funcia LoadMenu ce are ca parametri identificatorul instanei curente a aplicaiei
i numele meniului definit n fiierul de resurse. Funcia returneaz identificatorul
de meniu asociat.
Dup apelul funciei CreateWindowEx, fereastra a fost creat ns nu a
fost i afiat pe ecran. Pentru afiarea ferestrei sunt necesare nc dou apeluri de
funcii: ShowWindow respectiv UpdateWindow.
Funcia ShowWindow are prototipul:

39
BOOL ShowWindow(HWND hWnd, // identificatorul ferestrei
int nCmdShow // modul de afiare a ferestrei);

Apelul funciei n cadrul programului:


push SW_SHOWNORMAL
push hwnd
call ShowWindow

Funcia UpdateWindow redeseneaz zona client a ferestrei. Prototipul acesteia


este:
BOOL UpdateWindow(HWND hWnd // identificatorul ferestrei
);

n program, apelul se realizeaz astfel:


push hwnd
call UpdateWindow

Dup apelul funciei UpdateWindow, fereastra devine vizibil pe ecran.


Programul trebuie s poat prelucra intrrile de la tastatur i de mouse.
Windows creeaz o coad de mesaje asociat fiecrui program. Cnd apare un
eveniment, acesta este transformat de Windows ntr-un mesaj care este pus n
coada de mesaje a programului. Mesajele sunt preluate din coada de mesaje prin
intermediul buclei de mesaje. n pseudocod bucla de mesaje se reprezint astfel:
Ateapt_mesaj:
Dac este apare un mesaj, preia mesajul
Dac mesajul este QUIT Atunci Ieire
Apeleaz TranslateMessage
Apeleaz DispatchMessage
Trimite mesajul ctre procedura fereastr
napoi la Ateapt_mesaj
Ieire

Funcia GetMessage preia un mesaj din coada de mesaje. Prototipul


funciei GetMessage:
BOOL GetMessage(
LPMSG lpMsg,
HWND hWnd,
UINT wMsgFilterMin,
UINT wMsgFilterMax
);

//
//
//
//

adresa structurii cu mesajul


identificatorul ferestrei
primul mesaj
al doilea mesaj

40

Primul parametru este un pointer la o structur de tip MSG. Windows


completeaz cmpurile structurii de mesaje cu urmtorul mesaj din coada de
ateptare. Structura este MSG este:
MSG STRUC
hwnd
message
wParam
lParam
time
pt

DWORD ? ; identificatorul ferestrei creia i


este destinat mesajul
DWORD ? ; identificatorul mesajului
DWORD ? ; parametru dependent de mesaj
DWORD ? ; parametru dependent de mesaj
DWORD ? ; momentul inserrii mesajului n coada
de mesaje
POINT <>; poziia mouse-ului n momentul
inserrii mesajului

MSG ENDS

Dac n cmpul message al structurii este transmis o valoare diferit de


WM_QUIT, funcia GetMessage returneaz o valoare diferit de zero. Mesajul
WM_QUIT determin ieirea din bucla de mesaje.
n cadrul buclei de mesaje se apeleaz dou funcii. TranslateMessage
transmite structura MSG sistemului de operare pentru convertirea unor mesaje de
la tastatur. Prototipul acesteia este:
BOOL TranslateMessage( CONST MSG *lpMsg // pointer la o
structur MSG
);

Funcia DispatchMessage, al crei prototip este:


LONG DispatchMessage(
CONST MSG *lpmsg // pointer ctre structura ce conine
mesajul
);

retransmite structura MSG sistemului de operare.


Windows trimite apoi mesajul ctre funcia fereastr corespunztoare n
vederea prelucrrii acestuia.
Bucla de mesaje este implementat astfel:
;Bucla de mesaje
start_bucla:
push 0
push 0
push NULL
push offset msg
call GetMessage
or eax,eax

;
;
;
;
;

wMsgFilterMax
wMsgFilterMin
0 - toate ferestrele
lpMsg
returneaza FALSE pentru WM_QUIT

41
jz iesire
push offset msg
call TranslateMessage
push offset msg
call DispatchMessage
jmp start_bucla

Terminarea programului se face prin apelul funciei ExitProcess. Prototipul


acesteia este:
VOID ExitProcess(UINT uExitCode
procesului
);

// codul de ieire al

Secvena de cod n care se face apelul funciei este:


push 0
;codul de iesire returnat de aplicatie
call ExitProcess

Funcia fereastr este responsabil de afiarea n zona client a ferestrei,


precum i de tratarea mesajelor provenite de la tastatur i mouse. Funcia
fereastr poate avea orice nume, iar un program pentru Windows poate avea mai
multe funcii fereastr, asociate ferestrelor definte n cadrul acestuia. Funcia
fereastr este ntotdeauna asociat unei clase fereastr.
Funcia fereastr are urmtorul prototip:
LRESULT WndProc(HWND hwnd, //identificatorul ferestrei
UINT msg, //identificatorul mesajului
WPARAM wparam, //parametru asociat mesajului
LPARAM lparam //parametru asociat mesajului
);

Parametrii funciei corespund primelor patru cmpuri ai structurii MSG.


Fiecare mesaj recepionat de fereastr este identificat printr-un numr (parametrul
msg al funciei fereastr). n fiierele antet din Windows acestora le corespund
identificatori prefixai de WM_ (de la window message)
Pentru tratarea diverselor mesaje se utilizeaz o instruciune switch pentru
determinarea mesajelor primite de fereastr i a modului de prelucrare a acestuia.
Atunci cnd prelucreaz un mesaj funcia fereastr trebuie s returneze valoarea
zero. Toate mesajele ce nu sunt prelucrate de funcia fereastr sunt transmise
funcie DefWindowProc. Prototipul funciei DefWindowProc este:
LRESULT DefWindowProc(
HWND hWnd,
UINT Msg,
WPARAM wParam,

// identificatorul ferestrei
// mesajul
// primul parametru al mesajului

42
LPARAM lParam
);

// al doilea parametru al mesajului

Un mesaj ce trebuie tratat este WM_DESTROY care este trimis atunci cnd
utilizatorul dorete s nchid fereastra. Mesajul este tratat standard, prin apelul
funciei PostQuitMessage, ce are prototipul:
VOID PostQuitMessage(
int nExitCode
);

// codul de ieire

Implementarea funciei fereastr, care trateaz mesajul WM_DESTROY


este:
WndProc proc
;parametrii de pe stiva sunt:
;esp+4 --> hwnd
;esp+8 --> msg
;esp+12 --> wParam
;esp+16 --> lParam
cmp dword ptr [esp+8],WM_DESTROY
je msg_wm_destroy
jmp DefWindowProc
msg_wm_destroy:
push 0
call PostQuitMessage
xor
eax,eax
ret 16
WndProc endp

Celelalte mesaje sunt tratate de funcia standard.


n programul scris n limbaj de asamblare nu are importan dac numele
funciei fereastr este WndProc, acest lucru fiind la latitudinea programatorului.

25.6 Asamblarea i editarea de legturi


Pentru realizarea programului s-a utilizat MASM32. Acesta se gsete la
adresa http://www.pbq.com.au/home/hutch/masm.htm.
Asamblarea programului surs se realizeaz astfel:
ml /c /coff /Cp program.asm
Dac se folosesc fiiere de resurse, acestea trebuiesc compilate cu un
compilator de resurse (de exemplu rc.exe), obinndu-se un fiier de resurse obiect,
fiier ce va fi link-editat mpreun cu fiierul obiect al programului. Editarea de
legturi se realizeaz utiliznd urmtoare linie de comand:

43

link /SUBSYSTEM:WINDOWS /LIBPATH:c:\masm32\lib program.obj

25.7 Exemplu de program Win32


n continuare se prezint un program Windows, program care afieaz o
fereastr, n funcia fereastr tratndu-se mesajele WM_COMMAND (alegerea
unei opiuni din meniu), WM_LBUTTONDOWN (executarea unui clic de mouse
n zona client a ferestrei) i WM_DESTROY (la nchiderea ferestrei).
Fereastra are asociat un meniu avnd submeniul "Fisiere" cu o un singur
articol: "Iesire" i submeniul "Help" cu articolul "Despre...". Cnd se selecteaz
"Iesire" se va nchide fereastra, iar cnd se selecteaz "Despre..." se afieaz o
csu de dialog.
.386
.model flat, stdcall
option casemap :none
include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include res.equ
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
.data
.const
NumeFer
ferestrei
NumeApp
aplicatiei
MesajDespre
Mesaj1

db

'Programare sub Windows',0

;Numele

db

'Programare in Win32 ASM',0

;Numele

db
db

'Paul Pocatilu, 1999',0


'Mouse click',0

.data?
wcex WNDCLASSEX <?>
msg
MSG <?>
hwnd
dd ?
hinst
dd ?
hmeniu dd ?

;var de tip structura clasa fereastra


;Var de tip MSG
;identificatorul de fereastra
;identificatorul instantei curente
;identificatorul de meniu

.code
start:
;obtinerea hInstance

44
push 0
call GetModuleHandle
mov hinst,eax
;completarea campurilor structurii fereastra
mov wcex.cbSize, size WNDCLASSEX
mov wcex.style, CS_VREDRAW or CS_HREDRAW or CS_DBLCLKS
mov wcex.lpfnWndProc, offset WndProc
mov wcex.cbClsExtra,0
mov wcex.cbWndExtra,0
push hinst
pop wcex.hInstance
;se incarca iconul, definit in fisierul .rc
push ID_ICON ;icon id
push hinst
call LoadIcon
mov wcex.hIcon,eax
;se incarca cursorul sageata standard
push IDC_ARROW
push NULL
call LoadCursor
mov
mov
mov
mov
mov

wcex.hCursor,eax
wcex.hbrBackground,COLOR_WINDOW+1
wcex.lpszMenuName,0
wcex.lpszClassName,offset NumeFer
wcex.hIconSm,0

;Inregistrarea clasei fereastra


push offset wcex
call RegisterClassEx
;s-a inregistrat fereastra?
or eax,eax
jz iesire
;Crearea ferestrei
push ID_MENIU
push hinst
call LoadMenu
mov hmeniu,eax
push
push
push
push
push
push
push

0
hinst
hmeniu
0
CW_USEDEFAULT
CW_USEDEFAULT
CW_USEDEFAULT

;
;
;
;
;
;
;

lpParam
hInstance
identificator meniu
identificator parinte
inaltime
latime
y

45
push CW_USEDEFAULT
push WS_OVERLAPPEDWINDOW
push offset NumeApp
push offset NumeFer
push WS_EX_OVERLAPPEDWINDOW
call CreateWindowEx
mov hwnd,eax

;
;
;
;
;

x
stilul
titlul ferestrei
numele clasei
stilul extins

;se afiseaza fereastra


push SW_SHOWNORMAL
push hwnd
call ShowWindow
;se actualizeaza zona client
push hwnd
call UpdateWindow
;Bucla de mesaje
start_bucla:
push 0
push 0
push NULL
push offset msg
call GetMessage
or eax,eax
jz iesire

;
;
;
;
;

wMsgFilterMax
wMsgFilterMin
0 - toate ferestrele
lpMsg
returneaza FALSE pentru WM_QUIT

push offset msg


call TranslateMessage
push offset msg
call DispatchMessage
jmp start_bucla
iesire:
;Terminarea programului
push 0
; codul de iesire returnat de aplicatie
call ExitProcess
;Functia Fereastra
WndProc proc
cmp dword ptr [esp+8],WM_COMMAND
je msg_wm_command
cmp dword ptr [esp+8],WM_DESTROY
je msg_wm_destroy
cmp dword ptr [esp+8],WM_LBUTTONDOWN
je msg_wm_lbuttondown
jmp DefWindowProc
msg_wm_command:
;se testeaza alegerea optiunilor din meniu

46
cmp dword ptr [esp+12],ID_FISIERE_IESIRE
je msg_wm_destroy
cmp dword ptr [esp+12],ID_HELP_DESPRE
je help_despre
xor eax,eax
ret 16
msg_wm_lbuttondown:
;s-a facut click in zona client a ferestrei
;se afiseaza o casuta de dialog
;avind ca titlu NumeApp si mesaj Mesaj1
push MB_OK
push offset NumeApp
push offset Mesaj1
push NULL
call MessageBox
xor eax,eax
ret 16
help_despre:
;s-a ales optiunea Despre... din meniul Help
;se afiseaza o casuta de dialog
;avind ca titlu NumeApp si mesaj MesajDespre
push MB_OK
push offset NumeApp
push offset MesajDespre
push NULL
call MessageBox
xor eax,eax
ret 16
msg_wm_destroy:
;s-a inchis fereastra
push 0
call PostQuitMessage
xor
eax,eax
ret 16
WndProc endp
end start

Fiierul de resurse asociat are urmtorul coninut:


#define ID_ICON 101
#define ID_MENIU 102

ID_ICON ICON "MAIN.ICO"


ID_MENIU MENUEX
BEGIN

47
POPUP "&Fisiere", , , 0
BEGIN
MENUITEM "&Iesire", ID_FISIERE_IESIRE
END
POPUP "&Help", , , 0
BEGIN
MENUITEM "&Despre...", ID_HELP_DESPRE
END
END

La lansarea n execuie, programul va afia o fereastr, dimensiunile i


acesteia fiind generate de sistemul Windows (prin utilizarea
CW_USEDEFAULT). Prin apsarea butonului stng al mouse-ului n zona client a
ferestrei, prin tratarea evenimentului WM_LBUTTONDOWN se va activa o csu de
dialog. nchiderea ferestrei se realizeaz fie n mod clasic, fie prin alegerea opiunii
Iesire din meniul Fisiere.
poziia

BIBLIOGRAFIE
[ABEL95] IBM PC Assembly Language and Programming 3rd Edition Prentice Hall International, Inc, New Jersey, 1995
[ATHA92] Irina Athanasiu, Alexandru Panoiu Microprocesoarele
8086, 286, 386 Editura Teora, Bucureti, 1992
[BARK90] Nabajyoti Barkakati, The Waite Group's Microsoft Macro
Assembler Bible, SAMS, Carmel Indiana, 1990
[BETH87] RWMc Beth, J. R. Ferguson, IBM Assembler John Wiley &
Sons, New York, 1987
[BREY90] Barry B. Brey, 8086/8088, 80286, 80386 and 80486
Assembly Language Programming, Macmillan Publishing
Company, New York, 1990
[BRUM88] Penn Brumm, Don Brumm, 80386 Assembly Language A
Complete Tutorial and Subroutine Library TAB Books Inc,
Blue Ridge Summit, 1988
[BUY96]
Barry Buy, Programming the 80286, 80386, 80486 and
Pentium - Based Personal, Prentice Hall Englewood Cliffs,
New Jersey, 1996
[CAPR91] Vlad Cprariu, Sisteme de operare DOS - Funcii Sistem,
Microinformatica, Ediia a III-a, Cluj Napoca, 1991
[CATO74] I. Catona, I. Teodorescu, C. Popescu, Sistemul Felix C 256, Limbajul ASSIRIS, Editura Academiei, Bucureti,
1974
[Coff87]
James W. Coffron, Programming the 8086/8088, Ed.
Kleidarifmos, Athens, 1987

48

[COHE94] Le
microprocesseur
Pentium
Architecture
et
programmation, Armand Colin, Paris, 1994
[CUOR93] Sen - Cuo Ro Shean - Chuen Her, i386/i486 Advanced
Programming, Van Nosteand Reinhold, New York, 1993
[DAVI91] A. Davidoviciu, Gh. Dodescu, coordonatori MIX i
MACRO, vol. 2, Programarea n limbajul MACRO, Editura
Tehnic, Bucureti, 1991
[DETM90] Richard C. Detmer, Fundametals of Assembly Language
Programming, PC Heath Comp., Lexington Masschusetts,
1990
[DIAC75] G. Diaconescu, I. Lungu, Assembler, Lito ASE, Bucureti,
1975
[DIMO92] Dimopoulos
K.
Z.,
Paraskevopoulos
A.S.80x86
Architictonici schediasi & Programatismos Papasotiriu Ed.
Athens, 1992
[DORF90] Len Dorfman, Object Oriented Assembly Language
Windcrest, 1990 Mc Graw Hill Inc. New York
[DORF90a] Len Dorfman, Structured Assembly Language, Windcrest
Books Blue Ridgs Summit, 1990
[DOVI91] A. DOVIDOVICIU, Gh. DODESCU Mix si Macro (vol. 2)
Programarea in limbajul MACRO Editura Tehnica,
Bucureti, 1991
[FITZ86]
Robert M. Fitz, Larry Crokett, Universal Assembly
Language, TAB Books Inc. Blue Ridge Summit PA 17214,
1986
[GHEO92] MARIAN GHEORGHE, BADICA COSTIN, PATRASCOIU
OCTAVIAN Limbaje de asamblare MACRO-11, Intel
8086/88, Lito Universitate, Craiova, 1992
[GILL94] Frame van Gilluwe, The Undocumented PC, Addison
Wesley Publishing Company Reading, 1994
[GURT89] A.L. Gurtovtev, S.V. Gudimenko Programi dlia
microprotessorov, Editura Visaisaia Scola, Minsk, 1989
[HABI88] Stanley
Habib
Microprogramming
and
firmware
engineering methods, van Nostrand Reinhold, New York,
1988
[HALL80] Douglas V. Hall, Microprocessors and interfacing
Programming and hardware, Mc. Craw Hill International
New York, 1980
[HAWK81] Gerry Kan, Danny Hawkins, Lance Leventhal 6800
Assembly Language Programming, Osborne, California,
1981
[HOLZ87] Steven Holzner, Advanced Assembly Language on the IBM

49

PC, Brady - New York, 1987


[HOLZ90] Steven Holzer, Assembly Language for Pascal, Ed. Brady,
New York, 1990
[HOLZ96] Holzner, Steve Advanced Visual C++ 4, M&T Books,
New York 1996
[HORS91] Gordon Horsington Programming in ANSI standard C,
Sigma Press, Wilmslow, England, 1991
[iAPX83] ***** iAPX 286. Programmer's Reference Manual, Intel
Product Guide, Intel Literature Dept., Santa Clara 1983
[IRVI93]
KIP R. IRVINE, Assembly Language for the IBM PC
Mcmillan Publishing Company, New York, 1993
[IVAN96] Ion Ivan , Cristian Codreanu, Optimizarea programelor
asembler, ASE Departamentul de Informatic
Economic, Bucureti, 1996
[IVAN97] Ion Ivan Designul limbajelor de asamblare, Revista
Informatica Economic, nr. 1/1997
[IVAN98] Ion Ivan, Cristian Codreanu Optimizarea programelor
assembler, Revista Informatica Economic, nr. 6/1998
[IVAN98a] Ion Ivan, Marian Dardala, Gabriel Sutac, Valentin
Dragomir, Referirea datelor in structuri complexe prin
proceduri assembler, Informatica Economica, vol. III, nr. 7,
Trim III/1998
[IVAN99] Ion Ivan, Adrian Licuriceanu, Sebastian Tcaciuc, Gheorghe
Lupu, Aplicatii orientate obiect in limbaj de asamblare,
"Studii si cercetari de calcul economic si cibernetica
economica", nr 3/1999, Bucuresti, 1999
[JONE91] D.S. Jones 80x86 Assembly Programming, Oxford
University Press, New York, 1991
[KACM95] Gary Kacmarcik, Optimizing Power PC code Programming the Power PC chip in Assembly Language,
Addison Wesley Publishing Company Massachusetts,
1995
[LEVE87] Lance Leventhal 80387 Programming guide, Bantan
Books, Toronto, 1987
[LIUY86] Liu Yu-Cheng Microcomputer Systems: the 8086/8088,
Family Prentice Hall Englewood Cliffs, New Jersey, 1986
[LUCA85] Dan Luca Serbanuta, Valentin Cristea, Claudiu Popescu
Limbajul MACRO-11. ndrumar de laborator, IPB,
Bucureti, 1985
[LUPU82] Cristian Lupu, Vlad Tepelea, Emil Purice Microprocesoareaplicaii, Editura Militar, Bucureti, 1982
[LUPU82] Cristian Lupu, Vlad epelea, Emil Purice Microprocesoare -

50

[MARI92]

[MASM78]

[MASM86]

[MAST95]
[MATS76]
[MCBE87]
[MORG84]
[MORRIS]
[MUNT76]
[MURR88]
[MUSC96]
[NORT89]
[PETZ98]
[PRET75]

[RICH94]

[RODE96]

[ROC77]

[RUNN88]

Aplicaii, Editura Militar, Bucureti, 1982


Marian Gheorghe, Badica Costin, Ptrcoiu Octavian
Limbaje de asamblare Macro 11 Intel 8086/88, ndrumar
de Laborator, Lito Universitatea Craiova, 1992
***** MCS-86tm Macro Assembly language reference
manual (manual order number 9806640-02), Intel
Corporation, Santa Clara, 1978
***** MStm - DOS 3.1 Macro ASSEMBLER Manual User's
guide Masm Reference Manual, NEC Corporation 1986,
Printed in Japan
* * * , ASSEMBLY Language Master Class, Wrox Press
Ltd., Birmingham, 1995
Y. Matsumoto AA: Assembly Automation 1302XC 13O1XC
Robert W. Mc.Beth, J. Robert Ferguson IBM ASSEMBLER,
John Wiley & Sons, New York, 1987
Morgan Cristopher L., Assembly Language Routines for
the IBM PC & T, New York, Waite Group's, 1984
A.J. T. Davie, R. Morrison Recursive descent compiling,
University of St. Andrews, Scotland
E. Munteanu, V. Costea, N. Mitrov Programare in limbajul
de asamblare ASSIRIS, Editura Tehnic, Bucureti, 1976
Assembly Language Programming under OS/2, Osborne
Mc Gran Hill Berkley, 1988
Gheorghe Musc Programare n limbaj de asamblare,
Editura Teora, Bucureti, 1996
Peter Norton, John Socha, Peter Norton's Assembly
Language Book for the IBM PC, Brady New York, 1989
Petzold, Charles, Yao, Paul Programare n Windows 95,
Editura Teora, Bucureti, 1998
T. W. Prett Programming languages design and
implementation, Prentice Hall Inc. Englewood Cliffs NJ,
1975
Richard P. Paul, SPARC Architecture Assembly Language
Programming & C., Prentice Hall, Englewood Cliffs, New
Jersey, 1994
Liviu Rodean, Optimizarea programelor elaborate n
limbaje de asamblare, Lucrare de licen, ASE - Bucureti,
1996
V. Roca, C. Apostol, I. Ivan, I. Roca, Limbaje de
programare, Limbajul ASSIRIS, vol 1, 2, Lito ASE,
Bucureti, 1977
Wiliam C. Runnion, Structured Programming in Assembly

51

[SACH93]
[SALE95]

[SANC90]

[SANC94]
[SANC95]

[SCAN83]

[SCAN87]

[SCAN88]
[SCHA93]
[SCHM95]
[SENC93]
[SERA87]

[SERB85]

[SOCE75]

[SOMN92]
[STRU92]

Language for IBM PC, PWS - Kent Publishing Company,


Boston, 1988
Holger SCHAKEL, Programmer en Assembleur sur PC,
Edition Micro Application, Paris, 1993
Cristian Salescu, Implementarea mecanismelor de
recursivitate n limbaje de asamblare Lucrare de licen ASE, Bucureti, 1995
Julio Sanchez, Assembly Language tools and techniques
for the IBM Micro computers, Prentice Hall Englewood
Cliffs, New Jersey, 1990
Julio Sanchez, Maria P. Canton, PC Programming Hand
book Mc Gron Hill Inc, New York, 1994
Julio Sanchez, Maria P. Canton, Numerical Programming
the 387, 486 and PentiumTM, Mc Graw Hill, Inc., New
York, 1995
Leo J Scanlon, IBM PC & XT Assembly Language A guide
for programmers, Brady Communications Company Inc.,
New York, 1983
Leo J Scanlon, Assembly Language Subroutines for MSDOS Computers, Blue Ridge Summit PA TAB Boccks,
1987
Leo J. Scanlon, 8086/8088/80286, Assembly Language A
Brady Book, New York, 1988
Holger Schakel Programmer in assembleur sur PC, Edition
MicroAplication, Paris, 1993
Michael L. Schmit, Pentiumtm Processor Optimization tools
AP Professional, New York, 1995
Sen-Cuo Ro, Shean Chuen Hen i386/i486 Advanced
Programming, Van Nostrand Reinhold, New York, 1993
Luca Dan erbnai, Limbaje de asamblare i asambloare
n Limbaje de programare i compilator, Editura Academiei,
Bucureti, 1987
Luca Dan erbnai, Valentin Cristea, Claudiu Popescu,
Limbajul MACRO-11, ndrumar de Laborator, Lito IPB,
Bucureti, 1985
A. Soceneantu, G. Gavrilescu, T. Ilin Limbaje de asamblare
pentru calculatoarele electronice numerice. Asambloare,
Editura Facla, Timioara, 1975
Dan Somnea, Vldu Teodor, Programarea n Assembler,
Editura Tehnic, Bucureti, 1992
Crian Strugaru, Mircea Popa, Microprocesoare pe 16 bii,
Editura TM, Timioara, 1992

52

[SWAN95] Tom Swan, Mastering Turbo Assembler, SAMS Publishing


Indianapolis, 1995
[TASM88] ***** Turbo ASSEMBLER version 2.0 User's guide, Borland
International Inc., Green-Hils road, Scotts-Valley, 1988
[TASM99] ***** Turbo ASSEMBLER 3.0 User's guide, Borland
International Inc., Scotts-Valley, 1988
[THOR90] Michael Thorne, Computer Organisation and Assembly
Language
Programming,
The
Benjamin
Cummig
Publishing Comp. , Bonn, 1990
[TISC94] Michael Tischer, La Bible PC 5e dition, Edition Micro
Application, Paris, 1994
[TRIE90] Triebel A Walter, Singh Avtar, Microprocesorul 8086
Arhitectur, software i tehnici de interfaare, Editura
Mitron, Timioara, 1990
[TURL88] James L. Turley, Advanced 80386 Programming
techniques , Osborne Mc Graw Hill Ber Kley, 1988
[WYAT87] Allen L. Wyatt, Using Assembly Language, QUE
Corporation, Carmel, Indiana, 1987
[WYAT92] Allen L. Wyatt Jr., Advanced Assembly Language, QUE
Corporation Carmel, 1992
[YUCH86] YU Cheng Liu, Glen A. Gibson Microcomputer Systems
The 8086/8088 Family Arhitecture Programming and
Designe Prentice Hall International, Inc. New Jersey, 1986
[******]
http://win32asm.cjb.net, " Iczelion's Win32 Assembly
HomePage"
[******]
http://www.pbq.com.au/home/hutch/masm.htm, "MASM32"

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