Redirectarea intreruperilor 8086
Sistemele 8086 poseda un numar de 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).
Marea majoritate a intreruperilor BIOS sunt initializate la pornirea sistemului. La incarcarea sistemului de operare, acesta defineste/redefineste, la randul sau unele intreruperi pentru a putea asigura serviciile sistem care ii sunt specifice (ex. DOS rescrie rutina asociata intreruperii 21h pentru a implementa serviciile specifice sistemului de operare DOS).
Rutinele unor intreruperi soft (BIOS si DOS) pot trata in mod diferentiat intreruperea generata in functie de o anumita valoare specificata intr-un registru. Spunem ca intreruperea respectiva ofera mai multe servicii sau functii.
Avand un numar limitat de intreruperi si un numar mare de rutine care trebuiesc implementate, sistemele si aplicatiile utilizator folosesc in general urmatoarea conventie:
La apel in registrul AH se va depune numarul functiei care se va folosi.
In restul registrilor se pun parametrii necesarii executiei functiei respective (a se vedea documentatia=>NG)
Rutina de tratare a intreruperii va verifica la fiecare apel numarul functiei care trebuie apelata si va preda controlul rutinei in cauza.
1. Redirectarea intreruperilor
Pentru memorarea punctelor de intrare a celor 256 de intreruperi sunt folosite adresele de memorie de la 0000h:0000h =>0000h : 0400h(exclusiv). Adresa unui handler de intrerupere este formata din:
Adresa de segment pe 16 biti
Offset pe 16 biti.
Asadar adresa unui handler de interupere are nevoie de 2*16 biti = 32 biti ( 2 cuvinte = 4 octeti ) pentru a putea fi memorata. Pentru a memora 256 de adrese este nevoie de 1024 octeti, adica exact spatiul de memorie de la adresa 0000:0000 pana la 0000:0400h.
Pentru a redirecta un handler de intrerupere este suficient sa memoram in locatia de memorie, unde ii este stocat punctul de intrare, adresa noului punct de intrare pentru handler-ul intreruperii respective.
Ex1:
Pentru a redirecta intreruperea 10h (functii video) cu un handler scris de noi se vor stoca la adresele:
0000:[4*10h+2] => Adresa Segment Nou handler
0000:[4*10h] => Offset-ul handler.
Imediat dupa memorarea adresei noului handler, controlul va fi transferat catre acesta de fiecare data cand se va genera un apel catre intreruperea 10h.
In general redirectarea unei intreruperi presupune:
Salvarea adresei vechiului handler intr-o zona de memorie.
Setarea adresei noului handler pentru intrerupere.
Sistemul DOS poseda doua functii care permit obtinerea adresei unui handler de intrerupere (vezi int 21h functia 35h), respectiv setarea unui nou vector de intrerupere (int 21h, functia 25h).
Ex2: Pentru recuperarea adresei handlerului intreruperii 10h si redirectarea lui spre un handler utilizator:
Addr_int10 dd ?
mov ah, 3510h
int 21h ;intoarce in ES:BX adresa handler original
;salveaza adresa handler original
mov word ptr [addr_int10+2], ES
mov word ptr [addr_int10], BX
;instaleaza noul handler de intrerupere
mov ax, 2510h
;se presupune ca noul handler este in segmentul de cod current. (rutina scrisa de utilizator)
mov ax, cs
mov ds, ax
mov dx, offset <handler>
int 21h
; noul handler de intrerupere este setat
Pentru a putea scrie un handler de intrerupere DOS care functioneaza corect este necesar sa stim urmatoarele:
Apelul unui handler de intrerupere poate sa apara in orice moment in executia unui program (mai ales atunci cand este vorba de intreruperi sistem cum ar fi intreruperea de timp 08h sau cea de tastatura 09h, etc). In consecinta este necesar ca acesta sa aiba o durata de executie cat mai scurta in timp pentru a nu jena executia programului intrerupt. Deasemenea un handler nu trebuie sa corupa zonele de date si stiva programelor intrerupte.
Continutul registrilor trebuie pastrat (salvat) pentru a putea permite la terminarea handlerului reluarea normala a excutiei programului intrerupt.
La intrarea in rutina de tratare a handler-ului, stiva folosita este stiva programului intrerupt. Handlerul va folosi in consecinta stiva programului intrerupt. In cazul in care codul handlerului aloca mult spatiu de memorie in stiva este posibil sa depaseasca dimensiunea maxima a acesteia si sa corupa continutul stivei. Se va aloca o stiva proprie in acest caz.
Este nevoie sa luam in considerare cazul in care handlerul intreruperii este reapelat inca o data in timpul in care el se afla in tratarea unui eveniment anterior (trebuie scris astfel incat sa fie reentrant) => handlerul se intrerupe pe sine insusi. Este nevoie sa se salveze intregul context pentru a putea relua executia (variabilele locale specifice handler-ului).
Intreruperea 21h (functii DOS) nu este reentranta => daca un program este intrerupt in mijlocul unui apel al unei functii DOS si daca handler-ul nostru apeleaza la randul sau functii DOS, acest lucru va duce probabil la blocarea sistemului. Intreruperea 21h nu este reentranta datorita faptului ca foloseste o stiva statica proprie. Deci intreruperea unei functii DOS in curs de executie si apelarea unei alte functii DOS va duce la distrugerea continutului stivei pentru functia DOS intrerupta.
In cazul in care redirectarea unei intreruperi se face doar pentru a adauga functionalitate sau a modifica una din functiile intreruperii se va apela si handlerul original pentru tratarea cazurilor pe care handlerul nostru nu le ia in considerare.
La terminarea programului (in afara cazului in care acesta ramane rezident) este absolut necesara refacerea vectorilor de intrerupere modificati. In caz contrar sistemul de operare va apela in continuare handlerul a carui zona de memorie nu mai este alocata si care va fi cel mai probabil modificata la lansarea in executie a urmatorului program. Consecinta va fi inghetarea sistemului datorita transferului controlului executiei catre o locatie de memorie invalida.
;acest program redirecteaza functie 00H a intreruperii 2Fh
; Se redirecteaza intreruperea de fapt dar handlerul gestioneaza
; doar functia 00h. Restul functiilor sunt transmise handlerului original.
assume cs:cseg, ds:cseg
cseg segment
;adresa vechiului handler pentru intreruperea 2Fh
oldInt dd ?
;mesajul care se va afisa atunci cand se apeleaza functia 00H a intreruperii 2Fh
mesaj db 'Functia 00h a intreruperii 2Fh a fost redirectata',10,13,'$'
handler proc far
; inhiba intreruperile
cli
; testeaza daca functia apelata este functia 00h
cmp ah, 00h
; daca nu apeleaza handlerul original
jne orig
; Functia apelata este functia 00h
; salveaza pe stiva continutul registrilor ce
; vor fi eventual modificati
push ax
push bx
push dx
push ds
; pune in registrul ds adresa segementului de cod
; datele sunt stocate aici in segmentul de cod [OldInt si mesajul]
push cs
pop ds
; afiseaza mesaj folosind functia 09h a intreruperii 21h
mov ah, 09h
mov dx, offset mesaj
int 21h
; reface registrii modificati
pop ds
pop dx
pop bx
pop ax
sti
; intoarcere din handlerul intreruperii
iret
orig:
; apeleaza handlerul original printr-un apel far [seg]:[offset]
call dword ptr cs:[oldInt]
sti
; Return far. Nu folosim iret deoarece registrul de flag-uri
; a fost deja scos de pe stiva de handler-ul original
; prin iret. iret ar fi incorect aici deoarece ar mai realiza
; o operatie pop pt flag-uri de pe stiva, ori acestea nu mai
; exista pe stiva.
retf
handler endp
start:
mov ax, cseg
mov ds, ax
; obtine adresa handler-ului original al intreruperii
mov ax, 352Fh
int 21h
;salveaza adresa handler-ului original
mov word ptr [oldInt+2], es
mov word ptr [oldInt], bx
; inactiveaza intreruperile pe perioada modificarii adresei handlerului
cli
; seteaza noua adresa a handlerului intr. 2Fh
mov ax, 252Fh
mov dx, offset handler
;ds este setat deja pe cseg
int 21h
sti
; apel intrerupere 2Fh cu functia 00h Va fi apelat handler-ul nostru
mov ah, 00h
int 2Fh
; restaureaza handlerul original al intreruperii 2Fh
mov ax, 252Fh
mov dx, word ptr [oldInt]
mov bx, word ptr [oldInt+2]
mov ds, bx
int 21h
mov ax,4c00h
int 21h
cseg ends
end start
Lucrarea de laborator trebuie sa contina atit un nou handler de intrerupere cit si un program de test care sa apeleze intreruperea redirectata (daca este cazul).
La al saselea apel sa se refaca vechiul handler.
1. Sa se redirecteze intreruperea 15h. Noul handler va trebui sa verifice daca functia este 88h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'Nu exista memorie extinsa !'
2. Sa se redirecteze intreruperea 12h. Noul handler va trebui sa afiseze mesajul 'Memoria disponibila este ' si apoi cantitatea de memorie disponibila in Ko.
3. Sa se redirecteze intreruperea 18h. Noul handler va trebui sa afiseze mesajul 'Unde este interpretorul Basic ? '.
4. Sa se redirecteze intreruperea 08h. Noul handler va trebui sa afiseze mesajul 'Intreruperea de ceas a fost redirectata !' de 3 ori pe secunda.
5. Sa se redirecteze intreruperea 1Ah. Noul handler va trebui sa verifice daca functia este 00h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'S-a citit contorul de ceas !'
6. Sa se redirecteze intreruperea 1Ah. Noul handler va trebui sa verifice daca functia este 01h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'A fost redirectata intreruperea 1Ah !'
7. Sa se redirecteze intreruperea 14h. Noul handler va trebui sa verifice daca functia este 00h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 's-au initializat parametrii pentru COM1 !'
8. Sa se redirecteze intreruperea 14h. Noul handler va trebui sa verifice daca functia este 03h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'A fost redirectata intreruperea 14h !'
9. Sa se redirecteze intreruperea 13h. Noul handler va trebui sa verifice daca functia este 01h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'Discul curent este in starea :' si apoi mesajul corespunzator starii discului.
10.Sa se redirecteze intreruperea 13h. Noul handler va trebui sa verifice daca functia este 02h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'A fost redirectata intreruperea 13h !'
11.Sa se redirecteze intreruperea 17h. Noul handler va trebui sa afiseze mesajul 'Imprimanta este in starea :' si apoi mesajul corespunzator starii imprimantei.
12.Sa se redirecteze intreruperea 10h. Noul handler va trebui sa verifice daca functia este 0Fh, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'Modul video curent este :' si apoi mesajul corespunzator.
13.Sa se redirecteze intreruperea 10h. Noul handler va trebui sa verifice daca functia este 00h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'A fost redirectata intreruperea 10h !'
14.Sa se redirecteze intreruperea 10h. Noul handler va trebui sa verifice daca functia este 02h, daca nu sa se apeleze vechiul handler iar daca da, sa afiseze mesajul 'Pozitia cursorului a devenit' urmat de noua pozitie a cursorului.
15.Sa se redirecteze intreruperea 00h. Noul handler va trebui sa afiseze mesajul 'S-a redirectat intreruperea 00h'.
Politica de confidentialitate |
.com | Copyright ©
2024 - Toate drepturile rezervate. Toate documentele au caracter informativ cu scop educational. |
Personaje din literatura |
Baltagul – caracterizarea personajelor |
Caracterizare Alexandru Lapusneanul |
Caracterizarea lui Gavilescu |
Caracterizarea personajelor negative din basmul |
Tehnica si mecanica |
Cuplaje - definitii. notatii. exemple. repere istorice. |
Actionare macara |
Reprezentarea si cotarea filetelor |
Geografie |
Turismul pe terra |
Vulcanii Și mediul |
Padurile pe terra si industrializarea lemnului |
Termeni si conditii |
Contact |
Creeaza si tu |