Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Critical Error Handler - Int 24h

42 views
Skip to first unread message

Andy Mullen :o)

unread,
Feb 22, 2000, 3:00:00 AM2/22/00
to
Hi All,

I am trying to trap the critical error interrupt 24h using procedures in a
COM program.
I have set the model to TINY and have used int 21, functions 35h/25h to get
the old interrupt vector, and set the new vector to point to my new handler.

When the interrupt occurs, it processes the instructions in the new
interrupt handler, but it doesn't resume back to the main code......instead,
it just terminates there and then.

I have used IRET to return from the interrupt handler, but it doesn't seem
to work.

Any ideas?

Andy :o)

Here's the code I have used:


.MODEL TINY
.STACK
.DATA

InstalledMsg db 'Installed$'
RemovedMsg db 'Removed$'
_OldCritHandler dd ?


.CODE
org 100h

main proc
;Install handler
CALL InstallHandler

mov ax,0900h ; Display a message
lea dx,InstalledMsg ; stating that the handler is installed
int 21h

mov ax,1C00h ; Get info for
mov dx,1 ; Drive A
int 21h ; (Without floppy in drive should
cause crit err

; Code should resume here
CALL RemoveHandler ; Remove our handler and put the old one back

mov ax,0900h ; Display a message stating that the
handler
lea dx,RemovedMsg ; was removed
int 21h

; Terminate
mov ax,4C00h ; 0 in return code
int 21h ; end here.
main endp

InstallHandler proc uses ax bx ds es
mov ah,35h ; Get old int vector
mov al,24h ; of Interrupt 24h
int 21h ; Got get it.

mov word ptr _OldCritHandler,bx ; Store original offset
mov word ptr _OldCritHandler+2,es ; Store original segment

lea dx,CriticalHandler ; Load DS:DX with offset of new handler
mov ah,25h ; Set int vector
mov al,24h ; of int 24h
int 21h ; Do it!
ret ; Return to main code
InstallHandler endp


RemoveHandler proc uses ax bx ds
mov dx,word ptr _OldCritHandler ; Restore original offset
mov ds,word ptr _OldCritHandler+2 ; Restore original segment
mov ah,25h ; Set int vector
mov al,24h ; of 24h
int 21h ; Do it!
ret ; Return to main code
RemoveHandler endp


CriticalHandler proc far
push ax ; Push ax and dx as we modify them
push dx
mov ax,0200h ; Disaply one character
mov dx,7h ; Beep character
int 21h
pop dx
pop ax
iret ; Do nothing else, just ignore the
error and keep results
CriticalHandler endp

end main


John Walker

unread,
Feb 22, 2000, 3:00:00 AM2/22/00
to

Andy Mullen :o) wrote in message <88t34g$20e$1...@neptunium.btinternet.com>...
call the old handler here. I don't know how you would do that in asm,
but I guess it would look something like this :
jmp _OldCritHandler:_OldCritHandler+2 ;or something, maybe just jmp
_OldCritHandler

E.P. van Westendorp

unread,
Feb 22, 2000, 3:00:00 AM2/22/00
to
I wrote the program like you see below.
About the same code can also be used to check for a CD-ROM.

--

Eric P. van Westendorp Tel: +31(0252)210579
Reigerslaan 22 2215NN Voorhout Netherlands

TITLE CRITERR.ASM

;Demo Critical Error Handler
;Checks critical error on drive A:
;MASM 6.11D used ML /AT CRITERR.ASM

CODE SEGMENT 'CODE'
ASSUME DS:CODE,SS:CODE
ORG 0100H ;Code loaded at offset 0100H
.RADIX 10H ;Default all HEX
.486 ;80486+

;Get vector Critical Error Handler from PSP
;Store in own handler
MAIN PROC FAR
MOV EAX,DS:DWORD PTR[0012] ;Get vector from PSP
MOV [OLD_CRIT],EAX ;Store in new handler

;Revector Critical Error to own handler
;Vector later restored by INT 21 func 4C
MOV AX,2524 ;Set interrupt vector INT 24
MOV DX,OFFSET CRIT_ERR ; to handler
INT 21 ;Dos

;Try to read something from disk A:, like its free space
MOV AH,36 ;Get disk free space
MOV DL,01 ;A:=1 etc
INT 21 ;Dos
CMP AX,0FFFF ;Valid?
MOV DX,OFFSET FAIL_MESS ;Assume fail
JZ MESS_EXIT ;No Disk
MOV DX,OFFSET SUCCES_MESS ;Disk OK

;Print message DS:DX
MESS_EXIT: MOV AH,09 ;Print string
INT 21 ;Dos
MOV AX,4C00 ;Terminate program
INT 21 ;Dos
MAIN ENDP

