Cuprins
1. Introducere ............................................................................................................
3
2. Caracteristici ale limbajelor de programare .................................................
5
3. Definirea problemei .............................................................................................
7
4. Alegerea structurilor şi tipurilor de date utilizate .....................................
10
5. Construirea algoritmilor şi a schemelor logice ..............................................
11
6. Proiectarea structurii produsului software ...................................................
16
7. Textul sursă al programului ...............................................................................
18
8. Crearea documentaţiei aferente produsului program .................................
28
9. Testare şi implementare .....................................................................................
31
10. Analiză cantitativă şi calitativă .......................................................................
35
11. Concluzii .................................................................................................................
37
Anexa 1 ........................................................................................................................
39
Anexa 2 ........................................................................................................................
48
Anexa 3 ........................................................................................................................
49
Bibliografie .................................................................................................................
51
1. Introducere Disciplina LIMBAJE DE ASAMBLARE are ca obiectiv prezentarea limbajului de asamblare si modului de utilizare a acestuia în diferite aplicaţii. Limbajul de asamblare permite înţelegerea la nivel de amănunt a ceea ce se întâmpla în realitate într-un calculator. Familiarizarea cu un asemenea limbaj este mai mult decât benenefică pentru un programator, contribuind la eficienţa programelor dezvoltate indiferent de limbajul utilizat. Există mai multe motive pentru care programarea în limbaj de asamblare este necesară. Codul executabil generat din programe scrise în limbaje de asmblare – ASM – se execută în general foarte rapid. Unele module de program trebuie implementate în ASM datorită acestei viteze de lucru. Uneori, o parte a unui program este scrisă într-un limbaj de nivel înalt, iar modulele critice sunt scrise ca proceduri ASM, apelate la rândul lor de modulele de nivel înalt. Există situaţii în care este nevoie de acces direct la dispozitivele de intrare/ieşire sau la locaţii fizice de memorie, iar aceste operaţii nu pot fi executate în unele limbaje de nivel înalt. De exemplu, la calculatoare personale, programele TSR şi rutinele de tratare a întreruperilor sunt aproape totdeauna scrise în ASM. Pe scurt, limbajul de asamblare oferă viteze de execuţie şi acces la hardware care nu pot fi disponibile (cel mai adesea) în limbaje de nivel înalt. Un alt aspect important este cel al dezvoltării de programe pentru echipamente dedicate. Nu toate programele executabile sunt destinate calculatoarelor de uz general. Dezvoltarea masivă a microprocesoarelor a făcut ca acestea să controleze în prezent funcţionarea celor mai diverse dispozitive tehnice, de la carduri bancare până la echipamente de control industrial sau pentru comanda avioanelor. De asemenea există şi un puternic rol formativ al programării în limbaj de asamblare. Un programator nu ajunge niciodata la un nivel superior, dacă nu trece prin dezvoltarea de programe ASM. Programatorul care cunoaşte principiile de realizare a limbajelor de asamblare va trece cu uşurinţă de la utilizarea corectă a unui limbaj la altul, deşi aparţin unor generaţii diferite. Limbajul de asamblare defineşte operaţii elementare, iar programatorul gestionează toate resursele programului. Există posibilitatea de a construi secvenţe de instrucţiuni şi de a urmări din aproape în aproape prelucrările şi rezultatele corecte sau eronate. Pentru fiecare rezultat există posibilitatea de a descrie
3
mecanismul de realizare şi de a identifica adevăratele cauze care duc la erori. Pe parcursul pregătirii sunt predate cursuri şi se efectuează lucrări practice, iar în final trebuie elaborat un proiect care condiţionează intrarea în examen. Proiectul are ca obiectiv realizarea unei aplicaţii care permite studentului din anul trei de la Specializarea Informatică Economică, Facultatea de Cibernetică, Statistică şi Informatică Economică să însuşească şi să utilizeze în mod eficient limbajul de asamblare în soluţionarea problemei alese. Pentru a elabora proiectul se parcurg următorii paşi: • se defineşte problema de realizat; • se construieşte modelul care stă la baza efectuării calculelor; • se identifică datele care sunt folosite pentru rezolvarea problemei; • se elaborează structura produsului software; • se stabilesc proprietăţile pe care trebuie să le îndeplinească datele; • se elaborează schemele logice; • se scriu module de program care se asamblează; • se testează produsele software; • se procedează la implementare. Acest ghid furnizează atât elemente privind tehnologia de elaborare a proiectului, cât şi modalităţi rezolvare a problemelor şi de analiză a rezultatelor. Ghidul se încheie cu o listă orientativă de proiecte propuse, care se constituie într-un punct de plecare la definirea şi realizarea aplicaţiei, individualizate la nivelul fiecărui student. Autorii sunt recunoscători tuturor celor care prin sugestii şi observaţii contribuie la îmbunătăţirea ediţiei viitoare a acestui ghid. Autorii.
4
2. Caracteristici ale limbajelor de asamblare În cadrul unui proiect la disciplina „Limbaje de Asamblare” problema de soluţionat este aleasă de student. O problemă se deosebeşte de alta prin nivelul de complexitate, nivel care se regăseşte prin dimensiunea produsului software, exprimată ca număr de linii sursă. La rezolvarea problemei trebuie să se ţină cont de caracteristicile limbajelor de asamblare. Limbajele de programare evoluate posedă implementare la nivel de compilatoare, care realizează: • alocări automate de memorie pentru operanzii utilizaţi, dar nedefiniţi în program; • iniţializări la definire a operanzilor; • semnalarea neconcordanţelor între natura operanzilor sau a incompatibilităţilor, cu efectuarea corecţiilor celor mai probabile sau prin eliminarea de instrucţiuni din secvenţă; • conversiile necesare pentru a asigura gradul de omogenitate necesar al prelucrărilor. Limbajele de asamblare presupun existenţa la dispoziţia programatorului a tuturor resurselor sistemului de calcul. Acest lucru înseamnă că programatorul este obligat: • să definească în program toţi operanzii; • să iniţializeze toate zonele de memorie; • să asigure omogenitatea operanzilor în vederea efectuării corecte a operaţiilor de calcul. În programele scrise în limbaj de asamblare se execută exact operaţiile pentru care există instrucţiuni. Dacă un operand nu este definit dar este utilizat, asamblorul semnalează acest eveniment ca fiind major şi nu va proceda la trecerea la etapele ulterioare asamblării. Dacă un operand nu a fost iniţializat, se va lucra cu conţinutul existent al zonei de memorie. Simplitatea programului asamblor nu permite analiza corelaţiilor dintre instrucţiuni în aşa fel încât să semnalizeze că se folosesc variabile neiniţializate. De asemenea în programele scrise în limbaj de asamblare se află instrucţiuni dispuse una după alta, care formează secvenţe lineare. Apariţiile instrucţiunilor de salt întrerup caracterul liniar al programelor. 5
Limbajele de programare sunt structurate în definiri de tipuri de operanzi şi referiri de operanzi în vederea prelucrării. Contextul de prelucrare începe cu definirea operanzilor. Între modul de definire şi modul de utilizare există restricţii pe care programatorul trebuie să le respecte. Orice program foloseşte operanzi şi operatori. Limbajul de asamblare permite structurarea distinctă, pe segmente a datelor, stivei şi a codului executabil. Mai mult, există posibilitatea de a defini o variabilă oriunde în segmente şi de a o referi cu semnificaţia pe care contextul (cod instrucţiune, poziţie în lista de operanzi) îl dă. În limbajele de asamblare sunt definite modalităţi variate de referire a operanzilor (adresare directă, indirectă, indexată, bazată etc.). Octeţi sunt puşi în corespondenţă cu identificatorii şi cu etichete. Întrucât o instrucţiune efectuează o operaţie simplă şi instrucţiunile se organizează în secvenţe, programul scris în limbajul de asamblare este văzut ca secvenţe şi nu ca expresii. Mai mult, limitele de poziţionare a instrucţiunilor în secvenţe reduc gradul de compactare a programelor.
6
3. Definirea problemei Se doreşte evidenţierea migrări populaţiei pentru un număr dat de judeţe. Se doreşte calculul pentru fiecare judeţ în parte a unor indicatori care să evidenţieze migraţia populaţiei. Numărul judeţelor este limitat la 5 iar numele judeţelor se preia dintr-un masiv sau fişier sau se citeşte de la tastatură. Datele de ieşre se memorează într-un fişier text şi pentru fiecare judeţ se afişează în valoare absolută numărul populaţiei care a emigrat, imigrat şi sporul înregistrat – numărul populaţiei de la începutul perioadei de calcul plus numărul imigranţilor minus numărul emigranţilor. Se ia în considerare o singură perioada de calcul. În primul rând se stabilesc ieşirile. Acestea sunt: • sub forma unui număr; • sub forma unui şir de numere; • sub forma unui tabel; • sub forma mai multor tabele cu structuri diferite; • sub formă de fişiere; • sub formă grafică. Precizând exemple de control ce conţin valori numerice se procedează la clasificarea situaţiilor frecvent întâlnite şi la identificarea excepţiilor. Toate acestea trebuie să fie regăsite în tabele de date, întrucât la testare programul foloseşte exclusiv datele din aceste tabele. Pentru a vedea cum programul execută transformările necesare asupra datelor de intrare se testează toate variantele care există în aceste tabele de date. Pe baza datelor introduse se obţin conform algoritmului o serie de rezultate care sunt confruntate apoi cu rezultatele produse de program. În al doilea rând, se stabilesc date iniţiale, ceea ce se furnizează ca intrări de către program. Se stabilesc modalităţi de obţinere (măsurători, documente primare, alte surse ce furnizează date). În al treilea rând, se stabilesc formulele de calcul, care sunt, de regulă, sub forma: n
S = ∑ xi ; i
n
S = ∑ xi ⋅ p i ; i
7
De asemenea , se impun condiţii pentru includerea elementelor în formule: n
S = ∑ xi i xi > 0
sau n
S = ∑ xi i xi < 0
Este important să se stabilească: • numărul de componente; • variabilele, modul de regrupare. Trebuie văzut dacă toate ieşirile (rezultatele) se obţin folosind toate datele de intrare. Există următoarele situaţii care se întâlnesc în definirea problemei:
•
Problemă bine definită. Rezultatele se obţin din date. intrări: ieşiri:
n, x1, x2, ..., xn x n
formulă:
•
x=
∑x i =1
i
n
Problemă subdefinită. Se doresc multe rezultate şi nu sunt suficiente date de intrare. intrări: ieşiri:
n, x1, x2, ..., xn x n
formulă: lipsesc:
x=
∑x i =1
i
fi
n f1,f2, ..., fn 8
•
Problemă supradefinită. Se găsesc mai multe date de intrare, şi nu sunt folosite. intrări: ieşiri:
n, x1, x2, ..., xn f1,f2, ..., fn y1,y2, ..., yn x n
formulă: se găsesc în plus:
x=
∑x i =1
i
fi
n y1,y2, ..., yn
Situaţia în care problema este bine definită este ideală. În cazul în care problema este subdefinită se adaugă date de intrare, iar în cazul în care problema este supradefinită se pot şterge date de intrare sau adăuga rezultate. Pentru o înţelegere mai bună a problemei se consideră un caz practic. Fie lista judeţelor memorate într-un tabel în modul următor: Tabel 1. Exemplu de lista judeţelor utilizate în program. Denumire judeţ/Prescurtare Ilfov (IF) Constanţa (CT) Galaţi (GL) Cluj (CJ) Timiş (TM)
Cod zecimal
Cod hexazecimal
0 1 2 3 4
00 01 02 03 04
În tabelul 2 sunt prezentate datele cu care se operează în calculul indicatorilor care evidenţiază migraţia populaţiei.
9
4. Alegerea structurilor şi tipurilor de date utilizate Se ţine cont că se operează cu date privind migraţia populaţiei şi atunci majoritatea datelor de intrare şi ieşire se abstractizează în masive uni şi bi-dimensionale precum şi a fişierelor binare şi text. Se efectuează alegerea tipurilor de date utilizate în program. Este evident că deoarece se lucrează cu număr de populaţie, matricele care memorează dinamica populaţiei la o anumită perioada de timp vor avea elemente de tip întreg. Mai mult se vor elabora programe pentru procesoare standard (Intel, AMD) de PC-uri şi deci se vor folosi limbajele de asamblare puse la dispoziţie de acestea, adică se vor folosi tipurile de date pe care acestea le recunosc. Pentru numere întregi alegerea tipului de date se face astfel: • dacă numerele aparţin intervalului [-128, +127] sau [0, 255], se alege memorarea pe un octet (1 byte), folosinduse descriptorul db (define byte); • dacă numerele aparţin intervalului [-32768, +32767] sau [0, 65535], se alege memorarea pe doi octeţi (2 bytes – 1 cuvânt), folosindu-se descriptorul dw (define word); • dacă numerele aparţin intervalului [-231-1, +231-1] sau [0, 232-1], se alege memorarea pe patru octeţi (4 bytes – 2 cuvinte), folosindu-se descriptorul dd (define double [word]); • dacă numerele aparţin intervalului [-263-1, +263-1] sau [0, 264-1], se alege memorarea pe opt octeţi (8 bytes – 4 cuvinte), folosindu-se descriptorul dq (define quad [word]); În mod normal, operaţiile se efectuează pe maximum 16 biţi. Pentru lucru cu valori mai mari, se folosesc registrele extinse, pe 32 de biţi. În acest caz pentru că valorile se referă la numărul populaţiei din câteva judeţe – valori de maxim câteva zeci de milioane – se alege folosirea tipului de date pe patru octeţi, folosind descriptorul dd şi se va lucra cu registrele extinse ale microprocesorului.
10
5. Construirea algoritmilor şi a schemelor logice Se memorează într-un vector de cinci elemente prescurtările judeţelor. Fiecare element din vector are 2 octeţi pentru a memora prescurtările. De exemplu pentru cinci judeţe: Ilfov, Constanţa, Galaţi, Cluj, Timiş se memorează în vector (vectjud) astfel: vectjud[0] = IF, vectjud[1] = CT, vectjud[2] = GL, vectjud[3] = CJ, vectjud[4] = TM. Pentru o perioadă dată – perioadă fixă de un an – se memorează într-o matrice date despre populaţia din cele 5 judeţe în modul următor – se reconstruieşte Tabelul 2 dar valorile memorate sunt în hexazecimal pe patru octeţi adică 8 cifre hexazecimale: Tabel 3. Exemplu de date privind migraţia populaţiei – date reprezentare hexazecimală. Judeţ/ Judeţ
00
01
00 (IF)
00 20 16 E6 00 00 7D 00 00 00 88 B8 00 00 4E 20 00 00 52 08
00 00 00 00 C3 03 50 E8 00 00 06 00 41 0F 90 A0 00 00 00 05 2E E1 E0 2F 00 00 00 00 06 1B A4 BC 00 00 00 00 00 00 78 69
01 (CT)
02 (GL)
03 (CJ)
04 (TM)
02
03
04
00 00 07 D0 00 00 00 32 00 00 00 00 00 05 57 5A 00 00 00 D2
00 00 06 A4 00 00 00 64 00 00 00 78 00 00 2A F8 00 05 8A 70 11
Interpretarea tabelului 3 este identică cu intrepretarea tabelului 2. Trebuie efectuate calculele anumitor indicatori pentru a evidenţia migraţia populaţiei: • Indicator 1: numărul maxim de emigranţi dintr-un anumit judeţ, se calculează ca maximul elementelor de pe linia matricei mai puţin elementul de pe diagonala principală; IND1i = max (matrdate[i ][ j ]) , unde i ∈ {0,4} , i ≠ j şi i j∈{0 , 4}
reprezintă judeţul pentru se calculează indicatorul iar matrdate este matricea în care sunt memorate datele din tabelul 3. De exemplu pentru judeţul 04 (TM) IND14 = max (matrdate[4][ j ]) = 21.000 = 00005208. j∈{0 , 4}
•
Indicator 2: numărul minim de emigranţi dintr-un anumit judeţ, se calculează ca minimul elementelor de pe linia matricei mai puţin elementul de pe diagonala principală; IND2i = min (matrdate[i ][ j ]) , unde i ∈ {0,4} , i ≠ j şi i j∈{0 , 4}
reprezintă judeţul pentru se calculează indicatorul iar matrdate este matricea în care sunt memorate datele din tabelul 3. De exemplu pentru judeţul 04 (TM) IND24 = min (matrdate[4][ j ]) = 105 = 00000069. j∈{0 , 4}
•
Indicator 3: numărul maxim de imigranţi într-un anumit judeţ, se calculează ca maximul elementelor de pe coloana matricei mai puţin elementul de pe diagonala principală; IND3j = max (matrdate[i ][ j ]) , unde j ∈ {0,4} , i ≠ j şi j i∈{0 , 4}
reprezintă judeţul pentru se calculează indicatorul iar matrdate este matricea în care sunt memorate datele din tabelul 3. De exemplu pentru judeţul 04 (TM) IND34 = max (matrdate[i ][4]) = 11.000 = 00002AF8. i∈{0 , 4}
12
•
Indicator 4: numărul minim de imigranţi într-un anumit judeţ, se calculează ca minimul elementelor de pe coloana matricei mai puţin elementul de pe diagonala principală; IND4j = min (matrdate[i ][ j ]) , unde j ∈ {0,4} , i ≠ j şi j i∈{0 , 4}
reprezintă judeţul pentru se calculează indicatorul iar matrdate este matricea în care sunt memorate datele din tabelul 3. De exemplu pentru judeţul 04 (TM) IND44 = min (matrdate[i ][4]) = 11.000 = 00002AF8. i∈{0 , 4}
•
Indicator 5: numărul total de emigranţi dintr-un anumit judeţ, se calculează ca suma elementelor de pe linia matricei mai puţin elementul de pe diagonala principală; IND5i =
4
∑ (matrdate[i][ j ]) ,
unde
i ∈ {0,4} ,
i ≠ j şi i
j =0
reprezintă judeţul pentru se calculează indicatorul iar matrdate este matricea în care sunt memorate datele din tabelul 3. De exemplu pentru judeţul 04 (TM) IND54 = 3
∑ (matrdate[4][ j ]) = 21.435 = 000053BB. j =0
•
Indicator 6: numărul total de imigranţi într-un anumit judeţ, se calculează ca suma elementelor de pe coloana matricei mai puţin elementul de pe diagonala principală; IND6j =
4
∑ (matrdate[i][ j ]) ,
unde
i ∈ {0,4} ,
i ≠ j şi j
i =0
reprezintă judeţul pentru se calculează indicatorul iar matrdate este matricea în care sunt memorate datele din tabelul 3. De exemplu pentru judeţul 04 (TM) IND64 = 4
∑ (matrdate[i][4]) = 12.920 = 00003278. i =0
•
Indicator 7: numărul populaţiei rămase la sfârşitul perioadei statistice în respectivul judeţ, se calculeaza ca 13
elementul de pe diagonala principală corespunzător judeţului pentru care se calculează indicatorul plus Indicatorul 6 pentru judeţul respectiv minus Indicator 5 pentru acelaşi judeţ. IND7i = matrdate[i][i] + IND6i – IND5i. De exemplu pentru judeţul 04 adică i=4, IND74 = matrdate[4][4] + (12920 – 21435) = 363120 – 8515 = 354605 = 0005692D. Cei şapte indicatori de mai sus sunt indicatori ce se calculează fiecărui judeţ în parte, următori patru indicatori sunt indicatori agregaţi şi medii ce sunt corespunzători tuturor judeţelor. Astfel se calculează: • Indicator 8: maximul total al emigranţilor şi este maximul dintre toţi cei 5 (câte judeţe sunt) indicatori Indicator 1; IND8 = max( IND1i ) , unde i ∈ {0,4} . i
•
Indicator 9: minimul total al emigranţilor şi este minimul dintre toţi cei 5 (câte judeţe sunt) indicatori Indicator 2. IND9= min ( IND2 i ) , unde i ∈ {0,4} . i
•
Indicator 10: maximul total al imigranţilor şi este maximul dintre toţi cei 5 (câte judeţe sunt) indicatori Indicator 3; IND10 = max( IND3 i ) , unde i ∈ {0,4} .
•
Indicator 11: minimul total al imigranţilor şi este minimul dintre toţi cei 5 (câte judeţe sunt) indicatori Indicator 4. IND11 = min ( IND4 i ) , unde i ∈ {0,4} .
i
i
•
Indicator 12: numărul total de emigranţi din toate judeţele şi este suma tuturor celor 5 indicatori Indicator 5; IND12 = ∑ IND5 i , unde i ∈ {0,4} . i
•
Indicator 13: numărul total de imigranţi către toate judeţele şi este suma tuturor celor 5 indicatori Indicator 6; IND13 = ∑ IND6 i , unde i ∈ {0,4} . i
•
Indicator 14: numărul mediu de emigranţi din toate judeţele şi este valoarea Indicatorului 12 împărţit la 5, câte judeţe sunt luate în calcul; IND14 = IND12/5; 14
•
Indicator 15: numărul mediu de imigranţi către toate judeţele şi este valoarea Indicatorului 13 împărţit la 5, câte judeţe sunt luate în calcul. IND15 = IND13/5;
Trebuie avut în vedere că pentru calculul indicatorului 14 şi 15 se vor folosi variabile reale şi proceduri specifice de afişare variabilelor reale. Problema modului de afişare şi preluare a numerelor reale este des întâlnită în folosirea limbajelor de asamblare iar pentru rezolvarea ei în capitolul următor se vor elabora biblioteci proceduri sau macrodefiniţii. În continuare se prezintă schema logică a programului: START Preluare date de la tastatură sau din fişere; Construire matrice emigrare/imigrare; Calcul indicatori statistici Apel proceduri sau macrodefiniţii
Afişare indicatori
STOP
Figura 1: Schema logică generală a programului. Aceasta este schema logică generală a programului, ea fiind detaliată la nivelul fiecărei proceduri sau macrodefiniţii în parte.
15
6. Proiectarea structurii produsului software Se consideră că este nevoie să se lucreze cât mai modularizat. Se construiesc trei librării de proceduri şi macrodefiniţii. Unele librării sunt doar de macrodefiniţii şi aceleaşi librării sunt construite şi numai din proceduri. Se face acest lucru în vederea comparării performanţelor programului în cazul în care foloseşte macrodefiniţii şi în cazul în care foloseşte doar proceduri. Structura celor trei librării fiind următoarea: • bibliotecă de proceduri pentru conversia real-ASCII şi alte proceduri utile în calculul indicatorilor statistici; • bibliotecă de proceduri pentru lucru cu fişiere folosind intreruperea 21h, aceeaşi bibliotecă fiind rescrisă şi cu ajutorul macrodefiniţiilor; • bibliotecă de proceduri folosită pentru afişarea şirurilor de carctere şi preluarea de date de la tastatură, formatare ecran. Opţional se construieşte şi o bibliotecă de macrodefiniţii sau proceduri pentru afişarea meniului text sau grafic precum şi o bibliotecă pentru validarea datelor de intrare. Codul sursă pentru crearea şi utilizarea meniului este conţinut în programul principal. Pentru fiecare procedură sau macrodefiniţie din oricare bilbliotecă se poate construi o schemă logică şi explica în detaliu dar fiind multe asemenea construcţii, acestea sunt explicate împreună cu codul sursă aferent în anexele acestui material. Deci structura produsului software elaborat pentru rezolvarea problemei este următoarea: trei biblioteci de macrodefiniţii şi proceduri şi un program principal din care se apelează funcţiile din cele trei librării. Se creează o structură arborescentă a programului pentru a observa structura sa modulară în Figura 2:
16
Program Principal (MAIN)
Introducere date (INTRD)
Indicatori individuali (CALCF)
Efectuare Calcule (CALC)
Afisare rezultate (AFISR)
Indicatori agregati (CALCG)
Figura 2: Structura arborescentă a programului. Apelul procedurilor sau macrodefiniţiilor din aceste librării se face dintr-un program principal, program ce va fi prezentat parţial în Capitolul 7 al acestei lucrări. Codul sursă în limbaj de asamblare al bibliotecilor de macrodefiniţii şi proceduri se află în Anexa 1 a prezentului material.
17
7. Textul sursă al programului După parcurgerea tuturor paşilor anteriori se va trece la scrierea codului sursă a programului. Se includ bibliotecile cu macrodefiniţii care sunt folosite în program: include FMacro.mac include IO.mac
apoi se trece la scrierea propriu-zisă a codului. Programul este împărţit în trei segmente, segmentul de stivă, de date şi de cod. În segmentul de cod se observă 2 mari porţiuni, o porţiune în care se implementează o parte din procedurile folosite şi o parte în care este codul meniului şi apelul macrodefiniţiilor şi procedurilor necesare calcului indicatorilor. Sunt prezentate porţiuni din segmentul de stivă şi date: .model large .stack 1024 .data vectjud dw 5 dup ('IF','CT','GL','CJ','TM') ;definire vector de judete-doar 5 matrdate dw 5 dup (5 dup (0)) ;definire matrice de date, in varianta ;extinsa este de dd (elemente de patru octeti) vecttemp dd 6 dup(1) ;vector temporar pentru sumele de pe linii si de pe ;coloane CRLF db 13,10,'$' sir_inc1 db '[1]Preluare date tastatura',10,13,'$' sir_inc2 db '[2]Preluare date din fisier',10,13,'$' sir_calc db '[3]Calcul indicatori statistici',10, 13,'$' sir_afis db '[4]Afisare/Salvare indicatori',10,13,'$' sir_ies db '[5] IESIRE',10,13,'$' sir_opt db '-->$' sir_temp db 7 dup(0),'$' cod dw 0 numef db 'D:\Cristian\School\Articole\GhidPr~1\ghid\matr01.txt ','$'
i dw 5
18
j dw 5 col dw 5
Se observă că în segmentul de date se declară structura în care se reţin numele judeţelor cu care se operează. Pentru viitoarele versiuni ale programului datorită faptului că nu se va cunoaşte numărul de judeţe cu care se va opera această structură nu va mai fi un masiv unidimensional ci o listă simplu sau dublu înlănţuită. Matricea în care se reţin datele cu care se operează – matrdate – dacă se operează cu date de dimensiuni foarte mari poate avea alt tip mai cuprinzător. Apoi sunt declarate variabile contor sau şiruri de caractere care vor fi utilizate în afişarea meniurilor. În continuare se prezintă porţiuni din segmentul de cod. .code ;;;;Sectiune proceduri ;Procedura pentru efectuarea sumei pe linii din matrice ;Imaginea stivei inainte de apel trebuie sa fie ;distanta fata de BP in bytes ;adresa mica col 0 ; i 2 ; j 4 ; mat 6 FAR ; vect 10 FAR ;i->numarul efectiv de linii al matricei ;j->numarul de coloane al matricei ;REZULTAT: [vects+i*4]=suma elementelor de pe linia i ;[vects]->de tip double dd ;[adr]->inseamna continutul de la adresa adr sum_lin1 proc far push bp mov bp,sp add bp,6 push SI push DI push AX push BX push CX push DX push ES mov AX,2 mul word ptr [bp+2] mov word ptr [bp+2],AX
19
;pentru ca se lucreaza pe word mov AX,2 mul word ptr [bp+4] mov word ptr [bp+4],AX ;pentru ca se lucreaza pe word mov SI,0 ;initializare contor i linnextSI: mov DI,0 ;initializare contor j ;se pune in BX offset vector rezultate mov BX,[BP+10] ;se pune in BX segment vector rezultate mov ES,[BP+12] mov AX,0 add BX,SI add BX,SI ;pentru ca vectorul e dd mov ES:[BX],AX ;initializare valoare rezultat pe linia i linnextDI: mov AX,SI mul word ptr [BP] ;i*col add AX,DI ;AX=i*Col+j mov BX,[BP+6] mov ES,[BP+8] add BX,AX mov AX,ES:[BX] ;de abia acum se acceseaza a[i][j] mov CX,0 mov BX,[BP+10] mov ES,[BP+12] mov BX,SI mov BX,SI add ES:[BX],AX adc ES:[BX+2],CX add di,2 cmp DI,[BP+4] jne linnextDI add SI,2 cmp SI,[BP+2] jne linnextSI ;restaurare registri pop ES pop DX
20
pop CX pop BX pop AX pop DI pop SI pop BP retf 14 sum_lin1 endp
;Procedura pentru efectuarea sumei pe coloane din matrice ;Imaginea stivei inainte de apel trebuie sa fie ;distanta fata de BP in bytes ;adresa mica col 0 ; i 2 ; j 4 ; mat 6 FAR ; vect 10 FAR ;i->numarul efectiv de linii al matricei ;j->numarul de coloane al matricei ;REZULTAT: [vects+i*4]=suma elementelor de pe linia i ;[vects]->de tip double dd ;[adr]->inseamna continutul de la adresa adr sum_col1 proc far push bp mov bp,sp add bp,6 push SI push DI push AX push BX push CX push DX push ES mov AX,2 mul word ptr [bp+2] mov word ptr [bp+2],AX ;pentru ca se lucreaza pe word mov AX,2 mul word ptr [bp+4] mov word ptr [bp+4],AX ;pentru ca se lucreaza pe word mov DI,0 ;initializare contor i colnextDI:
21
mov SI,0 ;initializare contor j mov BX,[BP+10] ;se pune in BX offset vector rezultate mov ES,[BP+12] ;se pune in BX segment vector rezultate mov AX,0 add BX,DI add BX,DI ;pentru ca vectorul e dd mov ES:[BX],AX ;initializare valoare rezultat pe linia i colnextSI: mov AX,SI mul word ptr [BP] ;i*col add AX,DI ;AX=i*Col+j mov BX,[BP+6] mov ES,[BP+8] add BX,AX mov AX,ES:[BX] ;de abia acum se acceseaza a[i][j] mov CX,0 mov BX,[BP+10] mov ES,[BP+12] mov BX,DI mov BX,DI add ES:[BX],AX adc ES:[BX+2],CX add SI,2 cmp SI,[BP+2] jne colnextSI add DI,2 cmp DI,[BP+4] jne colnextDI ;restaurare registri pop ES pop DX pop CX pop BX pop AX pop DI pop SI pop BP retf 14 sum_col1 endp ;Procedura pentru citirea unei matrice dintr-un fisier ;Imaginea stivei inainte de apel trebuie sa fie
22
;distanta fata de BP in bytes ;adresa mica col 0 ; i 2 ; j 4 ; mat 6 NEAR ; nume 8 NEAR ; cod 10 NEAR ;i->numarul efectiv de linii al matricei ;j->numarul de coloane al matricei; nume=numele ;fisierului; cod=0 nici o eroare ;REZULTAT: [vects+i*4]=suma elementelor de pe linia i ;[vects]->de tip double dd ;[adr]->inseamna continutul de la adresa adr fis_read proc far push bp mov bp,sp add bp,4 push SI push DI push BX push CX push DX mov DX,[BP+8] mov AH,3Dh mov AL,0 int 21h mov cx,ax ;handlerul pentru fisier jnc TMP1rerr ;eroare la deschidere jmp rerr TMP1rerr: mov AH,3fh ;citire i mov BX,CX mov DX,[BP+2] ;offset i mov CX,2 int 21h jnc TMP2rerr jmp rerr TMP2rerr: mov CX,BX helpi: mov BX,DX ;offset i mov byte ptr [BX+1],0 ;byte-ul superior este 0 mov AH,3Fh ;citire j mov BX,CX mov DX,[BP+4] ;offset j mov CX,2
23
int 21h jc rerr mov CX,BX helpj: mov BX,DX ;offset j mov byte ptr [BX+1],0 ;byte-ul superior este 0 mov AX,2 mov BX,[BP+2] ;offset i mul word ptr [bx] mov word ptr [bx],AX ;pentru ca se lucreaza pe word mov AX,2 mov BX,[BP+4] mul word ptr [bx] ;offset j mov word ptr [bx],AX ;pentru ca se lucreaza pe word mov SI,0 rfisnextSI: mov DI,0 rfisnextDI: mov AX,SI mul word ptr [bp] ;i*Col mov BX,[bp+6] ;i*Col+j;adresa matrice add DX,BX ;a[i][j] ;citire din fisier mov BX,CX mov AH,3Fh mov CX,2 int 21h mov CX,BX jc rerr add DI,2 mov BX,[BP+4] cmp DI,[BX] jne rfisnextDI add SI,2 mov BX,[bp+2] cmp SI,[BX] jne rfisnextSI mov DX,0 ;necesar la impartire mov BX,[BP+2] mov AX,[BX] mov CX,2 div CX
;offfset j
;offset i
;offset i
24
mov [BX],AX ;restaurare valoare a lui i mov bx,[bp+10] ;offset cod mov AX,0 mov [BX],AX ;nici o eroare cod = 0 mov AH,3Eh ;inchidere fisier mov BX,CX int 21h jc rerr jmp rfisSF rerr: mov BX,[BP+10] ;se pune codul de eroare mov [BX],AX rfisSF: ;restaurare registri pop DX pop CX pop BX pop DI pop SI pop BP retn 12 fis_read endp start: ;MAIN mov AX,@data mov DS, AX ;;Sectiune cod - meniu meniu: StergeEcran afis sir_inc1 afis sir_inc2 afis sir_calc afis sir_afis afis sir_ies afis sir_opt mov AH, 01h int 21h cmp AL,'1' jne Pas1 jmp Opt1 Pas1: cmp AL,'2'
25
jne Pas2 jmp Opt2 Pas2: cmp AL,'3' jne Pas3 jmp Opt3 Pas3: cmp AL,'4' jne Pas4 jmp Opt4 Pas4: cmp AL,'5' jne Pas5 jmp exit_dos Pas5: ;s-a tastat altceva jmp meniu ;optiunile ;S-a ales optiunea 1 Opt1: ;se citesc 25 de elemente ale matricei push offset cod push offset numef push offset matrdate push offset i push offset j push offset col call fis_read cmp cod,0 jne exit_dos End_Opt1: jmp meniu ;S-a ales optiunea 2 Opt2: End_Opt2: jmp meniu ;S-a ales optiunea 3 Opt3: End_Opt3: jmp meniu ;S-a ales optiunea 4 Opt4: End_Opt4:
26
jmp meniu exit_dos: mov AX, 4C00h int 21h end start
Segmentul de cod este divizat în două mari părţi: o parte în care se descriu procedurile folosite şi o parte în care aceste proceduri sunt apelate. De asemenea urmărind codul sursă de la eticheta “start” – MAIN – eniul poate fi folosit în orice program doar că trebuie schimbate şirurile de caractere care sunt folosite pentru afişare. Aceste modificări au loc în segmentul de date. Se observă că în codul sursă prezentat în acest capitol este redat doar scheletul programului principal, apelator adică meniul şi funcţia de încărcare date din fişier. Apelul macrodefiniţiilor şi procedurilor pentru calculul indicatorilor se face în mod similar doar că trebuie ştiut foarte bine numărul de parametri şi ce parametri se transmit modulelor de calcul. Programul sursă are multe comentarii astfel încât dacă cineva doreşte să extindă facilităţile oferite de acest program să poată face acest lucru într-un mod facil.
27
8. Crearea documentaţei aferente produsului program Documentaţia unui produs program trebuie să conţină: manualul de utilizare, datele de test incluse in documentaţia de teste şi implementare şi documentarea în amănunt a codului sursă şi explicarea macrodefiniţiilor şi procedurilor care sunt folosite şi puse la dipoziţie pentru dezvoltarile ulterioare. Documentarea produsului este foarte importantă din mai multe puncte de vedere. Din punct de vedere dezvoltare-scalabilitate este foarte important ca ceilalţi dezvoltatori să înţeleagă foarte bine fiecare macrodefiniţie sau procedură pentru a creşte gradul de reutilizare al codului. Din punct de vedere al beneficiarului este foarte important manualul de utilizare în care sunt explicate toate amănuntele din perspectiva interfeţei. Este explicată interfaţa grafică cu utilizatorul, modul de configurare a anumitor fişiere şi de setare a mediului de lucru. Chiar dacă interfaţa om-calculator este una intuitivă şi prietenoasă documentarea pentru client este importantă. Acest manual de utilizare nu trebuie să fie foarte tehnic decât când aplicaţia se adresează unor specialişti. Documentarea macrodefiniţiilor, procedurilor, modulelor de program şi programelor trebuie făcută dacă programul are posibilităţi de extindere. Astfel se evită folosirea eronată a unor proceduri folosind parametri incorecţi sau fiind nevoie de rescrierea acelei porţiuni de cod care nu este înţeleasă, deoarece nu a fost documentată. Aşa cum l limbajele evoluate există programe care generează automat fişierele eferente fiecărei porţiuni de program – de exemplu javadoc din Java Development Kit. Deci se poate stabili o convenţie ca de exemplu comentariile de procedură să fie de 3 caractere “;” succesive. Apoi dacă este parametru de intrare se scrie în codul sursă “param” urmat de spaţiu şi numele parametrului de intrare, iar dacă este parametrul de ieşire, se procedează la fel ca mai sus numai că se mai adaugă un semn distinct “@” în faţă. De exemplu, la macrodefiniţia de ştergere un fişier forma generală este următoarea:
28
Macrodefiniţie pentru ştergerea unui fişier
Salvare regiştrii
Prelucrări
Restaurare regiştri
Figura 3: Schema generală a macrodefiniţiei pentru ştergerea unui fişier. Pentru generarea automată a documentaţiei cu ajutorul unui program creat de utilizator se vor scrie comentariile în următorul mod: ;;;Macrodefinitie pentru stergere fisier ;;;param NumeF: sir ASCIIZ ce contine numele fisierului ;;;@param Rez: rezultatul operatiei: 0 succes, altfel codul de ;;;eroare StergeFisier MACRO NumeF, Rez local NOK, Iesire push AX push DX push DS mov AH, 41h lea DX, NumeF int 21h jc NOK mov Rez, 0 jmp Iesire NOK: mov Rez, AX Iesire: pop DS pop DX pop AX ENDM
Apoi cu ajutorul unui program special care “ştie” convenţia stabilită, acest fişier se pot genera pagini HTML în care vor fi prezentate toate comentariile conform unui standard. După acest tip de manual se urmăreşte mult mai uşor tipul de parametri care trebuiesc folosiţi în proceduri şi macrodefiniţii, modul de apel şi uşurează mult munca de dezvoltare a noilor programe care utilizează module din acest program. 29
Pentru programul de faţă se elaborează manual de utilizare care conţine inclusiv date de test şi manualul în care este prezentată fiecare procedură sau macrodefiniţie cu tipul parametrilor de intrare, parametrilor de ieşire şi a codurilor de eroare utilizate. Dacă această muncă de documentare sar face manual şi nu automat pe baza comentariilor introduse de programatori, productivitatea dezvoltării programelor ar scădea considerabil.
30
9. Testare şi implementare Se iau toate datele de test. Mai întai se consideră cazurile extreme. De exemplu nu poate exista pe diagonala principală elemente cu valoarea 0. Se convine de asemenea ca să nu se utilizeze numere negative în matrice, deşi acestea ar putea avea o interpretare, se foloseşte convenţia conform căreia pe linie sunt exprimate emigrările de populaţie iar pe coloane imigrările. Programul se scrie în limbaj de asamblare specific procesoarelor Intel şi AMD şi se rulează pe PC-uri. Compilatoarele cu care s-a testat sunt TASM (Borland) şi MASM (Microsoft). La documentaţia în care se includ informaţii privind implementarea trebuie specificaţi paşi care trebuiesc a fi urmaţi pentru obţinerea programului final. Se scrie codul sursă într-un fişier text. De exemplu, dacă se scrie un program care evaluează o expresie cu cinci operanzi (x=a*b-c/d+e) vor trebui urmăriţi paşi: • se caută fişierul ce conţine codul sursă pentru evaluarea acestei expresii; • se compilează codul sursă; • în cazul în care nu apare nici o eroare se trece la pasul următor, dacă apar erori se reia primul pas; • se link-editeză codul obiect al programului şi în caz că nu apar erori se obţine programul executabil. Codul sursă a programului de mai sus se regăseşte în Anexa 2 a prezentului material. Este de preferat ca notaţiile folosite în documente de analiză/proiectare şi în caietul de sarcini să se respecte şi în program. Pe programul din Anexa 2 se explică pas cu pas ce se întâmplă cu regiştri microprocesorului, memoria, indicatori de condiţie, etc. În figura 4 este prezentată fereastra TurboDebugger-ului imediat ce este încărcat programul.
31
Figura 4: Turbo Debugger imediat dupa incărcarea programului. Acest program este lansat deobicei cu comanda td în MS-DOS prompt iar primul parametru din linia de comandă în mod uzual este fişierul executabil rezultat la paşi anteriori. Se observă că ecranul este împărţit în mai multe regiuni: • Regiunea din stânga sus conţine codul programului. Se observă că numele variabilelor au fost înlocuite cu numere, care reprezintă deplasamentele (offset) în cadrul segmentului de date. • Regiunea din stânga jos prezintă conţinutul segmentului de date. Se apasă click dreapta cu mouse-ul pe acea zonă şi se selectează opţiunea „Go to...”. Se inserează „DS:000E”, adică deplasamentul 000E în cadrul segmentului de date. Se observă că în stânga jos în figura 4 sunt octeţi exact în ordinea declarării în program adică a este 04, b este 02, c este 06 şi aşa mai departe. • Regiunea din dreapta sus conţine registrele procesorului şi indicatorii de condiţie (registru de flags). Aici se urmăresc efectele diferitelor instrucţiuni precum „mov”. • Regiunea din dreapta jos prezintă conţinutul segmentului de stivă; în acest caz nu s-a folosit stiva, deci conţinutul acestei zone este nedefinit. Pentru a rula pas cu pas programul se apasă tasta F7. De fiecare dată se urmăresc toate modificările care au loc. Conţinutul registrului AX la fiecare pas al execuţiei programului este prezentat în tabelul 4: 32
Tabel 4: Conţinutul registrului AX la rularea programului pas cu pas Instrucţiunea
mov AX,@data mov DS,AX mov AL,a
Conţinut AX (hexa) 0C6E 0C6E 0C04
mul b mov t1,AL xor AX,AX mov AL,c div d mov t2,AL mov AL,t1 sub AL,t2 add AL,e mov x,AL mov AH,4c int 21h
0008 0008 0000 0006 0002 0002 0008 0006 000F 000F 4C0F 4C0F
Observaţii
AX=@data DS=AX AL=04, AH rămâne 0C, IP devine 0008 AX=4*2=8 t1=AL AX=0, iar flags: Z=1, P=1 AL=06 dar AH=00 AL=6 div 3=2;AH=6 mod 3=0 t2=AL AL=t1 AL=AL-2=8-2=6 AL=AL+9=6+9=0F X=AL AH=4C;AL=0F Ieşire
În figura 5 este prezentată fereastra programului td chiar după ce s-a pus rezultatul expresiei în x.
Figura 5: Starea regiştrilor înainte de terminarea programului. 33
Se observă că registrul AX are valoarea 15 adică 0F, dar şi variabila x are tot valoarea 15 la adresa DS:0015. Cu cât acest pas de testare şi implementare este efectuat cât mai consecvent şi corect cu atât erorile care pot apărea la utilizarea programului pot fi mai mici. Mai mult cu ajutorul programului TurboDebugger se depistează deseori cauzele unei erori care dacă nu ar fi fost acest program ar fi creat multe probleme echipei de dezvoltare.
34
10. Analiză cantitativă şi calitativă Cea mai la îndemână analiză este cea cantitativă. Prima dată se masoară în octeţi mărimea fişierelor sursă. Apoi se măsoară dimensiunea codurilor obiect, şi apoi cele executabile. Următorul pas al analizei este viteza de execuţie a anumitor porţiuni din program. Dacă programul este modularizat atunci se calculează viteza de execuţie în secunde a unui modul pe diverse date de intrare. Dacă se consideră datele de intrare din tabelul 2 atunci rezultă următoarele rezultate: Tabel 5: Analiză cantitativă asupra unor programe assembler Indicatori
Program simplu de evaluare expresie aritmetic ă
Program calcul migraţie populaţie cu librării ce conţin macrodefiniţii
Program calcul migraţie populaţie cu librării ce conţin proceduri
Marime cod sursă (în bytes)
697 8226
8200
Mărime cod obiect (în bytes)
295 2804
1302
Mărime cod executabil (în bytes) Timp de execuţie (sec)
563 3100
1510
1 2
3
Observaţii
Este mult mai util calcularea numărului de linii sursă deoarece la mărimea fişierului sursă intră şi comentariile Primul program nu conţine nici o macrodefiniţie sau procedură.
Doar pe modul de calculează primul indicator
35
Este evident din datele înregistrate că tipul de aplicaţie este decisiv în alegerea de a lucra cu biblioteci de macrodefiniţii sau biblioteci de proceduri. De exemplu la o aplicaţie în care timpul este critic, eventual este vorba despre o aplicaţie în timp real, dar memoria nu are limitări serioase atunci se va opta pentru dezvoltarea de aplicaţii care folosesc macrodefiniţii. Dacă din contră spaţiul ocupat de codul executabil trebuie să fie mic iar timpul de răspuns nu este restrictiv atunci se va opta pentru dezvoltarea de programe utilizând biblioteci de proceduri. La calculatoarele personale la aplicaţii de dimensiuni medii rareori se pune problema de spaţiu de memorare a codului executabil. Dar există acum foarte multe dispozitive „neconvenţionale” (smart-card-uri, procesoare de telefoane mobile şi echipamente de comunicaţii) au nevoie de aplicaţii în timp real care să ocupe şi puţină memorie. Atunci se caută un grad de optim de îmbinare a bibliotecilor uzitate, adică se vor folosi biblioteci de macrodefiniţii în modulele critice din punct de vedere timp de execuţie, iar în modulele critice din punct de vedere spaţiu de stocare se vor utiliza biblioteci de proceduri. Considerentele calitative se resfrâng în mod direct asupra indicatorilor cantitativi. De exemplu calitatea programării, adică optimizarea codului scris implică obţinerea unui cod executabil cu număr optim de cicluri maşină. Acest lucru are influenţă directă asupra timpului de execuţie a programului. Deci evident timpul de execuţie a programului va scădea, dar mărimea codului executabil poate fi mai mare deoarece instrucţiunile cu cicluri maşină mai puţine pot ocupa mai mulţi octeţi. Aceste lucruri depind foarte mult şi de asamblorul folosit.
36
11. Concluzii În rezolvarea problemelor este foarte importantă analiza problemei. Dacă în perioada de analiză există erori care nu sunt tratate în momentul în care apar modificări asupra algoritmului pot rezulta ieşiri ale programului care nu mai pot fi controlate. Numărul de erori este de obicei proporţional cu dimensiunea problemei de rezolvat, iar pentru a evita astfel de eşuări se modularizează cât mai mult programul. Alegerea tipul de date utilizat în rezolvarea programului este foarte important. Depinde de foarte mulţi factori – limbajul de programare sau asamblare care se foloseşte, tipul de maşină sau procesor pe care se lucrează, compatibilitatea cu versiunile precedente – şi trebuie avută în vedere scalabilitatea programului, posibilitatea lui de extindere. De exemplu, dacă pentru un program utilizat într-o instituţie bancara se poate folosi tipul de date pe 8 octeţi (dq) pentru memorarea sumelor de bani, în momentul în care mai apar filiale şi programul trebuie implementat şi în acele filiale – sumele cu care se operează fiind mult mai mari – atunci este avantajos a se alege încă din perioada de analiză posibilitatea de lucra cu numere memorate ca şiruri de caractere iar operaţiile aritmetice şi logice să fie executate simulat. Un alt lucru important este structurarea programului în module cât mai independente pentru a putea fi dezvoltat în echipă. În acest sens programul se structurează arborescent iar nodurile arborelui sunt fie modulele care trebuiesc implementate fie funcţiile pe care trebuie să le îndeplinească programul. Specificaţiile elaborate de programator sau echipa de dezvoltare trebuie să fie concise şi clare. Ele trebuie să conţină exemple de test. Aceste exemple de multe ori nu sunt suficiente iar pentru creşterea performanţelor dezvoltatorului de programe se recurge la următoarea strategie: • Producătorul lansează produsul în variantă beta; • Produsul software este dat unui număr limitat de utilizatori pentru a fi testat; • Programul este testat cu datele de test ale utilizatorului pe cazuri reale dar rezultatele trebuie înscrise într-un tabel cu un anumit format; • Conform rezultatelor colectate de la acei utilizatori care au testat produsul – utilizatori au folosit programul gratuit dar au realizat implicit şi trestarea produsului – produsul 37
software este lansat în varianta finală. Tabelele de teste au un format standard în care sunt cuprinse informaţii ca: tipul de maşină şi procesor pe care s-a testat programul, data, cu ce date de test s-au obţinut ieşirile respective, durata execuţiei, dacă se intră în ciclare infinită, etc. Programatorul trebuie să respecte nişte reguli, convenţii şi standarde pentru a evita scrierea de cod redundant şi care conţine erori. De exmplu o convenţie folosită poate fi ca orice macrodefiniţie sau procedură să depună codul de eroare în registrul AX iar dacă AX este 0 atunci operaţia s-a executat cu succes iar dacă nu este 0 atunci va conţine un cod de eroare, codurile de eroare fiind comune pentru toată echipa de dezvoltare. O altă regulă este ca transmiterea parametrilor în procedură să se facă numai pe stivă. Pot fi stabilite convenţii chiar şi pentru scrierea codului sursă, de exemplu regiştrii fiind scrişi cu literă mare. Dacă se lucrează în echipă acest mod de abordare este esenţial, fiind necesară o coerenţă în dezvoltarea produsului.
38
Anexa 1
1. Bibliotecă de macrodefiniţii (FileMacro.mac) pentru lucru cu fişiere: ;Macrodefinitie pentru creare fisier ;Parametrii de intrare: ; NumeF: sir ASCIIZ ce contine numele fisierului ; Atrib: atribute de creare ale noului fisier: ; 0 fisier normal ; 1 fisier protejat la scriere ; 2 fisier ascuns ; 4 fisier de sistem ;Parametrii de iesire: ; Handler: indicator de fisier returnat sau -1 la ;eroare ; Rez: rezultatul operatiei: 0 succes, altfel codul ;de eroare CreeazaFisier MACRO NumeF, Atrib, Handler, Rez local NOK, Iesire push AX push CX push DX push DS mov AH, 3Ch mov CX, Atrib lea DX, NumeF int 21h jc NOK mov Handler, AX mov Rez, 0 jmp Iesire NOK: mov Handler, -1 mov Rez, AX Iesire: pop DS pop DX pop CX pop AX ENDM ;Macrodefinitie pentru deschidere fisier
39
;Parametrii de intrare: ; NumeF: sir ASCIIZ ce contine numele fisierului ; Acces: tipul de acces: ; 0 citire ; 1 scriere ; 2 citire/scriere ;Parametrii de iesire: ; Handler: indicator de fisier returnat sau -1 la ;eroare ; Rez: rezultatul operatiei: 0 succes, altfel codul ;de eroare DeschideFisier MACRO NumeF, Acces, Handler, Rez local NOK, Iesire push AX push DX push DS mov AH, 3Dh mov CX, Acces lea DX, NumeF int 21h jc NOK mov Handler, AX mov Rez, 0 jmp Iesire NOK: mov Handler, -1 mov Rez, AX Iesire: pop DS pop DX pop AX ENDM ;Macrodefinitie pentru inchidere fisier ;Parametrii de intrare: ; Handler: identificatorul de fişier returnat de ;funcţia de creare/deschidere ;Parametrii de iesire: ; Rez: rezultatul operatiei: 0 succes, altfel codul ;de eroare InchidereFisier MACRO Handler, Rez local NOK, Iesire push AX push BX mov AH, 3Eh mov BX, Handler int 21h jc NOK
40
mov Rez, 0 jmp Iesire NOK: mov Rez, AX Iesire: pop BX pop AX ENDM ;Macrodefinitie pentru scriere in fisier ;Parametrii de intrare: ; Handler: identificatorul de fisier returnat de ;functia de creare/deschidere ; Buffer: zona de memorie din care se vor scrie ;datele citite ; OctetiDeScris: numarul de octeti de scris ;Parametrii de iesire: ; OctetiScrisi: numarul de octeti scrisi ; Rez: rezultatul operatiei: 0 succes, altfel codul ;de eroare ScrieInFisier MACRO Handler, Buffer, OctetiDeScris, OctetiScrisi, Rez local NOK, Iesire push AX push BX push CX push DX mov AH, 40h mov BX, Handler lea DX, Buffer mov CX, OctetiDeScris int 21h jc NOK mov OctetiScrisi, AX mov Rez, 0 jmp Iesire NOK: mov Rez, AX Iesire: pop DX pop CX pop BX pop AX ENDM ;Macrodefinitie pentru citire din fisier ;Parametrii de intrare:
41
;Handler: identificatorul de fisier returnat de functia de ;creare/deschidere ;Buffer: zona de memorie in care se vor scrie datele citite ; OctetiDeScris: numarul de octeti de citit ;Parametrii de iesire: ; OctetiScrisi: numarul de octeti scrisi ;Rez: rezultatul operatiei: 0 succes, altfel codul ;de ;eroare CitesteDinFisier MACRO Handler, Buffer, OctetiDeCitit, OctetiCititi, Rez local NOK, Iesire push AX push BX push CX push DX mov AH, 3Fh mov BX, Handler lea DX, Buffer mov CX, OctetiDeCitit int 21h jc NOK mov OctetiCititi, AX mov Rez, 0 jmp Iesire NOK: mov Rez, AX Iesire: pop DX pop CX pop BX pop AX ENDM ;Macrodefinitie pentru stergere fisier ;Parametrii de intrare: ; NumeF: sir ASCIIZ ce contine numele fisierului ;Parametrii de iesire: ; Rez: rezultatul operatiei: 0 succes, altfel codul ;de eroare StergeFisier MACRO NumeF, Rez local NOK, Iesire push AX push DX push DS mov AH, 41h lea DX, NumeF int 21h jc NOK
42
mov Rez, 0 jmp Iesire NOK: mov Rez, AX Iesire: pop DS pop DX pop AX ENDM ;Macrodefinitie pentru pozitionare in fisier ;Parametrii de intrare: ; Handler: identificatorul de fisier returnat de ;functia de creare/deschidere ; Pozitie: numarul de octeti fata de punctul de ;referinta (inceput, curent, sfarsit) ; From: punctul de referinta: ; 0 fata de inceputul fisierului ; 1 fata de pozitia curenta in fisier ; 2 fata de sfarsitul fisierului ;Parametrii de iesire: ; PozCrt: noua pozitie in fisier ; Rez: rezultatul operatiei: 0 succes, altfel codul ;de eroare PozitionareInFisier MACRO Handler, Pozitie, From, PozCrt, Rez local NOK, Iesire push AX push BX push CX push DX mov AH, 42h mov AL, From mov BX, Handler mov DX, word ptr Pozitie[0] mov CX, word ptr Pozitie[1] int 21h jc NOK mov word ptr Pozitie[0], AX mov word ptr Pozitie[1], DX mov Rez, 0 jmp Iesire NOK: mov Handler, -1 mov Rez, AX Iesire: pop DX pop CX
43
pop BX pop AX ENDM
2. Biblioteca de macrodefinitii (IO.mac) pentru lucru cu siruri de caractere: ;Macrodefinitie pentru stergerea ecranului StergeEcran MACRO push AX mov AL,02h mov AH,00h int 10h pop AX ENDM ;Macrodefinitie pentru ;tastatura citc MACRO car push AX mov AH,01h int 21h mov car,AL pop AX ENDM
citirea
unui
caracter
de
la
;Macrodefinitie pentru citirea unui sir de caractere de ;max. 20 caractere de la tastatura cit MACRO buf local et1, et2 push AX push CX push BX lea BX, buf mov CX,20 xor SI,SI et1: jcxz et2 mov AH,01h int 21h cmp AL,13h je et2 mov AH,0 mov BX[SI],AX dec CX inc SI jmp et1
44
ENDM
et2: mov mov mov int mov mov int pop BX pop CX pop Ax
BX[SI], word ptr ’$’ DL,13 AH,02h 21h DL,10 AH,02h 21h
;Macrodefinitie pentru citirea unui sir de numere ;citirea se opreste cand se introduce orice altceva decat ;un numar citsn MACRO sir local etr, et1 push DS push BX push AX push DX lea BX, sir etr: mov AH,08h int 21h cmp AL,'9' jg et1 cmp AL,'0' jb et1 mov [BX],AL mov DL,AL mov AH,02h int 21h inc BX jmp etr et1: mov byte ptr[BX],'$' mov DL,13 mov AH,02h int 21h mov DL,10 mov AH,02h int 21h pop DX pop AX pop BX pop DS
45
ENDM ;Macrodefinitie pentru afisarea unui sir de caractere afis MACRO sir local etr, et1 push DS push DX push AX lea DX, sir mov AH,09h int 21h pop AX pop DX pop DS ENDM ;Macrodefinitie pentru conversie ASCII-binar ;parametri – numar:DB, num:DD, baza:DW ;numărul se află în AX - EAX atoi MACRO numar,num,baza local etsf, rev push DS push SI push EAX push EBX lea SI,numar xor EAX,EAX xor EBX,EBX rev: mov BL,[SI] cmp BL,’$’ jz etsf sub BL,30h mul baza add EAX,EBX inc SI jmp rev etsf: mov num, EAX pop EBX pop EAX pop SI pop DS ENDM
46
;Macrodefinitie pentru conversie binar-ASCII ;si afisare ;parametri – numarul este preluat din nr DD afisn MACRO nr,baza local rel,etc,etsf push BP push SP push EAX push EDX mov BP,SP mov EAX,nr rel: xor DX,DX or EAX,0 jz etc div baza add EDX,30h push EDX jmp rel etc: cmp BP,SP jz etfs pop EDX mov AH,02h int 21h jmp etc etsf: mov num, EAX pop BX pop AX pop SI pop DS ENDM
47
Anexa 2
;Program de evaluare a expresiei matematice x=a*b-c/d+e .model small .data a db 4 b db 2 c db 6 d db 3 e db 9 t1 db ? t2 db ? x db ? .code start: mov mov mov mul mov xor mov div mov mov sub add mov mov int end start
;definire model de memorie ;definire segment de date ;definire variabile
;definire rezultate ;definire segment de cod ;etichetă de început ax,@data ;initializare segment de date ds,ax al,a ;al=a b ;al=al*b t1,al ;t1=a1 ax,ax ; ax=0 al,c ;al=c d ;al=al div d t2,al ;t2=al al,t1 ;al=t1 al,t2 ;al=a1-t2 al,e ;al=al+e x,al ;x=al ah,4Ch ;4Ch cod serviciu 21h ;apel intrerupere DOS ;sfarsit program
48
Anexa 3 Probleme propuse pentru realizarea proiectelor la disciplina limbaje de asamblare. Indicele sintetic al preţurilor de tip Paasche. Calculul indicatorului static ritm Masa monetară Calculul productuivităţii medii zilnice la nivelul unei întreprinderi Calculul estimatorului A din ecuaţia de regresie Calcularea procentului de modificare a producţiei fizice totale Calculul fondului de timp calendaristic Profitul mediu la 1 leu cifră de afaceri Nivelul mediu al productivităţii muncii la nivelul economiei naţionale 10. Calculul ritmului încasărilor lunare 11. Impactul taxelor pe cantitate asupra restricţiei de buget 12. Calculul mediei şi dispersiei dintr-o serie de date 13. Calculul duratei medii a zilei de lucru la nivelul unei întreprinderi 14. Calculul ratei rentabilităţii resurselor consumate 15. Calculul indicelui de lichiditate 16. Calculul indicilor de tip LasPeyres şi Paasche pentru analiza modificării valorii vânzărilor sub influenţa factorilor preţul şi cantitatea 17. Calculul salariului mediu 18. Câştigul potenţial al titlurilor financiare 19. Indicele producţiei valorice 20. Productivitatea marginală 21. Calculul salariului net 22. Calculul suprafeţei totale de depozitare 23. Lucru cu structuri dinamice de date – liste, arbori. 24. Calcularea indicelui de preţ la consumatori 25. Efectul de substituţie şi efectul de venit de tip Slutsky 26. Calculul cotei de piaţă 27. Calculul rtmului modificărilor relative 28. Calculul rezultatului exerciţiului contabil al unei firme prin contul de profit şi pierdere 1. 2. 3. 4. 5. 6. 7. 8. 9.
49
29. Realizare repartiţiilor bazate pe generarea secvenţelor de numere aleatoare cu densitate de probabilitate f în probleme de simulare economică 30. Calculul abaterii individuale
50
Bibliografie [ATHA92] [IVAN96] [IVAN97] [IVAN98] [IVAN98a]
[IVAN99]
[IVAN02] [IVAN02a]
[MUSC97] [SOMN92]
Irina Athanasiu, Alexandru Panoiu, „Microprocesoarele 8086, 286, 386”, Editura Teora, Bucureşti, 1992. Ion Ivan, Cristian Codreanu, „Optimizarea programelor assembler”, ASE – Departamentul de Informatică Economică, Bucureşti, 1996. Ion Ivan, „Designul limbajelor de asamblare”, revista „Informatică Economică”, Nr.1/1997, Bucureşti. Ion Ivan, Cristian Codreanu, „Optimizarea programelor assembler”, revista „Informatică Economică”, Nr.6/1998, Bucureşti. Ion Ivan, Marian Dârdală, Gabriel Şutac, Valentin Dragomir, „Referirea datelor în structuri complexe prin proceduri assembler”, revista „Informatică Economică”, vol. III, Nr.7/1998, Bucureşti. Ion Ivan, Adrian Licuriceanu, Sebastian Teaciuc, Gheorghe Lupu, „Aplicaţii orientate obiect în limbaje de asamblare”, „Studii şi cercetări de calcul economic şi cibernetică economică”, Nr.3/1999, Bucureşti. Ion Ivan, Paul Pocatilu, Doru Cazan, „Practica dezvoltării software în limbaje de asamblare”, Editura Economică, Bucureşti 2002. Ion Ivan, Paul Pocatilu, Marius Popa, Cristian Toma, „Semnătura electronică şi securitatea datelor în comerţul electronic”, revista „Informatică Economică”, vol. VI, Nr.3/2002, Bucureşti. Gheorghe Muscă, „Programare în limbaj de asamblare”, Editura Teora, Bucureşti 1997. Dan Somnea, Vlăduţ Teodor, „Programarea în assembler”, Editura Tehnică, Bucureşti 1992.
51