Houssey
Moderator
 Din: Buzau
Inregistrat: acum 18 ani
Postari: 260
|
|
1. Obiectivele lucrarii Lucrarea urmareste prezentarea introductiva a modului de lucru cu întreruperile al microprocesoarelor 8086/88, punându-se accent pe evidentierea unor tehnici de implementare a programelor în limbaj de asamblare, ce folosesc apeluri de sistem DOS. Se au în vedere functiile sistem pentru gestiunea operatiilor de I/E, memoriei si proceselor.
2. Aparatura si suporturile utilizate
• PC în configuratia: unitate centrala, monitor, tastatura, mouse; • Precizarile din prezentul îndrumar;
3. Breviar teoretic
Sistemul de întreruperi
Actiunea provocata de îndeplinirea unei conditii (interna sau externa în raport cu programul aflat în executie) prin care se realizeaza automat transferul controlului unei rutine speciale de tratare se numeste întrerupere, iar rutina respectiva se numeste rutina de întrerupere. Exista doua clase de întreruperi: • întreruperi interne: acestea sunt initiate de starea programului aflat în executie sau prin executarea unor instructiuni speciale de întrerupere. Ele se caracterizeaza prin faptul ca sunt sincrone în raport cu programul aflat în executie. Se mai numesc întreruperi software. • întreruperi externe: acestea sunt initiate de partea hardware prin intermediul semnalelor de întrerupere trimise catre procesor. Declansarea lor semnifica îndeplinirea unor evenimente externe procesorului. Ele se caracterizeaza prin faptul ca sunt asincrone în raport cu programul aflat în executie. Se mai numesc întreruperi hardware. O rutina de întrerupere este asemanatoare unei proceduri în sensul ca dupa executia ei se revine în programul întrerupt la instructiunea imediat urmatoare celei întrerupte. Modalitatea de declansare a unei rutine de întrerupere este în general diferita de apelul unei proceduri, existând însa, pentru anumite clase de întreruperi si similitudini (la microprocesoarele 8086/88 exista aproape o similitudine perfecta între apelul procedurilor îndepartate si instructiunile de întrerupere). Ca element comun, notam necesitatea salvarii contextului programului întrerupt (cuvânt de stare program, numarator de program, registre generale) la intrarea în rutina de întrerupere. Deoarece anumite întreruperi sunt initiate de evenimente externe procesorului, asincrone în raport cu programul aflat în executie, acesta nu le poate transmite nici un fel de parametrii, comunicatiile de date putând avea loc numai utilizând variabile direct accesibile ambelor secvente de program: secventa curent executabila si rutina de întrerupere. Actiunile ce rezulta în urma aparitiei unei întreruperi si care determina transferul controlului rutinei de întrerupere poarta numele de secventa de întrerupere. Secventa de întrerupere specifica microprocesoarelor 8086/88 este urmatoarea: 1. Se salveaza valorile curente ale psw , cs si ip în stiva; 2. Se încarca perechea de registre cs:ip dintr-un pointer determinat pe baza unei valori calculata folosind tipul întreruperii, si anume, daca n este tipul întreruperii, valoarea calculata este 4*n. Pointerul ce contine noile valori ale registrelor cs si ip se numeste vector de întrerupere; 3. Se sterg flagurile if si tf. Noile continuturi ale registrelor cs si ip determina adresa de început a rutinei de întrerupere. Tipul întreruperii este un numar întreg în gama 0..255. Adresa vectorului de întrerupere rezulta prin înmultirea tipului întreruperii cu 4. Primele 5 tipuri de întrerupere, si anume 0, 1, 2, 3 si 4, au semnificatii speciale predefinite: a. tipul 0 este utilizat pentru tratarea erorii de împartire la zero. Daca se realizeaza o împartire la zero se declanseaza automat o întrerupere cu tipul 0. O astfel de situatie poate apare ori de câte ori, dupa executarea unei instructiuni idiv sau div, câtul are o depasire de format, oricare ar fi valoarea flagului if ; b. tipul 1 este utilizat pentru executarea programelor în regim “pas cu pas”. Daca flagul tf este setat, se va declansa automat o întrerupere cu tipul 1 la sfârsitul fiecarei instructiuni executate de procesor. Deoarece flagul tf este sters în urma secventei de întrerupere, nu vor fi declansate întreruperi si dupa instructiunile din rutina de întrerupere; c. tipul 2 este utilizat de catre întreruperea nemascabila. Întreruperea nemascabila este o întrerupere externa care poate apare indiferent de starea flagului if. d. tipul 3 este rezervat unei instructiuni speciale de întrerupere cu lungimea de un octet cu codul 0cc. Aceasta instructiune este utilizata pentru implementarea facilitatii de executare a unui program cu puncte de oprire (breakpoint) din cadrul programelor depanatoare (debugger). e. tipul 4 este utilizat pentru tratarea depasirilor. Daca se executa o instructiune into când flagul of este setat, se va declansa o întrerupere cu tipul 4.
Întreruperi DOS
Un sistem de operare permite utilizatorului controlul asupra sistemului de calcul; el poate fi definit ca o colectie de proceduri si programe. Aceste proceduri pot fi apelate din programele utilizatorului si permit acestuia accesul la resursele calculatorului, memorie si periferice, precum si la o serie de informatii care descriu contextul curent în care functioneaza calculatorul. Exista doua tipuri de servicii DOS: întreruperi si functii. Functiile DOS se apeleaza cu întreruperea 21h (INT 21h) si numarul functiei în registrul AH, în timp ce celelalte întreruperi DOS se apeleaza prin întreruperi software: INT n. Rutinele pe care sistemul de operare DOS le utilizeaza pentru gestiunea resurselor calculatorului pot fi apelate din programele scrise în limbaj de asamblare. Aceste rutine se mai numesc apeluri sistem (system calls). Utilizarea apelurilor sistem de catre programele de aplicatie permite obtinerea de programe independente de masina fizica, garantându-se compatibilitatea acestora cu versiunile superioare ale sistemului de operare DOS. Instructiunile de întrerupere cu tipurile 20,..., 3f sunt rezervate apelurilor sistem. Majoritatea apelurilor sistem sunt grupate la întreruperea cu tipul 21. Aceste apeluri sunt cunoscute sub numele de functii sistem. Pentru executarea unui apel sistem se procedeaza astfel: • se transfera parametrii apelului în registrele procesorului. Parametrii împreuna cu registrele corespunzatoare sunt specifici fiecarui apel în parte; • se executa instructiunea int cu tipul corespunzator apelului respectiv. Pentru executarea unei functii sistem se procedeaza astfel: • se transfera parametrii functiei în registre; • se transfera numarul functiei în registrul ah; • se transfera un cod suplimentar, daca acest lucru este cerut de functia respectiva in registrul al; • se executa instructiunea int 21h. Majoritatea functiilor sistem seteaza flagul cf daca a aparut o eroare, codul de eroare fiind returnat în registrul ax. Principalele functii sistem pot fi grupate în urmatoarele categorii:
a. Functii pentru operatiile de I/E standard, specifice urmatoarelor dispozitive de I/E: consola, imprimanta, interfata seriala. Daca un program foloseste pentru implementarea operatiilor de I/E aceste functii, intrarea respectiv iesirea sa pot fi redirectate. Dintre aceste functii, de mentionat sunt urmatoarele: Functia 01: aceasta functie citeste un caracter de la intrarea standard, pe care îl trimite în ecou la iesirea standard. Daca caracterul citit este CTRL-C, se executa int 23h. La apel (ah)=01, si dupa executie (al)=codul ASCII al caracterului citit. Ex: mov ah,1 int 21h
Functia 02: aceasta functie scrie un caracter la iesirea standard. Daca se tasteaza CTRL-C, se executa int 23h. La apel (ah)=02, (dl)=codul ASCII al caracterului care trebuie scris. Ex: mov dl,cod_ASCII_caracter mov ah,2 int 21h
Functia 07: aceasta functie citeste un caracter de la intrarea standard. Caracterul citit nu este trimis în ecou la iesirea standard, si nu se efectueaza nici un test pentru CTRL-C. La apel (ah)=07 si dupa executie (al)=codul ASCII al caracterului citit. Ex: mov ah,7 int 21h
Functia 09: aceasta functie realizeaza afisarea unui sir de caractere la iesirea standard, sirul de caractere fiind terminat cu '$'. Caracterul '$' nu se afiseaza. La apel (ah)=09, (ds):(dx)=adresa de început a sirului de caractere respectiv.
Ex: lea dx,sir mov ah,9 int 21h
Functia 0A: aceasta functie realizeaza citirea unui sir de caractere de la intrarea standard. La apel (ah)=0A, (ds):(dx)=adresa unei zone tampon cu urmatoarea structura: • primul octet al zonei va contine la apel numarul maxim (fie acesta n) de caractere care vor fi citite, inclusiv un caracter CR; • al doilea octet al zonei va contine dupa executia functiei numarul de caractere efectiv citite, caracterul CR nefiind contorizat; • restul zonei va trebui sa contina cel putin atâtia octeti câti au fost specificati în primul octet. Dupa executia functiei aici va fi depus sirul citit, primul caracter din sir fiind plasat la adresa cea mai mica. Caracterele citite sunt plasate în zona tampon specificata, începând cu al treilea octet al zonei. Citirea se termina când se tasteaza CR. Daca se încearca introducerea mai multor caractere decât numarul specificat, adica n-1, caracterele în plus se ignora, fiind trimis la iesirea standard caracterul BEL (07). Ultimul caracter din zona tampon este întotdeauna CR. Daca se tasteaza CTRL-C, se executa int 23h. Ex: lea dx,sir mov sir,nr_car mov ah,0Ah int 21h
b. Functii pentru gestiunea memoriei Sistemul de operare DOS tine evidenta blocurilor de memorie alocate prin scrierea la începutul fiecaruia a unei înregistrari numita bloc de control al memoriei (Memory Control Block, MCB) ce contine informatii referitoare la dimensiunea blocului în numar de paragrafe (1 paragraf=16 octeti) si un pointer la urmatorul bloc, daca exista. Dintre functiile pentru gestiunea memoriei le mentionam pe urmatoarele: Functia 4816: prin aceasta functie, procesul aflat în executie poate cere alocarea unei cantitati de memorie, specificata în numar de paragrafe. La apel (ah)=48, (bx)=numarul de paragrafe cerute. Daca la retur (cf)=1, înseamna ca a aparut o eroare, codul de eroare fiind specificat în registrul ax, si anume: daca (ax)=7 înseamna ca s-a alterat un MCB, iar (ax)=8 înseamna ca nu exista suficienta memorie pentru alocare. În registrul bx se obtine numarul de paragrafe disponibile. Daca la retur (cf)=0, înseamna ca alocarea s-a efectuat cu succes, în registrul ax întorcându-se adresa de segment a zonei de memorie alocata. Ex: mov bx,numar_octeti mov cl,4 shr bx,cl inc bx int 21h
Functia 49 aceasta functie elibereaza un bloc de memorie alocat anterior cu functia 48 La apel (ah)=49, (es)=adresa de segment a blocului respectiv. Daca la retur (cf)=1 înseamna ca a aparut o eroare, codul de eroare fiind specificat în registrul ax, si anume: (ax)=7 înseamna alterarea MCB-ului, iar (ax)=9 înseamna ca se doreste eliberarea unui bloc ce nu a fost alocat corect (cu functia 4816). Daca la retur (cf)=0 înseamna ca eliberarea s-a facut cu succes. Ex: mov ax,adresa_segment mov es,ax mov ah,9 int 21h
Functia 4A: aceasta functie modifica dimensiunea unui bloc de memorie alocat anterior. La apel (ah)=4A, (bx)=noua dimensiune a blocului în numar de paragrafe. Daca la retur (cf)=1, înseamna ca a aparut o eroare, codul de eroare fiind specificat în registrul ax, si anume (ax)=7 înseamna alterarea MCB-ului, (ax)=8 înseamna memorie insuficienta (în situatia în care s-a dorit marirea dimensiunii blocului), iar (ax)=9 înseamna ca se doreste modificarea dimensiunii unui bloc de memorie ce nu a fost alocat corect. Daca (ax)=8, registrul bx va contine numarul de paragrafe disponibile. Daca la retur (cf)=0 înseamna ca modificarea dimensiunii blocului s-a facut cu succes. Ex: lea bx,ultimul_octet mov cl,4 shr bx,cl add bx,17 mov ah,4Ah int 21h mov ax,bx shl ax,cl
c. Functii pentru gestiunea proceselor Functia 4B: aceasta functie realizeaza încarcarea si executia unui program, respectiv încarcarea unui overlay, fara executarea acestuia, în functie de un cod suplimentar, ce poate avea valoarea 0, respectiv 3. Un overlay este o portiune de program ce se pastreaza pe disc, fiind încarcata în memoria principala pentru executie la cererea utilizatorului, datorita spatiului limitat al acesteia. În cele ce urmeaza se prezinta doar functia de încarcare si executie a unui program, cunoscuta si sub numele de functia load and execute. La apel (ah)=4B, (al)=0, (ds):(dx)=adresa unui sir de caractere terminat cu caracterul NUL (codul ASCII 0) ce reprezinta calea catre un fisier ce contine programul executabil, iar (es):(bx)=adresa unui bloc de parametrii (EXEC Parameter Block, EPB). Când un program utilizeaza aceasta functie pentru încarcarea si executarea altui program, sistemul de operare DOS aloca memoria necesara si creeaza un bloc de date numit prefixul segmentului programului (Program Segment Prefix, PSP) la offsetul 0 în cadrul blocului de memorie alocat programului, încarca noul program si îi paseaza controlul. Adresa de segment a PSP se depune în registrele segment ds si es. Noul program are responsabilitatea ca la terminarea sa sa execute o functie sistem pentru retransmiterea controlului programului apelant. Programul apelant se numeste program parinte si programul încarcat si executat sub controlul programului parinte se numeste program copil. Linia de comanda se specifica sub forma unui sir de octeti ce cuprinde: • primul octet este lungimea liniei, caracterul CR de terminare nefiind contorizat; • urmeaza sirul de caractere ce compune linia de comanda propriu-zisa; • ultimul octet din sir este caracterul CR. Spre exemplu pentru lansarea programului command.com cu linia de comanda: command /c dir /w ce are ca efect executarea unei copii a command.com si sub aceasta copie a unei comenzi dir /w, sirul corespunzator liniei de comanda se va defini astfel: cmd_line DB 9,'/c dir /w',0dh Pentru ca programul copil sa poata fi încarcat trebuie sa existe suficienta memorie principala disponibila. Sistemul de operare DOS aloca toata memoria principala disponibila unui program în momentul încarcarii sale. Când un program parinte realizeaza încarcarea si executarea unui program copil, trebuie sa elibereze o portiune de memorie utilizând functia 4A, înaintea apelului pentru încarcarea si executarea programului copil. În urma executarii apelului toate fisierele deschise devin disponibile noului program încarcat, programul parinte având astfel controlul definirii intrarii si iesirii standard, auxiliare si al dispozitivelor de imprimare. Facem observatia ca în urma executarii apelului, toate registrele se distrug, incluzând registrele ss si sp. Daca flagul cf este setat în urma executarii apelului, înseamna ca a aparut o eroare, codul de eroare fiind întors în registrul ax. Programul copil primeste de asemenea un mediu (environment), ce reprezinta o secventa de siruri de caractere (sirurile de caractere din cadrul mediului DOS curent se pot afisa la terminal cu comanda DOS set), terminate fiecare cu caracterul NUL, de forma parametru=valoare (spre exemplu VERIFY=ON). Mediul trebuie sa înceapa la o adresa de paragraf, sa nu depaseasca 32 Kocteti si sa fie terminat cu caracterul NUL. Dupa ultimul caracter NUL se afla o multime de argumente pasate programului copil, care constau din: un contor pe cuvânt (în mod normal egal cu 1) urmat de o secventa de siruri de caractere terminate fiecare cu caracterul NUL, numarul de siruri fiind indicat de contor (în mod normal un sir). Daca apelul gaseste fisierul cu programul executabil în directorul curent, sirul de caractere contine unitatea si calea catre programul executabil, asa cum au fost pasate functiei 4B. Daca apelul gaseste fisierul în calea respectiva, apelul concateneaza numele fisierului cu calea respectiva. Un program poate utiliza aceasta zona pentru a determina calea de unde a fost încarcat. Mediul este alocat într-un bloc separat de memorie. Se recomanda ca un program care ramâne rezident (cu functia 31) sa îti elibereze blocul de memorie ce contine mediul, cu functia 49. Secventa de program necesara pentru încarcarea si executarea unui program trebuie sa contina în majoritatea situatiilor urmatorii pasi: 1. Se executa un apel al functiei sistem 4A16 cu (es)=adresa de segment a PSP si (bx)=cantitatea minima de memorie necesara programului parinte în paragrafe; 2. Se pregateste un sir de caractere terminat cu caracterul NUL ce contine numele fisierului cu programul copil si se depune adresa de început a acestui sir în perechea de registre (ds):(dx); 3. Se pregateste un EPB si se depune adresa sa de început în perechea de registre (es):(bx); 4. Se salveaza valorile curente ale registrelor de segment în variabile relative la cs, acesta fiind singurul punct de referinta în urma revenirii din programul copil; 5. Se executa apelul functiei load and execute; 6. Se refac ss si sp la valorile initiale; 7. Se verifica flagul cf pentru a se testa aparitia unei eventuale erori; 8. Se refac ds si es; 9. Optional se poate testa codul de revenire din programul copil, cu ajutorul functiei sistem 4D.
Functia 4D: Prin intermediul acestei functii, un program parinte poate prelua codul de retur întors de un program copil prin functiile 31 sau 4C la apel (ah)=4D, iar în urma executarii apelului (al)=codul de retur si (ah)=un cod ce indica metoda de iesire din programul copil, putând fi:
Cod Semnificatie 0 Terminare normala 1 Terminare prin CTRL-BREAK (int 23h) 2 Terminare datorita unei erori critice (int 24h) 3 Terminare prin functia 3116 (pastrare proces în memorie)
Aceasta functie trebuie apelata doar o singura data pentru fiecare proces terminat în parte. Ex: mov ah,4Dh int 21h
Functia 31: Apelul acestei functii are ca efect terminarea programului aflat în executie, datele si codul programului terminat ramânând rezidente în memorie. La apel (ah)=31, (al)=codul de retur întors catre programul parinte si (dx)=numarul de paragrafe de memorie necesare programului ce ramâne rezident. Ex: mov al,ind_eroare lea dx,ultimul_octet mov cl,4 ; conversie la numar de paragrafe shr dx,cl inc dx mov ah,31h int 21h
Functia 62: Aceasta functie se utilizeaza pentru determinarea adresei prefixului (Program Segment Prefix) corespunzator programului aflat în executie. La apel (ah)=62 adresa este întoarsa în registrul bx. Ex: mov ah,62h int 21h
4. Desfasurarea lucrarii
Urmatorul program utilizeaza functia 4b pentru a rula o a doua copie a programului command.com. Revenirea se face executând comanda DOS exit.
.model small .stack 10h DATA SEGMENT epb_struc STRUC seg_env DW 0 cmd_lin DW 2 DUP(?) fcb_1 DW 2 DUP(?) fcb_2 DW 2 DUP(?) epb_struc ENDS mesaji DB 'Se lanseaza un nou COMMAND.COM','$' mesajo DB 'S-a revenit la vechiul COMMAND.COM!','$' pgm_file DB 'c:\command.com',0 pgm_cmd DB 0 epb epb_struc <> DATA ENDS
.model small .stack 10h COD SEGMENT ASSUME cs:COD,ds:DATA old_ss DW ? old_sp DW ? old_ds DW ? start: mov ax,DATA mov ds,ax ; Calculeaza numarul de paragrafe alocate programului in ax mov ax,cs mov bx,es ; es contine adresa de segment a PSP sub ax,bx mov cl,4 shl ax,cl add ax,OFFSET ultima_instr xor dx,dx mov cx,10h div cx inc ax ; Se reduce dimensiunea blocului de memorie alocat programului mov bx,ax mov ah,4ah int 21h ; Se afiseaza primul mesaj lea dx,mesaji mov ah,09h int 21h ; Se asteapta o tasta mov ah,07h int 21h ; Se încarca o noua copie a COMMAND.COM mov dx,OFFSET pgm_file mov bx,OFFSET epb mov [bx].cmd_lin[0],OFFSET pgm_cmd mov [bx].cmd_lin[2],SEG pgm_cmd mov [bx].fcb_1[0],5ch mov [bx].fcb_1[2],es mov [bx].fcb_2[0],6ch mov [bx].fcb_2[2],es mov ax,4b00h push ds pop es mov old_sp,sp mov old_ss,ss mov old_ds,ds int 21h ; Se afiseaza al doilea mesaj mov sp,old_sp mov ss,old_ss mov ds,old_ds lea dx,mesajo mov ah,09h int 21h ; Terminare program mov ax,4c00h int 21h ultima_instr: COD ENDS END start
Cel de-al doilea program citeste o tasta, determina daca este o tasta obisnuita sau functionala si apoi afiseaza codul tastei. Citirea se face cu functia 07. Daca la primul apel se întoarce codul 0 în registrul al, înseamna ca tasta apasata este o tasta functionala, codul extins al tastei fiind determinat cu un al doilea apel al functiei.
DATA SEGMENT cerere DB 'Tastati o tasta',0ah,0dh,'$' sir DB 3 DUP (?),0ah,0dh,'$' mesaj1 DB 'Codul tastei este:',0ah,0dh,'$' mesaj2 DB 'Codul extins al tastei este:',0ah,0dh,'$' DATA ENDS STIVA SEGMENT STACK 'STACK' DW 30 DUP(?) virf LABEL WORD STIVA ENDS COD SEGMENT ASSUME cs:COD,ds:DATA,ss:STIVA start: jmp incep conv PROC NEAR ; Primeste în registrul al un numar întreg si în registrul bx ; adresa unei zone de 3 octeti. Întoarce în aceasta zona sirul de ; caractere corespunzator scrierii zecimale a numarului push dx xor ah,ah mov dl,10 div dl add ah,'0' mov [bx+2],ah xor ah,ah div dl add ah,'0' mov [bx+1],ah add al,'0' mov [bx],al pop dx ret conv ENDP
incep: mov ax,DATA mov ds,ax mov ax,STIVA mov ss,ax mov sp,OFFSET virf ; Se afiseaza mesajul care cere tastarea unei taste lea dx,cerere mov ah,09h int 21h ; Se citeste o tasta mov ah,07h int 21h ; Se testeaza daca este tasta functionala cmp al,0 jz cod_extins ; Se determina codul tastei lea bx,sir call conv ; Se afiseaza mesaj1 lea dx,mesaj1 mov ah,09h int 21h jmp afis ; Se citeste codul extins cod_extins: mov ah,07h int 21h ; Se determina codul extins lea bx,sir call conv ; Se afiseaza mesaj2 lea dx,mesaj2 mov ah,09h int 21h ; Se afiseaza codul tastei afis: lea dx,sir mov ah,09h int 21h mov ax,4c00h int 21h COD ENDS END start
5. Modul de lucru 1. Se editeaza programele exemplu (în orice mediu de editare) si se salveaza cu extensia .ASM. 2. Se asambleaza si link-editeaza programele, obtinându-se forma .EXE; 3. Se testeaza programele, inclusiv prin încarcarea sa în depanator. 4. Se cere sa se modifice cel de-al doilea program astfel încât la citirea tastei aceasta sa fie afisata pe ecran.
_______________________________________ House Music Set`s Me Free!
|
|