Intreruperi. Programare multimodul

Intreruperi


Ex.1. Sa se citeasca de la tastatura numele unui fisier. Sa se afiseze acest fisier pe ecran.



assume cs:code, ds:data
data segment
	msg db 'Numele fisierului: $'
	fileName db 12,?,13 dup (?)
	buffer db 21 dup (?)
	openErrorMsg db 'Fisierul nu exista.$'
	readErrorMsg db 'Nu se poate citii din fisier.$'
	handler dw 0
data ends
code segment
start:
	mov ax, data
	mov ds, ax

	; afisam mesajul cu functia 09h, int 21h
	mov ah, 09h
  	mov dx, offset msg
	int 21h 

	; citim de la tastatura numele fisierului cu ajutorul functiei 0ah, int 21h
	mov ah, 0ah
	mov dx, offset fileName
	int 21h
	; în urma citirii la adresa fileName+2 se memoreaza numele fisierului citit
	; la adresa fileName + 1 se memoreaza dimensiunea sirului de caractere care reprezinta numele fisierului


	; transformam numele fisierului într-un sir ASCIIZ
	mov bl, fileName[1]
	mov bh, 0
	add bx, offset fileName
	add bx, 2
	mov byte ptr [bx], 0

	; deschidem fisierul cu functia 3dh, int 21h
	mov ah, 3dh
	mov al, 0 ; deschidem fisierul pentru citire
	mov dx, offset fileName+2
	int 21h

	jc openError ; eroare la deschiderea fisierului daca CF e setat
	mov handler, ax ; salvam identificatorul (handler) fisierului in handler

	; cât timp nu e sfârsit de fisier citim din fisier si afisam pe ecran
	goOn:
	    mov ah, 3fh
	    mov bx, handler
	    mov dx, offset buffer	; citim in buffer
	    mov cx, 20 ; citim maxim 20 de caractere
	    int 21h

	    jc readError

	    ; în caz de succes functia 3dh întoarce în ax numarul de octeti cititi

	    ; salvam numarul octetilor cititi si pregatim sirul pentru afisare
	    mov si, ax
	    mov buffer[si], '$'

	    ; afisam ce am citit
	    mov ah, 09h
	    int 21h
	    cmp si, 20
            je goOn ; daca am citit 20 de octeti înseamna ca nu am terminat de citit
      	    jmp endPrg ; sarim peste tratarea eventualelor erori 
	openError:
	    mov ah, 09h
	    mov dx, offset openErrorMsg
	    int 21h
	    jmp endPrg

	readError:
	    mov ah, 09h
	    mov dx, offset readErrorMsg
	    int 21h

	endPrg:
	    ; inchidem fisierul cu functia 3eh a intreruperii 21h
	    mov ah, 3eh
	    mov bx, handler
	    int 21h

	    mov ax,4c00h
	    int 21h

code ends
end start


Ex.2. Sa se scrie un program de asamblare care tipareste pe ecran, in baza 10, continutul registrilor AX si BX.
 

Rezolvare: Deoarece nu exista nici o intrerupere, a carei rutina de tratare 
sa poata tipari (sau citi) un numar in baza 10, va trebui sa ne folosim de 
functia 02h a intreruperii 21h care stie sa afiseze un caracter sau de functia 
09h a intreruperii 21h care afiseaza un sir de caractere. Pentru a ajunge 
de la un numar (ex. 2435 in baza 10) la un sir de caractere pe care sa-l 
putem afisa (ex. sirul '2','4','3','5') vom imparti succesiv numarul si 
caturile obtinute la 10 si vom retine resturile care reprezinta de fapt, 
cifrele numarului.
 

assume cs:code, ds:data
data segment
            LinieNoua db 10,13,'$'
            zece dw 10
data segment
code segment

            AfisBaza10   PROC
            ; definim o procedura care afiseaza registrul ax in baza 10
            cmp ax, 0
            jge pozitiv 
            ; altfel, numarul e negativ si afisam caracterul '-' cu ajutorul functiei 02h a int 21h
            push ax
            mov ah, 02h
            mov dl, '-'
            int 21h
            pop ax
            neg ax              ; ax:= valoarea absoluta a lui ax

            pozitiv:
; pentru a nu avea depasiri, vom imparti totdeauna pe DX:AX la 10. Tot 
; impartim la 10 si punem resturile obtinute (adica cifrele) pe stiva pentru 
; a inversa, in final, ordinea lor.

		mov cx, 0 ; in cx, vom retine numarul de cifre puse pe stiva
		repeta:
			mov dx, 0
			div zece
			push dx
			inc cx
			cmp ax, 0
			ja repeta ; daca catul>0 jmp repeta 

		; acuma vom scoate fiecare cifra de pe stiva si o vom afisa cu ajutorul 
		; functiei 02h a int 21h

		scoate:
			pop dx
			; restul, adica cifra, se afla in DL (deoarece este un numar intre 0 si 10)
			add dl, '0' ; obtinem caracterul corespunzator cifrei
			mov ah, 02
			int 21h
			loop scoate
		ret            ; revenirea din procedura
AfisBaza10 ENDP

            
start:     
            mov ax, data
            mov ds, ax

            mov ax, 2435
            ; afisam valoarea din ax apeland procedura AfisBaza10
            call AfisBaza10

            ; sarim la linie noua pe ecran
            mov ah, 09h
            lea dx, LinieNoua
            int 21h
            
            mov ax, bx
            ; afisam valoarea din ax apeland procedura AfisBaza10
            call AfisBaza10
 
            mov ax, 4c00h
            int 21h
code ends
end start

Programare multimodul



Program multimodul = program format din cel putin 2 module:

Directive utile:
PUBLIC simbol : exporta "simbol" care e definit in modulul curent spre a fi folosit in alte module

EXTRN simbol: tip : importa "simbol" definit intr-un modul extern spre a fi folosit in modulul curent; tip poate fi: BYTE, WORD, DWORD, NEAR, FAR, PROC, ABS (constanta, equ).

GLOBAL simbol : face acelasi lucru ca si PUBLIC si EXTRN impreuna.

Ex.3. Scriem un program care concateneaza doua stringuri apeland pentru aceasta o procedura
scrisa intr-un modul extern si apoi va afisa stringul rezultat.

Modulul main.asm:

assume cs:code, ds:data
data segment
	s1 db 'Buna ', 0
	s2 db 'dimineata!', 0
	rezultat db 30 dup(?)
data ends
PUBLIC rezultat
EXTRN Concat:PROC
code segment
start:
	mov ax, data
	mov ds, ax

	mov ax, offset s1
	mov bx, offset s2
	call Concat

	mov ah, 09h
	lea dx, rezultat
	int 21h

	mov ax, 4c00h
	int 21h
code ends
end start


Modulul secundar.asm:

assume cs:code, ds:data

data segment
data ends

EXTRN rezultat:BYTE
PUBLIC Concat

code segment
	Concat PROC 
		push ds
		pop es
		; in AX avem offset s1 si in BX avem offset s2
		mov di, offset rezultat
		mov si, ax

		repeta:
			lodsb
			cmp al, 0
			je cont
			stosb
			jmp repeta

		cont:
			mov si, bx
		
		repeta1:
			lodsb
			cmp al, 0
			je dupa
			stosb
			jmp repeta1

		dupa:
			mov al, '$'
			stosb			

		ret
	Concat ENDP

code ends
end

Obtinerea executabilului:
TASM main.asm
TASM secundar.asm
TLINK main+secundar