home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / assemblr / mslang / as / dskwatch.asm < prev    next >
Assembly Source File  |  1985-08-28  |  4KB  |  109 lines

  1. ; By Steve Holzner (from June 11, 1985 issue of PC Magazine)
  2.  
  3. interrupts    segment at 0h    ; This is where the disk interrupt
  4.     org    13h*4        ; holds the address of its service routine
  5. disk_int    label    dword
  6. interrupts    ends
  7.  
  8. screen    segment at 0B000h    ; A dummy segment to use as the Extra
  9. screen    ends            ; Segment so we can write to the display
  10.  
  11. code_seg    segment
  12.     assume    cs:code_seg
  13.     org    0100h        ; ORG = 100h to make this a .COM file
  14. first:    jmp    load_watch    ; First time through jump to initialize routine
  15.  
  16.     msg_part_1    db    'Disk error: '    ; Here are the error messages
  17.     msg_part_2    db    'No response Failed Seek NEC Error   '
  18.             db    'Bad CRC SeenDMA Overrun Impos Sector'
  19.             db    'No Addr MarkW. ProtectedErr Unknown '
  20.     first_position    dw    ?        ; Position of 1st char on screen
  21.     flags        dw    ?
  22.     screen_seg_offset dw    0        ; 0 for mono, 8000h for graphics
  23.     old_disk_int    dd    ?        ; Location of old disk interrupt
  24.     ret_addr    label dword        ; Used in fooling around with
  25.     ret_addr_word    dw 2 dup(?)        ;   the stack
  26.  
  27. disk_watch    proc    far    ; The disk interrupt will now come here
  28.     assume    cs:code_seg
  29.     pushf            ; First, call old disk interrupt
  30.     call    old_disk_int
  31.     pushf            ; Save the flags in memory location "FLAGS"
  32.     pop    flags        ; (cunning name)
  33.     jc    error        ; If there was an error, carry flag will have
  34.     jmp    fin        ;  been set by Disk Interrupt
  35. error:    push    ax        ; AH has the status of the error
  36.     push    cx        ; Push all used registers for politeness
  37.     push    dx
  38.     push    di
  39.     push    si
  40.     push    es
  41.     lea    si,msg_part_1    ; Always print "Disk Error: " part.
  42.     assume    es:screen    ; Use screen as extra segment
  43.     mov    dx,screen
  44.     mov    es,dx
  45.     mov    di,screen_seg_offset    ; DI will be pointer to screen position
  46.     add    di,first_position    ; Add to point to desired area on screen
  47.     call    write_to_screen        ; This writes 12 chars from [SI] to [DI]
  48.     mov    dx,80h            ; Initialize for later comparisons
  49.     mov    cx,7            ; Loop seven times
  50. e_loop:    cmp    ah,dh            ; Are error code and DH the same?
  51.     je    e_found            ; If yes, Error has been found
  52.     add    si,12            ; Point to next error message
  53.     shr    dh,1            ; Divide DH by 2
  54.     loop    e_loop            ; Keep going until matched  DH = 0
  55.     cmp    ah,3            ; Error code no even number; 3 perhaps?
  56.     je    e_found            ; If yes, have found the error
  57.     add    si,12            ; Err unknown; unknown error returned
  58. e_found:call    write_to_screen        ; Write the error message to the screen
  59.     pop    es        ; Restore the registers
  60.     pop    si
  61.     pop    di
  62.     pop    dx
  63.     pop    cx
  64.     pop    ax
  65. fin:    pop    ret_addr_word        ; Fooling with the stack. We want to
  66.     pop    ret_addr_word[2]    ; preserve the flags but the old flags
  67.     add    sp,2            ; are still on the stack. First remove
  68.     push    flags            ; return address, then flags. Fill flags
  69.     popf                ; from "FLAGS", return to correct addr.
  70.     jmp    ret_addr
  71. disk_watch    endp
  72.  
  73. write_to_screen    proc    near    ; Puts 12 characters on screen
  74.     mov    cx,12        ; Loop 12 times
  75. w_loop:    movs    es:byte ptr[di],cs:[si] ; Move to the screen
  76.     mov    al,7        ; Move screen attribute into screen buffer
  77.     mov    es:[di],al
  78.     inc    di        ; Point to next byte in screen buffer
  79.     loop    w_loop        ; Keep going until done
  80.     ret
  81. write_to_screen    endp
  82.  
  83. load_watch    proc    near    ; This procedure initializes everything
  84.     assume    ds:interrupts    ; The data segment will be the interrupt area
  85.     mov    ax,interrupts
  86.     mov    ds,ax
  87.  
  88.     mov    ax,disk_int    ; Get the old interrupt service routine
  89.     mov    old_disk_int,ax    ; address and put it into our location
  90.     mov    ax,disk_int[2]    ; OLD_DISK_INT so we can call it.
  91.     mov    old_disk_int[2],ax
  92.  
  93.     mov    disk_int,offset disk_watch  ; Now load the address of DskWatch
  94.     mov    disk_int[2],cs        ; routine into the disk interrupt
  95.  
  96.     mov    ah,15        ; Ask for service 15 of INT 10h
  97.     int    10h        ; This tells us how display is set up
  98.     sub    ah,25        ; Move to twenty five places before edge
  99.     shl    ah,1        ; Mult. by two (char & attribute bytes)
  100.     mov    byte ptr first_position,ah    ; Set screen cursor
  101.     test    al,4        ; Is it a monochrome display?
  102.     jnz    exit        ; Yes - jump out
  103.     mov    screen_seg_offset,8000h    ; No, set up for graphics display
  104. exit:    mov    dx,offset load_watch    ; Set up everything but this program to
  105.     int    27h            ; stay and attach itself to DOS
  106. load_watch    endp
  107.     code_seg    ends
  108.     end    first    ; END "FIRST" so 8088 will go to FIRST first.
  109.