Redirectarea întreruperii de pe nivelul 0
Împărţirea unui număr foarte mare la un număr mic, poate duce la apariţia întreruperii pe nivelul 0.
Pentru obţinerea rezultatului corect, se redirectează întreruperea de pe nivelul 0 spre o rutină care realizează
împărţirea în situaţia în care împărţitorul este diferit de 0. Implementaţi programul de mai jos, şi rulaţi-l pas
cu pas.
.model small
.stack 100
.data
demp dd 44444444h
imp dw 1111h
cat dd ?
rest dw ?
.code
;procedura primeste deimpartitul in (DX, AX) si impartitorul in BX
;returneaza catul in (BX, AX) si restul in DX
divc proc
cmp bx, 0 ;daca eroare adevarata
jnz divc1
int 0 ;apel tratare impartire cu 0
divc1:
push es ;salvare registre modificate de procedura
push di
push cx
mov di, 0
mov es, di ;adresa pentru intrarea intrerupere nivel 0
push es:[di] ;salvare adresa oficiala
push es:[di+2]
mov word ptr es:[di], offset trat_0 ;incarcare vector intrerupere
mov es:[di+2],cs ; pentru noua rutina de tratare
div bx ;incercare executie instructiune de impartire
;nu a aparut eroare
sub bx, bx ;daca impartirea s-a executat corect se pune 0
;in bx ca sa corespunda modului de transmitere al parametrilor stabilit
revenire:
pop es:[di+2]
pop es:[di]
pop cx
pop di
pop es
ret
trat_0 proc far
push bp ;salvare bp
mov bp, sp
;schimba adresa de revenire din rutina trat_0, adresa care se gaseste in stiva
;a fost pusa in stiva la apelare rutinei de intrerupere (IP-ul)
mov word ptr [bp+2], offset revenire
push ax ;salvare ax, Y0
mov ax, dx ;primul deimpartit Y1
sub dx, dx
;executie impartire Y1 la X
;rezulta (AX) = Q1, (DX) = R1
div bx
pop cx ;Y0
push ax ;salvare Q1
mov ax, cx
;executie impartire (R1, AX) la X
;rezulta AX=Q0, DX=R0
div bx
pop bx ;Q1
pop bp
iret
trat_0 endp
divc endp
start: mov ax, @data
mov ds, ax
mov ax, word ptr demp
mov dx, word ptr demp+2
mov bx, imp
call divc
mov word ptr cat, ax
mov word ptr cat+2, bx
mov rest, dx
mov ah, 4ch
int 21h
end start.
Împărţirea unui număr foarte mare la un număr mic, poate duce la apariţia întreruperii pe nivelul 0.
Pentru obţinerea rezultatului corect, se redirectează întreruperea de pe nivelul 0 spre o rutină care realizează
împărţirea în situaţia în care împărţitorul este diferit de 0. Implementaţi programul de mai jos, şi rulaţi-l pas
cu pas.
.model small
.stack 100
.data
demp dd 44444444h
imp dw 1111h
cat dd ?
rest dw ?
.code
;procedura primeste deimpartitul in (DX, AX) si impartitorul in BX
;returneaza catul in (BX, AX) si restul in DX
divc proc
cmp bx, 0 ;daca eroare adevarata
jnz divc1
int 0 ;apel tratare impartire cu 0
divc1:
push es ;salvare registre modificate de procedura
push di
push cx
mov di, 0
mov es, di ;adresa pentru intrarea intrerupere nivel 0
push es:[di] ;salvare adresa oficiala
push es:[di+2]
mov word ptr es:[di], offset trat_0 ;incarcare vector intrerupere
mov es:[di+2],cs ; pentru noua rutina de tratare
div bx ;incercare executie instructiune de impartire
;nu a aparut eroare
sub bx, bx ;daca impartirea s-a executat corect se pune 0
;in bx ca sa corespunda modului de transmitere al parametrilor stabilit
revenire:
pop es:[di+2]
pop es:[di]
pop cx
pop di
pop es
ret
trat_0 proc far
push bp ;salvare bp
mov bp, sp
;schimba adresa de revenire din rutina trat_0, adresa care se gaseste in stiva
;a fost pusa in stiva la apelare rutinei de intrerupere (IP-ul)
mov word ptr [bp+2], offset revenire
push ax ;salvare ax, Y0
mov ax, dx ;primul deimpartit Y1
sub dx, dx
;executie impartire Y1 la X
;rezulta (AX) = Q1, (DX) = R1
div bx
pop cx ;Y0
push ax ;salvare Q1
mov ax, cx
;executie impartire (R1, AX) la X
;rezulta AX=Q0, DX=R0
div bx
pop bx ;Q1
pop bp
iret
trat_0 endp
divc endp
start: mov ax, @data
mov ds, ax
mov ax, word ptr demp
mov dx, word ptr demp+2
mov bx, imp
call divc
mov word ptr cat, ax
mov word ptr cat+2, bx
mov rest, dx
mov ah, 4ch
int 21h
end start.
Niciun comentariu:
Trimiteți un comentariu