home *** CD-ROM | disk | FTP | other *** search
- ; By Steve Holzner (from June 11, 1985 issue of PC Magazine)
-
- interrupts segment at 0h ; This is where the disk interrupt
- org 13h*4 ; holds the address of its service routine
- disk_int label dword
- interrupts ends
-
- screen segment at 0B000h ; A dummy segment to use as the Extra
- screen ends ; Segment so we can write to the display
-
- code_seg segment
- assume cs:code_seg
- org 0100h ; ORG = 100h to make this a .COM file
- first: jmp load_watch ; First time through jump to initialize routine
-
- msg_part_1 db 'Disk error: ' ; Here are the error messages
- msg_part_2 db 'No response Failed Seek NEC Error '
- db 'Bad CRC SeenDMA Overrun Impos Sector'
- db 'No Addr MarkW. ProtectedErr Unknown '
- first_position dw ? ; Position of 1st char on screen
- flags dw ?
- screen_seg_offset dw 0 ; 0 for mono, 8000h for graphics
- old_disk_int dd ? ; Location of old disk interrupt
- ret_addr label dword ; Used in fooling around with
- ret_addr_word dw 2 dup(?) ; the stack
-
- disk_watch proc far ; The disk interrupt will now come here
- assume cs:code_seg
- pushf ; First, call old disk interrupt
- call old_disk_int
- pushf ; Save the flags in memory location "FLAGS"
- pop flags ; (cunning name)
- jc error ; If there was an error, carry flag will have
- jmp fin ; been set by Disk Interrupt
- error: push ax ; AH has the status of the error
- push cx ; Push all used registers for politeness
- push dx
- push di
- push si
- push es
- lea si,msg_part_1 ; Always print "Disk Error: " part.
- assume es:screen ; Use screen as extra segment
- mov dx,screen
- mov es,dx
- mov di,screen_seg_offset ; DI will be pointer to screen position
- add di,first_position ; Add to point to desired area on screen
- call write_to_screen ; This writes 12 chars from [SI] to [DI]
- mov dx,80h ; Initialize for later comparisons
- mov cx,7 ; Loop seven times
- e_loop: cmp ah,dh ; Are error code and DH the same?
- je e_found ; If yes, Error has been found
- add si,12 ; Point to next error message
- shr dh,1 ; Divide DH by 2
- loop e_loop ; Keep going until matched DH = 0
- cmp ah,3 ; Error code no even number; 3 perhaps?
- je e_found ; If yes, have found the error
- add si,12 ; Err unknown; unknown error returned
- e_found:call write_to_screen ; Write the error message to the screen
- pop es ; Restore the registers
- pop si
- pop di
- pop dx
- pop cx
- pop ax
- fin: pop ret_addr_word ; Fooling with the stack. We want to
- pop ret_addr_word[2] ; preserve the flags but the old flags
- add sp,2 ; are still on the stack. First remove
- push flags ; return address, then flags. Fill flags
- popf ; from "FLAGS", return to correct addr.
- jmp ret_addr
- disk_watch endp
-
- write_to_screen proc near ; Puts 12 characters on screen
- mov cx,12 ; Loop 12 times
- w_loop: movs es:byte ptr[di],cs:[si] ; Move to the screen
- mov al,7 ; Move screen attribute into screen buffer
- mov es:[di],al
- inc di ; Point to next byte in screen buffer
- loop w_loop ; Keep going until done
- ret
- write_to_screen endp
-
- load_watch proc near ; This procedure initializes everything
- assume ds:interrupts ; The data segment will be the interrupt area
- mov ax,interrupts
- mov ds,ax
-
- mov ax,disk_int ; Get the old interrupt service routine
- mov old_disk_int,ax ; address and put it into our location
- mov ax,disk_int[2] ; OLD_DISK_INT so we can call it.
- mov old_disk_int[2],ax
-
- mov disk_int,offset disk_watch ; Now load the address of DskWatch
- mov disk_int[2],cs ; routine into the disk interrupt
-
- mov ah,15 ; Ask for service 15 of INT 10h
- int 10h ; This tells us how display is set up
- sub ah,25 ; Move to twenty five places before edge
- shl ah,1 ; Mult. by two (char & attribute bytes)
- mov byte ptr first_position,ah ; Set screen cursor
- test al,4 ; Is it a monochrome display?
- jnz exit ; Yes - jump out
- mov screen_seg_offset,8000h ; No, set up for graphics display
- exit: mov dx,offset load_watch ; Set up everything but this program to
- int 27h ; stay and attach itself to DOS
- load_watch endp
- code_seg ends
- end first ; END "FIRST" so 8088 will go to FIRST first.