;Replace default Critical Error Handler, disable Retry, Fail, Continue
mess
CRIT_ERR PROC FAR
TEST AH,10000000Y ;A block device caused error?
JNZ CONT_CRIT ;No
OR AL,AL ;Did drive A: cause the error?
JNZ CONT_CRIT ;No, another block device
MOV AL,03 ;Return to program with error
TEST AH,00001000Y ;Allowed to terminate function?
JNZ RET_ACT ;Yes
DEC AL ;No, terminate the program
RET_ACT: IRET

;Not a critical error on drive A:, jump to address orignal crit. error
handler
CONT_CRIT:
DB 0EA ;JMP FAR
OLD_CRIT DD 00000000 ;Stores addres original handler
CRIT_ERR ENDP

;Messages
FAIL_MESS DB 0A,0D,"Drive A: not ready$"
SUCCES_MESS DB 0A,0D,"Drive A: ready$"

CODE ENDS
END MAIN

Kees Nuyt

unread,
Feb 22, 2000, 3:00:00 AM2/22/00
to
On Tue, 22 Feb 2000 04:22:41 -0000, "Andy Mullen :o)"
<An...@Support.btinternet.com> wrote:

>I am trying to trap the critical error interrupt 24h using procedures in a
>COM program.
>I have set the model to TINY and have used int 21, functions 35h/25h to get
>the old interrupt vector, and set the new vector to point to my new handler.

So far, so good.

>When the interrupt occurs, it processes the instructions in the new
>interrupt handler, but it doesn't resume back to the main code......instead,
>it just terminates there and then.

It's not a normal interrupt handler.

>I have used IRET to return from the interrupt handler, but it doesn't seem
>to work.

From the MS-DOS 3.1 Programmer's Reference Manual, probably
still valid ...; my comments between () as in (comment -- KN)

"
After retrying an I/O error three times, MS-DOS issues Interrupt
24H. The interrupt handler receives control with interrupts
disabled. AX and DI contain error codes, and BP contains the
offset (to the segment address in SI) of a Device Header control
block that describes the device on which the error occurred.

Requirements for an Interrupt 24H handler
To use (you don't have to -- KN) the MS-DOS critical error
handler to issue the "Abort, Retry, or Ignore" prompt and get
the user's response, the first thing a user-written critical
error handler should do is push the flags and execute a far call
to the address of the standard Interrupt 24H handler (the user
program that changed the Interrupt 24H vector should have saved
this address). After the user responds to the prompt, MS-DOS
returns control to the user-written routine.

NOTE: there are _source_ applications which will have trouble
with this as it changes the stack frame. (Don't know what that
means -- KN)

The error handler can do its processing now, but beforeit does
anything else, it must preserve BX, CX, DX, DS, ES, SS and SP.
Only function calls 01-0Ch inclusive and 59h may be used (if it
uses any others, the MS-DOS stack is destroyed and MS-DOS is
left in an unpredictable state), nor should it change the
contents of the device header.

If an Interrupt 24H routine returns to the user program (rather
than returning to MS-DOS), it must restore the user program's
register -!!- removing all but the last three words from the
stack -!!- and issue an IRET. Control returns to the statement
immediately following the I/O function request that resulted in
the error. This leaves MS-DOS in an unstable state until a
function request above 0CH is called.

User Stack.
The user stack is in effect, and contains the following
(starting with the top of the stack):
IP -MS-DOS registers from
CS -issuing Interrupt 24H
FLAGS

AX -user registers at time
BX -of original INT 21H
CX -(saved by MS-DOS -- KN)
DX
SI
DI
BP
DS
ES

IP -From the original INT
CS -21h from the user to MS-DOS
FLAGS

The registers are set such that if the user-written error
handler issues an IRET (immediately, without popping the user
regs, so returning to MS-DOS I/O routines -- KN), MS-DOS
responds according to the value in AL:
AL Action
0 Ignore the error
1 Retry the operation
2 Abort the program by issuing Interrupt 23H
3 Fail the system call that is in progress.

(I think this applies if you
- either far-call the original handler
- or set AL by yourself
and IRET immediately, without popping the user
registers; MS-DOS I/O would take over; ignore, retry, abort or
fail according to the value in AL, and return to the user
program itself. -- KN)

Note that the ignore option may cause unexpected results as it
causes MS-DOS to believe that an operation completed
successfully when it didn't.
"

My conclusion:
You have to pop three dummy's (for IP, CS and FLAGS)
and AX, BX, CX, DX, SI, DI, BP, ES and DS before
issuing the IRET that returns to the user program.

Succes !

--
( Kees Nuyt; Rotterdam; Netherlands
) mailto:nu...@ipr.nl
c[_] Disclaimer: Any opinions etc. are mine, not necessarily my employer's.

0 new messages