Sunteți pe pagina 1din 8

Înreruperi

Î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).

La aparitia unei intreruperi au loc urmatoarele actiunii:


• suspendarea programului in curs de executie
• lansarea in executie a rutinei de tratare a intreruperi respective
• reluarea executiei programului suspendat (in majoritatea cazurilor)

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

4. intreruperi definite de programatori.

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”.

Instructiunea INT, sintaxa:


INT n
provoaca activarea handlerului corespunzator intreruperii cu numarul n.
Exemplul 1: Functia 02h a intreruperii 21h permite afisarea unui caracter pe ecran. Intreruperea asteapta
in registrul AH codul functiei (02h) iar in registrul DL, codul ASCII al caracterului pe care dorim sa il
tiparim la iesirea standard. Modul de apel este:

mov ah, 02h


mov dl, ‘A’
int 21h ; instructiunea 'int' cere procesorului sa genereze intreruperea 21h

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.

Functii de intrare/iesire cu periferice de tip caracter

• 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

• 02h – afiseaza un caracter la iesirea standard


La intrare: AH = 02h
DL = codul ASCII al caracterului de tiparit
Returneaza: nimic

• 08h – citire de caracter fara ecou


La intrare: AH = 08h
Returneaza: AL = codul ASCII al caracterului citit
• 09h – tipareste un sir de caractere la iesirea standard. Acest sir de caractere trebuie sa contina ca
si marcaj de sfarsit de sir caracterul ‘$’. Acest caracter nu va fi tiparit.
La intrare: AH = 09h
DS:DX = adresa de inceput a sirului de tiparit
Returneaza: nimic

• 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.

assume cs: code, ds:data


data segment
LinieNoua db 10,13,'$';<LF>, <CR>, ’$’

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

;urmeaza afisarea in baza 2 a numărului conţinut de nr.

;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 bx, nr ;salvăm conţinutul numarului nr în bx

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’

;altfel, înseamnă că CF=0, deci afişăm caracterul ’0’

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

loop Repeta2 ;bucla se execută de CX ori, în cazul nostru de16 ori

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

int 21h ;de tipărit va fi format din caracterele 10 şi 13 a căror combinaţie


;cauzează trecerea la linie nouă, şi caracterul ’$’ pentru marcarea
;sfârşitului de şir la afişare
;urmează afişarea în baza 10 a numărului conţinut de nr.

;Î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.

mov bx,nr ;refacem valoare lui bx

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

mov ah, 02h ;funcţia de tipărire a unui caracter

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

mov cx, 0 ;folosim cx pentru a reţine numărul cifrelor obţinute

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

push dx ;reţinem în stivă cifra obţinută (push dl ar fi incorect deoarece


;stiva este organizată pe cuvinte)

inc cx ;creştem cu 1 valoarea lui cx deoarece am mai găsit o cifră

cmp ax, 0 ;seria împărţirilor succesive la 10 se termină în

jne Repeta10 ;momentul în care obţinem un cât egal cu zero

;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

pop dx ;extragem valoarea cifrei curente din stivă în registrul dx

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)

mov ah, 02h


int 21h ;afişarea cifrei curente

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

int 21h ;de tipărit va fi format din caracterele 10 şi 13 a căror combinaţie

;cauzează trecerea la linie nouă, şi caracterul ’$’ pentru marcarea


;sfârşitului de şir la afişare

;urmează afişarea în baza 16 a numărului conţinut de nr.

;ş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.

mov ax, nr ;refacem valoarea lui ax

mov cx, 4 ;numărul de grupuri de câte 4 biţi ale cuvântului din ax

Repeta16:
mov dx, 0 ;registrul folosit pentru izolarea a câte unui grup de 4 biţi

push cx ;salvăm cx, deoarece este nevoie de acest registru şi în


;următoarea buclă (care foloseşte de asemenea loop)

mov cx, 4 ;numărul de biţi ce formează o cifră hexa

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): alds:[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

mov dl, al ;afişarea caracterului obţinut se face cu funcţia 02h

mov ah, 02h ;a întreruperii 21h

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

int 21h ;de tipărit va fi format din caracterele 10 şi 13 a căror combinaţie


;cauzează trecerea la linie nouă, şi caracterul ’$’ pentru marcarea
;sfârşitului de şir la afişare

mov ax, 4C00h ;funcţia 4Ch a întreruperii 21h cauzează terminarea

int 21h ;programului; în ah se pune codul de retur (00h în cazul nostru)

code ends
end start

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