home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / advmsdos / chap13 / zerodiv.asm < prev   
Encoding:
Assembly Source File  |  1988-10-01  |  3.8 KB  |  179 lines

  1.          title     ZERODIV --- Divide by zero handler
  2.          page      55,132
  3.  
  4. ; ZERODIV.ASM --- Terminate-and-stay-resident handler
  5. ;                 for divide-by-zero interrupts
  6. ; Copyright 1988 Ray Duncan
  7. ; Build:    C>MASM ZERODIV; 
  8. ;         C>LINK ZERODIV; 
  9. ;         C>EXE2BIN ZERODIV.EXE ZERODIV.COM
  10. ;            C>DEL ZERODIV.EXE
  11. ;
  12. ; Usage:    C>ZERODIV
  13. ;
  14.  
  15. cr    equ     0dh           ; ASCII carriage return
  16. lf      equ     0ah           ; ASCII line feed
  17. beep    equ    07h        ; ASCII bell code
  18. backsp    equ    08h        ; ASCII backspace code
  19.  
  20. _TEXT     segment    word public 'CODE'
  21.  
  22.     org    100H      
  23.  
  24.     assume     cs:_TEXT,ds:_TEXT,es:_TEXT,ss:_TEXT
  25.  
  26.  
  27. init    proc     near          ; entry point at load time    
  28.  
  29.                 ; capture vector for
  30.                 ; interrupt zero ...
  31.     mov    dx,offset zdiv    ; DS:DX = handler address
  32.     mov    ax,2500h    ; Fxn 25H = set vector
  33.                 ; interrupt type = 0
  34.     int    21h        ; transfer to MS-DOS
  35.  
  36.                 ; print sign-on message
  37.     mov    dx,offset msg1    ; DS:DX = message address
  38.     mov    ah,9        ; Fxn 09H = display string
  39.     int    21h        ; transfer to MS-DOS
  40.  
  41.                 ; DX = paragraphs to reserve
  42.     mov    dx,((offset pgm_len+15)/16)+10h
  43.     mov    ax,3100h    ; Fxn 31H = terminate and
  44.                 ; stay resident
  45.     int    21h        ; transfer to MS-DOS
  46.  
  47. init    endp
  48.  
  49.  
  50. zdiv    proc    far        ; this is the divide by 
  51.                 ; zero interrupt handler
  52.  
  53.     sti            ; enable interrupts
  54.  
  55.     push    ax        ; save registers
  56.     push    bx
  57.     push    cx
  58.     push    dx
  59.     push    si
  60.     push    di
  61.     push    bp
  62.     push    ds
  63.     push    es
  64.  
  65.     mov    ax,cs          ; make data addressable
  66.     mov    ds,ax
  67.  
  68.                 ; display message
  69.                 ; "Continue or Quit?"
  70.     mov    dx,offset msg2    ; DS:DX = message address    
  71.     mov    ah,9        ; Fxn 09H = display string
  72.     int    21h        ; transfer to MS-DOS
  73.  
  74. zdiv1:    mov    ah,1        ; Fxn 01H = read keyboard
  75.     int    21h        ; transfer to MS-DOS
  76.  
  77.     or    al,20h        ; fold char. to lower case
  78.  
  79.     cmp    al,'c'        ; is it C or Q?
  80.     je    zdiv3        ; jump, it's a C
  81.  
  82.     cmp    al,'q'
  83.     je    zdiv2        ; jump, it's a Q
  84.  
  85.                 ; illegal entry, send beep
  86.                 ; and erase the character
  87.     mov    dx,offset msg3    ; DS:DX = message address
  88.     mov    ah,9        ; Fxn 09H = display string
  89.     int    21h        ; transfer to MS-DOS
  90.  
  91.     jmp    zdiv1        ; try again
  92.  
  93. zdiv2:                ; user picked "Quit"
  94.     mov    ax,4cffh    ; terminate current program
  95.     int    21h        ; with return code = 255
  96.  
  97. zdiv3:                ; user picked "Continue"
  98.                 ; send CR-LF pair
  99.     mov    dx,offset msg4  ; DS:DX = message address
  100.     mov    ah,9        ; Fxn 09H = print string
  101.     int    21h        ; transfer to MS-DOS
  102.  
  103.                 ; what CPU type is this?
  104.     xor    ax,ax        ; to find out, we'll put
  105.     push    ax        ; zero in the CPU flags
  106.     popf            ; and see what happens
  107.     pushf
  108.     pop    ax
  109.     and    ax,0f000h    ; 8086/88 forces 
  110.     cmp    ax,0f000h    ; bits 12-15 true
  111.           je    zdiv5        ; jump if 8086/88
  112.  
  113.                 ; otherwise we must adjust
  114.                 ; return address to bypass
  115.                 ; the divide instruction...
  116.     mov    bp,sp        ; make stack addressable
  117.  
  118.     lds    bx,[bp+18]    ; get address of the
  119.                 ; faulting instruction
  120.  
  121.     mov    bl,[bx+1]    ; get addressing byte
  122.     and    bx,0c7h        ; isolate mod & r/m fields
  123.  
  124.     cmp    bl,6        ; mod 0, r/m 6 = direct
  125.     jne    zdiv4        ; not direct, jump
  126.  
  127.     add    word ptr [bp+18],4
  128.     jmp    zdiv5
  129.  
  130. zdiv4:    mov    cl,6        ; otherwise isolate mod
  131.     shr    bx,cl        ; field and get instruction
  132.     mov    bl,cs:[bx+itab]    ; size from table
  133.     add    [bp+18],bx
  134.  
  135. zdiv5:    pop    es        ; restore registers
  136.     pop    ds
  137.     pop    bp
  138.     pop    di
  139.     pop    si
  140.     pop    dx
  141.     pop    cx
  142.     pop    bx
  143.     pop    ax
  144.     iret            ; return from interrupt
  145.  
  146. zdiv    endp
  147.  
  148.  
  149. msg1    db       cr,lf        ; load-time signon message
  150.     db    'Divide by Zero Interrupt '
  151.     db    'Handler installed.'
  152.     db    cr,lf,'$'
  153.  
  154. msg2    db    cr,lf,lf    ; interrupt-time message
  155.     db    'Divide by Zero detected: '
  156.     db    cr,lf,'Continue or Quit (C/Q) ? '
  157.     db    '$'
  158.  
  159. msg3    db    beep        ; used if bad entry
  160.     db    backsp,' ',backsp,'$'
  161.  
  162. msg4    db    cr,lf,'$'    ; carriage return-line feed
  163.  
  164.                 ; instruction size table
  165. itab    db    2        ; mod = 0
  166.     db    3        ; mod = 1
  167.     db    4        ; mod = 2
  168.     db    2        ; mod = 3
  169.  
  170. pgm_len    equ    $-init        ; program length
  171.  
  172. _TEXT     ends
  173.  
  174.     end    init
  175.  
  176.