In acest tutorial destinat imbajului de asamblare pentru procesoare din familia Intel 8086 sunt prezentate modalitatile de lucru cu fisiere:
- Creare fisier
- Inchidere fisier
- Deschidere fisier
- Scriere in fisier
- Citire din fisier
- Pozitionare in fisier
- Extindere jump-uri de tip short
In programele realizate in limbaj de asamblare fisierul este identificat prin:
- nume (sir de caractere), la operatiile de deschidere si creare
- handler (valoare pozitiva pe 16 biti ce identifica in mod unic fisierul pe disc sau alte dispozitive), la operatiile de inchidere, citire, scriere, pozitionare
Exista o serie de handler-e asociate unor dispozitive standard:
Valoare | Denumire | Descriere |
---|---|---|
0 | stdin | Intrare standard |
1 | stdout | Iesire standard |
2 | stderr | Iesire standard pentru mesaje de eroare |
3 | stdaux | Dispozitiv auxiliar |
4 | stdprn | Imprimanta standard |
Principalele functii DOS pentru lucrul cu fisiere sunt:
Cod functie (se pune in AH) |
Operatie |
3Ch | Creare fisier |
3Dh | Deschidere fisier |
3Eh | Inchidere fisier |
3Fh | Citire din fisier |
40h | Scriere in fisier |
41h | Stergere in fisier |
42h | Pozitionare in fisier |
56h | Redenumire fisier |
Considerand urmatoarele variabile definite in segmentul de date al unui program ce foloseste fisiere:
handler dw ? ;handler la fisier atribut dw ? ;atribut creare fisier tipDeschid dw ? ;modul de deschidere a fisierului rez db ? ;variabila verificare reusita operatie numeFis db 'fisier.dat',0 ;nume fisier NrOctetideScris dw ? ;numarul de octeti de scris in fisier NrOctetiScrisi dw ? ;numarul de octeti scrisi efectiv in fisier
CREARE FISIER
Parametrii | Registru corespondent |
---|---|
– cod functie |
3Ch → AH |
– nume fisier |
DX |
– atribut fisier |
CX |
Parametrii returnati: | |
– handler |
AX |
– rezultat operatie |
in functie de carry flag |
La momentul crearii, tipul fisierul poate fi:
- read-only (1)
- hidden (2)
- system (4)
- normal (0)
Creare MACRO numeFis, atribut, handler, rez local eroare, final push AX push CX push DX mov AH,3Ch ;incarc codul functiei mov CX,atribut ;pun atributul fisierului lea DX,numeFis ;incarca in DX adresa sirului de caractere asociat numelui INT 21h ;apelez intreruperea 21h jc eroare ;daca operatia nu a avut loc cu succes CF este setat ;verific reusita operatiei mov handler,AX ;daca fisierul a fost creat initializez handler-ul mov rez,0 ;initializez variabila rez cu 0 jmp final ;salt la sfarsit macro eroare: ;in caz de eroare mov handler,-1 ;initializez handler-ul cu o valoare negativa mov rez,AX ;retin in rez codul erorii (este diferit de 0) final: pop DX pop CX pop AX ENDM
Inchidere Fisier
Parametrii intrare: | Registru corespondent |
---|---|
– cod functie |
3Eh → AH |
– handler |
BX |
Parametrii returnati: | |
– rezultat operatie |
in functie de carry flag |
Inchidere MACRO handler, rez local eroare, final push AX push BX mov AH,3Eh ;incarc codul functiei mov BX,handler ;incarc handler-ul fisierului INT 21h jc eroare ;daca operatia nu a avut loc cu succes CF este setat ;verific reusita operatiei mov rez,0 jmp final eroare: mov rez,AX ;retin in rez codul erorii (este diferit de 0) final: pop BX pop AX ENDM
DECHIDERE FISIER
Parametrii intrare: | Registru corespondent |
---|---|
– cod functie |
3Dh → AH |
– nume fisier |
DX |
– tip acces |
AL |
Parametrii returnati: | |
– handler |
AX |
– rezultat operatie |
in functie de carry flag |
Fisierul poate deschis pentru:
- citire (0)
- scriere (1)
- citire/scriere (2)
Deschidere MACRO numeFis, tipDeschid, handler, rez local eroare, final push AX push DX mov AH,3Dh ;incarc codul functiei mov AL, tipDeschid ;indic tipul deschiderii fisierului lea DX,numeFis ;incarca in DX adresa sirului de caractere asociat numelui INT 21h ;apelez intreruperea 21h jc eroare ;daca operatia nu a avut loc cu succes CF este setat ;verific reusita operatiei mov handler,AX ;daca fisierul a fost deschis initializez handler-ul mov rez,0 ;initializez variabila rez cu 0 jmp final ;salt la sfarsit macro eroare: ;in caz de eroare mov handler,-1 ;initializez handler-ul cu o valoare negativa mov rez,AX ;retin in rez codul erorii (este diferit de 0) final: pop DX pop AX ENDM
Scriere in fisier
Parametrii intrare: | Registru corespondent |
---|---|
– cod functie |
40h → AH |
– handler fisier |
BX |
– buffer din care se citesc datele pentru a fi scrise in fisier |
DX |
– numar octeti de scris in fisier |
CX |
Parametrii returnati: | |
– numar octeti scrisi efectiv in fisier |
AX |
– rezultat operatie |
in functie de carry flag |
Scrie MACRO handler, buffer, NrOctetideScris, NrOctetiScrisi,rez local eroare, final push AX push BX push CX push DX mov AH,40h ;incarc codul functiei mov BX,handler ;incarc handler-ul fisierului existent mov CX, NrOctetideScris ;indic numarul de octeti de scris in fisier lea DX,buffer ;incarca in DX adresa zonei de unde iau datele de scris INT 21h ;apelez intreruperea 21h jc eroare ;daca operatia nu a avut loc cu succes CF este setat ;verific reusita operatiei mov NrOctetiScrisi,AX ;retin numarul de octeti efectiv scrisi mov rez,0 ;initializez variabila rez cu 0 jmp final ;salt la sfarsit macro eroare: ;in caz de eroare mov rez,AX ;retin in rez codul erorii (este diferit de 0) final: pop DX pop CX pop BX pop AX ENDM
Atentie Buffer-ul poate fi un element de tip articol, masiv sau variabila. De exemplu, pentru a scrie intr-un fisier primele 3 elemente ale unui vector vector db 1,2,3,4,5b se scrie instructiunea:
Scrie handler,vector,3,NrOctetiScrisi,rez
Citire din Fisier
Parametrii intrare: | Registru corespondent |
---|---|
– cod functie |
3Fh → AH |
– handler fisier |
BX |
– buffer in care se scriu datele citite din fisier |
DX |
– numar octeti de citit din fisier |
CX |
Parametrii returnati: | |
– numar octeti cititi efectiv din fisier |
AX |
– rezultat operatie |
in functie de carry flag |
Citeste MACRO handler, buffer, NrOctetideCitit, NrOctetiCititi,rez local eroare, final push AX push BX push CX push DX mov AH,3Fh ;incarc codul functiei mov BX,handler ;incarc handler-ul fisierului existent mov CX, NrOctetideScris ;indic numarul de octeti de citit din fisier lea DX,buffer ;incarca in DX adresa zonei unde pun datele citite INT 21h ;apelez intreruperea 21h jc eroare ;daca operatia nu a avut loc cu succes CF este setat ;verific reusita operatiei mov NrOctetiCititi,AX ;retin numarul de octeti efectiv cititi mov rez,0 ;initializez variabila rez cu 0 jmp final ;salt la sfarsit macro eroare: ;in caz de eroare mov rez,AX ;retin in rez codul erorii (este diferit de 0) final: pop DX pop CX pop BX pop AX ENDM
Pozitionare in fisier
Parametrii intrare: | Registru corespondent |
– cod functie |
42h → AH |
– handler fisier |
BX |
– punct de referinta |
AL |
– numar octeti fata de punctul de referinta ai saltului (e un double) |
cuv. inferior → DX cuv. superior → CX |
Parametrii returnati: | |
– noua pozitie in fisier (un double) |
cuv. inferior → AX cuv. superior → DX |
– rezultat operatie |
in functie de carry flag |
Punctul de referinta poate fi:
- 0, inceputul fisierului;
- 1, pozitia curenta in fisier;
- 2, sfarsitul fisierului.
Pozitionare MACRO handler, pozitie, referinta, pozitieNoua, rez local eroare, final push AX push BX push CX push DX mov AH,42h ;incarc codul functiei mov AL,referinta ;indic referinta fata de care fac saltul mov BX,handler ;incarc handler-ul fisierului existent mov DX,word ptr pozitie[0] ;numar octeti salt mov CX,word ptr pozitie[2] ; expresie similara este si ; mov DX,WORD PTR pozitie ; mov CX,WORD PTR pozitie +2 INT 21h jc eroare ;daca operatia nu a avut loc cu succes CF este setat ;verific reusita operatiei mov word ptr pozitieNoua[0],AX ;noua pozitie mov word ptr pozitieNoua[2],DX mov rez,0 jmp final ;salt la sfarsit macro eroare: ;in caz de eroare mov rez,AX ;retin in rez codul erorii (este diferit de 0) final: pop DX pop CX pop BX pop AX ENDM
Presupunand ca toate aceste macrodefinitii sunt definite in fisierul MacroFis.inc se scrie programul care construieste un fisier si il foloseste pentru a memora elementele unui vector de elemente si de structuri. Ulterior, se construiesc alti doi vectori in care se pun elementele aflate in fisier.
Atentie Fisierul MacroFis.inc contine doar codul fiecarei macrodefinitii in parte fara nici o alta declaratie in plus. Acest fisier nu necesita asamblare sau link-editare. Instructiunea include
MacroFis.inc din programul principal (dat mai jos) copiaza codul din fisierul indicat si il insereaza pe pozitia instructiunii.
Atentie Pentru a determina dimensiunea unui vector se va utiliza simbolul $ asociat offset-ului curent in segmentul de date.
Pentru un masiv de tip tip_vect (orice tip de baza sau structura) pentru lungime ca numar de elemente se utilizeaza expresia:
vector tip_vector elem1, elem2, elem3, ….., elemn
tip equ TYPE vector
nrElem equ ($ – vector)/tip
In cazul masivelor definite cu dup se poate utiliza LENGTH pentru a obtine numarul de elemente.
.model small .286 .stack 100h .data student STRUC ;articol de tip student nume db 15 dup (?) varsta db ? nrMatricol dw ? ENDS dimStudent equ SIZE student ;dimensiune in octeti a unui ;articol de tip student vector db 1,2,3,4,5 ;vector de elemente lvector equ $-vector ;lungime vector ca numar de octeti ;cum elementele vectorului sunt de tip octet atunci lvector ;da si numarul de elemente vector2 db 5 dup(?) ;al doilea vactor vectorStudenti student <'Popescu',23,1234>,<'Ionescu',22,1235>,<'Gheorghe',22,1236> ;vector de articole dimVectStud equ $-vectorStudenti ;dimensiune in octeti nrStudenti equ dimVectStud/dimStudent ;numar elemente vectorStudenti2 student nrStudenti dup(?) ;al doilea vector handler dw ? ;handler la fisier atribut dw ? ;atribut creare fisier tipDeschid dw ? ;modul de deschidere a fisierului rez dw ? ;variabila verificare reusita operatie NrOctetideScris dw ? ;numar de octeti de scris in fisier NrOctetiScrisi dw ? ;numar de octeti scrisi in fisier NrOctetiCititi dw ? ;numar de octeti de cititi din ;fisier Pozitie dd ? ;dimensiunea saltului la ;pozitionare PozitieNoua dd ? ;noua pozitie in fisier numeFis db 'fisier.dat',0 ;nume fisier mesajEroare db 'Eroare executie functie!','
Atentie Salturile conditionate nu pot referi etichete aflate la mai mult de 128 octeti. Solutia consta in evitarea acestor situatii prin rescrierea codului si a conditiei de verificat astfel incat sa avem salturi mai mici. In exemplul anterior, verificarea realizarii corecte a unei macrodefinitii se realiza prin:
apel de macrodefinitie cmp rez,0 jne afiseaza_eroare apel macrodefinitie urmatoare … jmp exit afiseaza_eroare: AfiseazaMesaj mesajEroare exit: mov AX,4c00h int 21h
insa eticheta afiseaza_eroare se afla la o distanta mai mare de 128 de octeti. Din acest motiv s-au folosit etichetele continuarei cu i = 1,2.. iar verificarea a devenit:
apel de macrodefinitie cmp rez,0 je continuarei AfiseazaMesaj mesajEroare continuarei apel macrodefinitie urmatoare
Extindere jump-uri de tip short
Se presupune secventa de cod
efectuare comparatie je salt ... salt:
care este corecta in cazul in care eticheta salt se gaseste la mai putin de 128 de octeti. In caz contrar saltul, extinderea salturilor conditionate se realizeaza prin abordarea secventei de cod astfel:
- utilizarea unui salt neconditionat (acesta poate face salturi mai mari de 128 de octeti):
efectuare comparatie jne continuare jmp salt continuare: ... salt:
- repetarea codului de la instructiunea salt pentru fiecare comparatie:
efectuare comparatie jne continuare salt: ... continuare: ...
- utilizarea unui salt neconditionat fara a utiliza etichete suplimentare
efectuare comparatie jne $+2+ dimensiune in octeti a instructiunii urmatoare jmp salt ... salt:
Instructiunea jne $+2+ dimensiune in octeti a instructiunii urmatoare adauga la offset-ul curent din segmentul de cod (retinut in IP si indicat cu $) 2 octeti reprezentand dimensiunea acestei instructiunii si dimensiunea in octeti a instructiunii urmatoare. Cum in aceasta abordare instructiunea urmatoare este jmp salt trebuie indicata dimensiunea ei (vezi documentatie Structuri de control → 3 octeti pentru jump near si 5 octeti pentru jump far). Deci, in acest caz instructiunea se mai poate scrie jne $ + 5. Pentru a afla dimensiunea altor instructiuni se utilizeaza TurboDebugger-ul si se fac diferente de offset-uri ale instructiunilor respective. Pentru a fi sigur de tipul jump-ului se indica tipul acestuia explicit cu jmp NEAR PTR salt aceasta instructiune avand 3 octeti.
;mesaj eroare .code include MacroF.inc ;includ fisierul ce contine macrodefinitiile start: mov AX,@data mov DS,AX Creare numeFis,0,handler,rez ;creez fisierul cmp rez,0 ;verific executia operatiei je continuare1 AfiseazaMesaj mesajEroare ;afisez mesaj eroare continuare1: Inchidere handler,rez ;inchid fisierul cmp rez,0 ;verific executia operatiei je continuare2 AfiseazaMesaj mesajEroare ;afisez mesaj eroare continuare2: Deschidere numeFis,2,handler,rez ;deschid fisierul cmp rez,0 ;verific executia operatiei je continuare3 AfiseazaMesaj mesajEroare ;afisez mesaj eroare continuare3: Scrie handler,vector,lvector,NrOctetiScrisi,rez ;scriu in fisier primul vector Scrie handler,vectorStudenti,dimvectstud,NrOctetiScrisi,rez ;scriu in fisier primul vector de articole mov word ptr pozitie,0 ;indic pozitia saltului mov word ptr pozitie[2],0 ;pun zero pt. a ma pozitiona la 0 ;octeti fata de inceputul fisierului Pozitionare handler,pozitie,0,PozitieNoua,rez ;ma pozitionez pe inceputul fisierului Citeste handler,vector2,lvector,NrOctetiCititi,rez ;citesc in al doilea vector elementele din ;fisier: 1,2,3,4,5 Citeste handler,vectorStudenti2,dimVectStud,NrOctetiCititi,rez ;citesc in al doilea vector de articole ;elementele din fisier Inchidere handler,rez ;inchid fisierul mov AX,4c00h int 21h end start
Codul macrodefinitiei AfiseazaMesaj este (este inclus tot in MacroF.inc) :
AfiseazaMesaj MACRO mesaj push AX push DX mov Ah,09h lea DX,mesaj int 21h pop DX pop AX ENDM
Foarte util articolul,multumesc