Documente Academic
Documente Profesional
Documente Cultură
Întrerupere = acțiune a microprocesorului prin care acesta anunță apariția unui eveniment.
Pot exista maxim 256 de intreruperi. Fiecare intrerupere are asociata o rutina de cod numita Rutina de
Tratare a intreruperii (RTI), care se executa la aparitia intreruperii respective. Nu sunt definte toate cele
256 de intreruperi (nu exista rutine asociate cu toate cele 256 de intreruperi).
In functie de cauzele care genereaza aparitia unui semnal de intrerupere, acestea se pot clasifica in:
1. intruperi externe microprocesorului: apasarea unei taste, terminarea unei operatii de intrare/iesire
2. intreruperi interne microprocesorului: impartirea la zero, tentativa de adresare a unei zone de
memorie care nu exista, tentativa de executarea a unei instructiuni care are cod inexistent
De obicei, dupa tratarea unei intreruperi externe programul se reia, dar dupa o intrerupere interna nu!
In functie de nivelul la care sunt definite intreruperile in cadrul sistemul de calcul acestea se pot clasifica
astfel:
1. intreruperi hard. Rutinele acestor intreruperi sunt scrise de proiectantii de calculatoare si se afla
memorate in cipurile fizice ale calculatorului.
Ex:
• intreruperea 00h – se genereaza ca urmare a unei tentative de impartire la 0
• intreruperea 01h – se apeleaza dupa fiecare instructiune masina daca este setat TF
(TrapFlag = 1). Este folosita de depanatoare gen Turbo Debuger.
2. intreruperi BIOS. Rutinele acestor intreruperi sunt scrise de proiectantii BIOS-ului calculatorului.
Ex:
• intreruperea 11h – ofera informatii despre echipamentele instalate in sistem
• intreruperea 12h – informatii despre dimensiunea memoriei RAM
3. intreruperi DOS. Rutinele acestor intreruperi sunt scrise de proiectantii sistemului de operare.
Ex:
• intreruperea 20h – terminarea unui program.
• intreruperea 21h – ofera toate functiile sistem oferite de sistemul de operare DOS
• intreruperea 33h – lucrul cu mouse-ul
Rutinele unor intreruperi soft (BIOS si DOS) pot trata in mod diferentiat intreruperea generata in functie
de o anumita valoare specificata in registrul AH. Spunem ca intreruperea respectiva ofera mai multe
“servicii” sau “functii”.
Efectul acestui grup de instructiuni este afisarea caracterului ‘A’ la iesirea standard.
Observatii:
• Lista completa a tuturor intreruperilor si a functiilor oferite de acestea se gaseste in Norton
Guide. Este recomandata o parcurgere prealabila (lecturare si nu memorare) a tuturor
intreruperilor si functiilor. Nu se cerere memorarea tuturor intreruperilor si a functiilor, dar
studentul trebuie sa stie sa caute in documentatia electronica suportul pentru a rezolva un anumit
tip de problema.
• Unele intreruperi figureaza in documentatii ca “rezervate” sau “nedocumentate”. Este vorba de
intreruperi pentru care proiectantii lor (autorii rutinelor de tratare) nu au facut publice specificatii,
fie ca utilizarea lor poate duce la actiuni neprevazute, fie ca actiunea intreruperii respective se
poate schimba de la o versiune la alta a sistemului de operare sau BIOS-ului calculatorului. Se va
evita folosirea acestor intreruperi.
• Unele intreruperi s-ar putea sa nu functioneze conform asteptarilor in mediile Windows.
Intreruperea 21h
Principala intrerupere DOS este intreruperea 21h, deoarece ne da acces la toate functiile DOS:
• Functii de intrare/iesire cu periferice de tip caracter
• Functii specifice directoarelor si fisierelor
• Functii de gestiune a memoriei
• Functii de gestiune a proceselor
• Functii specific discului
• Informatii despre sistem, etc.
• 01h – citeste un caracter de la intrarea standard si il afiseaza la iesirea standard (citire cu ecou)
La intrare: AH = 01h
Returneaza: AL = codul ASCII al caracterului citit
• 0Ah – citeste de la intrarea standard un sir de caractere pana la tastarea lui Enter
La intrare: AH = 0Ah
DS:DX = adresa de inceput a zonei de citire. Structura acesteia este descrisa
mai jos (nrMaxim trebuie completat la intrare).
Returneaza: completeaza nrCitite si spatiuCitire conform observatiilor de mai jos
Zona de citire este o zona de memorie (sir de bytes alaturati) cu urmatoare structura:
nrMaxim, nrCitite, spatiuCitire
unde:
− nrMaxim este primul octet si contine lungimea maxima a sirului care se citeste (inclusive
Enter). Acest octet trebuie completat inainte de efectuarea operatiei de citire cu un numar
din intervalul [0,255]
− nrCitite este al doilea octet si este neinitializat inainte de operatia de citire
− spatiuCitire este zona de memorie rezervata pentru caracterele care vor fi citite de la
instrarea standard. Incepe de la al treilea octet (offset 2) din cadrul zonei de citire si este
de lungime nrMaxim
Probleme:
1. Sa se afiseze un numar in baza 2, 10 si 16.
Soluţie: Orice problemă de afişare a unei valori numerice implică generarea şirului de caractere
corespunzător valorii numerice. În cazul nostru, va fi vorba despre generarea şirului corespunzător în baza
2, 10 sau 16. De exemplu, dacă în AX se va afla valoarea 31762, va fi vorba despre generarea şirului
’111110000010010’ pentru baza 2, ’31762’ pentru baza 10 repsectiv ’7C12’ pentru baza 16.
zece dw 10
tabela db '0123456789ABCDEF'
nr dw 145
data ends
code segment
start: ;eticheta de start
push data
pop ds ;încărcarea registrului segment ds cu adresa de început a
;segmentului de date data
;vom obţine fiecare bit din configuraţia binară a conţinutului registrului ax. Pentru aceasta vom folosi
;instrucţiuni pe biţi pentru a deplasa spre stânga cu câte o poziţie întreaga configuraţie; după fiecare
;deplasare, bitul obţinut în CF (întotdeauna bitul care iese din configuraţie) va fi afişat pe ecran.
mov cx, 16 ;dorim să obţinem configuraţia binară a unui cuvânt (bx), deci va trebui
;să efectuăm 16 deplasări spre stânga
Repeta2:
shl bx, 1
jc unu ;daca CF=1, se face salt la o etichetă unde se afişează caracterul ’1’
mov ah, 02h ;pentru afişarea caracterelor folosim funcţia 02h a întreruperii 21h:
mov dl, '0' ;în dl vom pune codul ASCII al caracterului de afişat
int 21h ;prin apelul int 21h cu ah=02h se declanşează afişarea caracterului cu
;codul ASCII valoarea din dl
jmp EndAfis2
unu:
mov ah, 02h
mov dl, '1'
int 21h
loop Repeta2
EndAfis2: ;după afişarea numărului, indiferent în ce bază, se va afişa o linie ;nouă
mov ah, 09h ;în acest scop se va folosi funcţia 09h a întreruperii 21h,
mov dx, offset LinieNoua ;funcţie de afişare a unui şir; în cazul acesta, şirul
;În cazul afişării unei valori în baza 10, trebuie să facem distincţia între ax conţinând un număr negativ şi
;ax conţinând un număr pozitiv. Aceasta deoarece obţinerea cifrelor din reprezentarea zecimală a unui
;număr se face diferit dacă numărul este negativ. Şi anume: dacă numărul este pozitiv, prin împărţiri
;succesive la 10 obţinem cifrele din reprezentarea sa zecimală, iar dacă numărul este negativ, o metodă
;de a determina cifrele zecimale este obţinerea valorii absolute a acestui număr, urmată apoi de împărţiri
;succesive la 10.
cmp bx, 0
jge pozitiv ;jge (jump if greater or equal) cauzează saltul la eticheta pozitiv dacă valoarea din
;registrul ax este mai mare sau egală cu 0
negativ:
neg bx ;dacă în interpretarea cu semn valoarea din ax este strict negativă, prin
;negativare vom obţine modulul numărului negativ
mov dl, '-' ;afişăm caracterul '-' ca semn al numărului zecimal negativ pe care îl vom
;afişa mai jos
int 21h
;vom executa în continuare codul scris pentru cazul în care numărul este pozitiv
;pentru obţinerea cifrelor zecimale, vom face împărţiri succesive la 10 ale numărului aflat în ax,
;despre care ştim acum că este pozitiv. Înainte de a face împărţirea, trebuie să fim atenţi la
;următoarea situaţie: ştim că prin împărţirea unui cuvânt la un octet, câtul va fi un octet (obţinut
;în al). Ce se întâmplă dacă prin împărţirea la 10 a cuvântului din ax, câtul obţinut nu încape în al?
;De exemplu, în cazul împărţirii fără semn 3000:10=300>255 (cel mai mare număr fără semn
;reprezentat pe 1 octet). Într-o astfel de situaţie, asamblorul va semnala depăşirea prin emiterea
;întreruperii 0 şi afişarea mesajului de eroare „Divide by zero”. Pentru a evita această situaţie, se
;recomandă extinderea cuvântului la dublucuvânt, şi împărţirea dublucuvântului la cuvântul 10.
În ;urma unor astfel de conversii câtul va încăpea sigur în dimensiunea de reprezentare alocată.
pozitiv:
mov ax,bx ;mutam numarul in ax pentru impartiri
Repeta10:
mov dx, 0 ;deoarece în acest moment interpretăm numărul din ax ca fiind
;pozitiv, pentru a-l extinde la dublucuvânt completăm registrul
;dx cu valoarea 0 (conversie fără semn)
div zece ;în urma împărţirii la 10, câtul se obţine în ax şi restul în dx;
;deoarece restul nu poate fi un număr strict mai mare decât 9,
;este suficient un octet pentru reprezentarea sa. Ca urmare,
;valoarea restului va fi un număr reprezentat pe octetul mai puţin
;semnificativ al lui dx, adică dl
;s-a putut observa că cifrele obţinute sunt reţinute în primă fază în stivă, fără a fi afişate direct pe măsură
;ce sunt obţinute motivul este faptul că prin împărţiri succesive la 10, cifrele numărului se obţin în ordine
;inversă punându-le în stivă în ordinea în care sunt obţinute, şi cunoscând numărul lor, reţinut în cx, în
;momentul în care le vom scoate din stivă le vom avea în ordinea corectă (datorită principiului Last In First
;Out)
RepetaAfis: ;în acest moment avem reţinute în stivă toate valorile cifrelor de
;afişat; numărul lor este reţinut în cx
add dl, '0' ;în dl generăm codul ASCII al caracterului pe care dorim să-l
;afişăm
;vom face afişarea cifrei folosind funcţia de afişare a unui caracter (funcţia 02h, int 21h); pentru a face
;transformarea cifrei în caracterul corespunzător ei (ex. 2 => ’2’), vom aduna la această cifră codul ASCII
;al caracterului ’0’, obţinând astfel codul ASCII al caracterului corespunzător cifrei; de exemplu, adunând
;la numărul 2, format dintr-o singură cifră, codul ASCII al ;caracterului ’0’, care este 48, obţinem codul
;ASCII 50 al caracterului ’2’
;după cum se poate observa, ’0’ din instrucţiunea add dl, ’0’ are semnificaţia de „codul ASCII al
;caracterului 0” (instrucţiunea add dl, 48 ar avea acelaşi efect, deoarece codul ASCII al ;caracterului ’0’
;este 48)
loop RepetaAfis
;după afişarea numărului, indiferent în ce bază, se va afişa o linie ;nouă
mov ah, 09h ;în acest scop se va folosi funcţia 09h a întreruperii 21h,
mov dx, offset LinieNoua ;funcţie de afişare a unui şir; în cazul acesta, şirul
;ştim ca fiecărui grup de 4 biţi din reprezentarea binară a unui număr, îi corespunde o cifră hexa pornind
;de la acest lucru, vom face afişarea în baza 16 a numărului din ax prin afişarea cifrelor hexa
;corespunzătoare celor 4 grupuri de câte 4 biţi din reprezentarea binară a cuvântului din ax.
;vom folosi un registru (dx de exemplu, deoarece este disponibil) pentru obţinerea la un moment dat a
;unui grup de 4 biţi, adică a unei cifre hexa; iniţial acest registru are valoarea 0;
;vom izola un grup de 4 biţi din ax prin rotirea cuvântului spre stânga (rol) de 4 ori cu câte o ;poziţie. După
;fiecare astfel de rotire, ştiind că bitul care iese din configuraţie este reţinut în CF, vom face o rotire spre
;stânga cu carry (rcl) a configuraţiei din registrul dx, pentru a introduce în dx biţii care ies din ax, în aceeaşi
;ordine.
;după repetarea de 4 ori a secvenţei „rotire spre stânga a lui ax – rotire spre stânga cu carry a lui ;dx”, în
;registrul dx (mai precis în semioctetul inferior al registrului dl) vom avea cifra hexa corespunzătoare unui
;grup de 4 biţi.
Repeta16:
mov dx, 0 ;registrul folosit pentru izolarea a câte unui grup de 4 biţi
Repeta4:
rol ax, 1
rcl dx, 1
loop Repeta4
pop cx ;restaurăm valoarea lui cx necesară pentru bucla principală
;Repeta16
push ax ;salvam valoarea cuvantului ax deoarece vom avea nevoie de
registrul al la utilizarea instructiunii xlat
mov al, dl ;cifra hexa obţinută în dx este un număr mai mic decât 16, deci
încape în dl, octetul mai puţin semnificativ al cuvântului dx
mov bx, offset tabela ;pentru ca instrucţiunea xlat să poată folosi tabela de
;translatare de la adresa ds:bx
xlat tabela
;pentru fiecare cifră hexa se obţine caracterul corespunzător prin intermediul instrucţiunii xlat.
;Instrucţiunea xlat transformă octetul curent din al într-un alt octet, utilizând în acest scop o tabelă de
;corespondenţă furnizată de utilizator (în cazul nostru tabela) numită tabelă de translatare. Adresa
;tabelei este furnizată în cazul nostru în ds:bx. Efectul instrucţiunii xlat este înlocuirea octetului din al cu
;octetul din tabelă ce are indexul valoarea din al (primul octet din tabelă are indexul 0): alds:[bx+al]
;Se va aduna la offset-ul şirului tabela un număr de octeţi egal cu numărul din al, unde noi am pregătit
;chiar cifra hexa pe care dorim să o afişăm; în al se va obţine caracterul corespunzător cifrei; de exemplu,
;dacă numărul din al este 12 (în baza 10), adunând 12 la offset-ul tabelei obţinem în al caracterul ’C’, care
;este cifra hexa corespunzătoare de afişat pentru valoarea numerică 12
int 21h
pop ax ;restaurare valoare ax
loop Repeta16
Sfarsit: ;după afişarea numărului, indiferent în ce bază, se va afişa o linie
;nouă
mov ah, 09h ;în acest scop se va folosi funcţia 09h a întreruperii 21h,
mov dx, offset LinieNoua ;funcţie de afişare a unui şir; în cazul acesta, şirul
code ends
end start