;----------------------------------------
; Traps divide-by-zero

Hook    EQU     0h              ;Vector to hook into.
.286                            ;Uses 286 codes, PUSHA & POPA

cseg segment
assume cs:cseg, ds:cseg
org 100h                        ;COM format.

Begin:
        call    Init
        mov     dx,offset o_msg
        mov     ah,9
        int     21h
        mov     ax,-1           ;Force an overflow error.
        div     al

        mov     dx,offset z_msg
        mov     ah,9
        int     21h
        mov     bx,0            ;Now the divide by zero error.
        div     bx
        call    Restore
        int     20h

o_msg db 'First we MOV AX,-1 : DIV AL and get:  ',36
z_msg db 13,10,'            Now we DIV 0, producing:  ',36
o_txt db '** Divide overflow **', 13,10,36
z_txt db '** Divide by zero **', 13,10,36
Old_Int         dd      ?       ;Storage- points to the old ISR.

;******************************************************
New_ISR         proc far

        pusha                   ;Save the registers
        push    ds
        push    es

        pushf                   ;Test flags to see what caused
        pop     ax              ; this interrupt.
        test    ah,00001000b
        jz      zero            ;Was it an overflow?

        mov     ah,9            ; Yes, print overflow message.
        mov     dx,offset o_txt
        jmp     exit
 zero:
        mov     ah,9            ; No, print divide by zero msg.
        mov     dx,offset z_txt
 exit:
        int     21h             ;Call DOS 21/9, print text.

        mov     bp,sp           ;Setup IP on stack to next
        add     bp,20d          ; instruction beyond DIV.
        add     word ptr [bp],2 ;  (10 words on stack)
        pop     es              ;Restore the registers
        pop     ds              ; and return from interrupt.
        popa
        iret

endp

;****************************************************
Init            proc near
  ;Install the interrupt handler.

        mov     ah,35h          ;Get old vector and store it.
        mov     al,Hook
        int     21h
        mov     word ptr cs:[Old_Int],es
        mov     word ptr cs:[Old_Int+2],bx

        mov     al,Hook         ;Change the target vector.
        mov     dx,offset New_ISR
        mov     ah,25h
        int     21h
        ret
endp

;****************************************************
 Restore        proc near
  ;Restore the old interrupt handler.

        push    ds
        mov     al,Hook
        mov     ds,word ptr cs:[Old_Int]
        mov     dx,word ptr cs:[Old_Int+2]
        ;lds     dx,dword ptr cs:[Old_Int]
        mov     ah,25h
        int     21h
        pop     ds
        ret

endp


cseg ends
end Begin
