home *** CD-ROM | disk | FTP | other *** search
- .386p
- ;************************************************************************/
- ;* Copyright (C) 1986-1990 Phar Lap Software, Inc. */
- ;* Unpublished - rights reserved under the Copyright Laws of the */
- ;* United States. Use, duplication, or disclosure by the */
- ;* Government is subject to restrictions as set forth in */
- ;* subparagraph (c)(1)(ii) of the Rights in Technical Data and */
- ;* Computer Software clause at 252.227-7013. */
- ;* Phar Lap Software, Inc., 60 Aberdeen Ave., Cambridge, MA 02138 */
- ;************************************************************************/
-
- ;
- ; This program demonstrates
- ;
-
- ;
- ; Constants and data structures
- ;
- include dosx.ah
-
- ;
- ; Segment definitions and ordering.
- ;
- _codeseg segment byte public use32 'code'
- _codeseg ends
- _data segment dword public use32 'data'
- _data ends
- _stack segment dword stack use32 'stack'
- db 2048 dup (?) ; 2K stack
- _stack ends
-
- ;
- ; Global data
- ;
- _data segment
-
- public pm_cesel,pm_ceoff,rm_cevec
- rm_cevec dd ? ; original real mode critical err vector
- pm_ceoff dd ? ; original protected mode critical err vector
- pm_cesel dw ? ;
- align 4
-
- afile db 'a:\foo',0
- status_msg db 'Causing critical err by reading from open A: floppy drive'
- db 0Dh,0Ah,'$'
- _data ends
-
- ;****************************************************************************
- ; Program entry point
- ;****************************************************************************
-
- assume cs:_codeseg,ds:_data
- _codeseg segment
-
- public main
- main proc near
-
- ;
- ; Save current real and protected mode critical error vectors, and install our
- ; critical error handler so it always gets control in protected mode. We use
- ; the 2506h system call to do this, because the critical error interrupt is
- ; always issued in real mode by DOS.
- ;
- mov cl, 24h ; save real mode critical error vector
- mov ax, 2503h ;
- int 21h ;
- mov rm_cevec, ebx ;
- mov ax, 2502h ; save prot mode critical error vector
- mov cl,24h ;
- int 21h ;
- mov pm_cesel, es ;
- mov pm_ceoff, ebx ;
- push ds ; install our critical error handler
- lea edx, crite_hnd ; to always get control in
- mov ax, cs ; protected mode
- mov ds, ax ;
- mov cl,24h ;
- mov ax, 2506h ;
- int 21h ;
- pop ds ;
-
- ;
- ; Cause a critical error by attempting to open a file on the A: floppy
- ; disk drive (which will cause a critical error if the floppy door is
- ; open).
- ;
- mov ah, 09h ; tell user we're causing CTRL/C
- lea edx, status_msg ;
- int 21h ;
- lea edx,afile ; open file on A: drive
- mov ax,3D00h ;
- int 21h ;
-
- ;
- ; Restore the original interrupt vectors and exit
- ;
- mov cl, 24h ; restore original real mode vector
- mov ebx, rm_cevec ;
- mov ax, 2505h ;
- int 21h ;
- push ds ; restore original prot mode vector
- mov edx, pm_ceoff ;
- mov ax, pm_cesel ;
- mov ds, ax ;
- mov cl,24h ;
- mov ax, 2504h ;
- int 21h ;
- pop ds ;
-
- mov ax,4C00h ; exit to DOS
- int 21h ;
- main endp
-
- ;****************************************************************************
- ; CRITE_HND - Protected Mode Critical Error Handler
- ; It just prints out a message saying the error occurred, and then
- ; returns, instructing DOS to fail the system call that caused the error.
- ;
- ; To demonstrate how to use the interrupt stack frame to get the
- ; original stack when the interrupt occurred, we pick up the
- ; original AX value for the INT 21h call (saved on the critical error
- ; stack by DOS) and print out AH to show what call it was that failed.
- ;****************************************************************************
- public crite_hnd
- crite_hnd proc near
- ;
- ; Interrupt handler stack frame
- ;
- #FLGS equ (dword ptr 52[ebp]) ; 386|DOS-Extender flags
- #GS equ (word ptr 48[ebp]) ; original GS
- #FS equ (word ptr 44[ebp]) ; original FS
- #DS equ (word ptr 40[ebp]) ; original DS
- #ES equ (word ptr 36[ebp]) ; original ES
- #SS equ (word ptr 32[ebp]) ; original SS
- #ESP equ (dword ptr 28[ebp]) ; original ESP
- #EFLAGS equ (dword ptr 24[ebp]) ; original EFLAGS
- #CS equ (dword ptr 20[ebp]) ; original CS
- #EIP equ (dword ptr 16[ebp]) ; original EIP
- #EBP equ (dword ptr [ebp]) ; original EBP
-
- ;
- ; This is an interrupt handler, so we must preserve all registers we use.
- ; Also re-enable interrupts so hardware interrupts aren't blocked.
- ;
- sti ; re-enable interrupts
- push ebp ; set up stack frame
- mov ebp,esp ;
- push ebx ; save regs, EXCEPT EAX which we
- push ecx ; return a value in
- push edx ;
- push ds ;
- push es ;
- mov ax,SS_DATA ; set DS to our data segment
- mov ds,ax ;
-
- ;
- ; Get the real mode stack address in ES:EBX. The critical error
- ; interrupt should ALWAYS be issued from real mode, but check in case
- ; someone coded a software INT 24h in prot mode by mistake.
- ;
- test #FLGS,IFL_RMODE ; branch if didn't come from real
- jz #not_real ; mode
- movzx ebx,#SS ; get linear addr of real mode stack
- shl ebx,4 ; in conventional memory
- add ebx,#ESP ;
- mov ax,SS_DOSMEM ; set ES to DOS memory segment
- mov es,ax ;
-
- ;
- ; Print out a message, and the AH value for the INT 21h call that failed,
- ; so the user can see what the call was.
- ;
- ; DOS critical error stack frame
- ;
- #DOS_FLAGS equ (word ptr es:22[ebx]) ; interrupt stack frame from real
- #DOS_CS equ (word ptr es:20[ebx]) ; mode INT 21h
- #DOS_IP equ (word ptr es:18[ebx]) ;
- #DOS_ES equ (word ptr es:16[ebx]) ; regs at time INT 21h was issued
- #DOS_DS equ (word ptr es:14[ebx]) ; in real mode
- #DOS_BP equ (word ptr es:12[ebx]) ;
- #DOS_DI equ (word ptr es:10[ebx]) ;
- #DOS_SI equ (word ptr es:8[ebx]) ;
- #DOS_DX equ (word ptr es:6[ebx]) ;
- #DOS_CX equ (word ptr es:4[ebx]) ;
- #DOS_BX equ (word ptr es:2[ebx]) ;
- #DOS_AX equ (word ptr es:[ebx]) ;
-
- _data segment
- ce_msg db 'Critical error occurred on INT 21h function $'
- _data ends
- mov ah,9 ; print critical err msg
- lea edx,ce_msg ;
- int 21h ;
- mov ax,#DOS_AX ; get original AX value
- mov al,ah ; convert AH to ASCII, save in BX
- call btohex ;
- mov bx,ax ;
- mov ah,2 ; output function code & newline
- mov dl,bl ;
- int 21h ;
- mov dl,bh ;
- int 21h ;
- mov dl,0Dh ;
- int 21h ;
- mov dl,0Ah ;
- int 21h ;
-
- #exit:
- mov eax,3 ; instruct DOS to fail the function
- ; (DOS 3.1 and later only)
- pop es ; restore regs
- pop ds ;
- pop edx ;
- pop ecx ;
- pop ebx ;
- pop ebp ;
- iretd ; return from interrupt
-
- #not_real:
- ;
- ; Interrupt didn't originate from real mode
- ;
- _data segment
- nreal_msg db 'Critical error interrupt issued in prot mode!!',0Dh,0Ah,'$'
- _data ends
- mov ah,9 ; print error msg & exit
- lea edx,nreal_msg ;
- int 21h ;
- jmp #exit ;
- crite_hnd endp
-
- ;****************************************************************************
- ; BTOHEX -- convert byte in AL to ASCII hex in AX, all other regs unchanged
- ;****************************************************************************
- btohex proc near ; convert byte to hex
- push bx ; save regs
- mov ah,0 ; make sure AH is 0
- mov bx,ax ; save value to convert
- call ntohex ; get LS hex digit into BL
- xchg ax,bx ;
- shr ax,4 ; get MS hex digit into AL
- call ntohex ;
- shl bx,8 ; combine the two digits in AX
- or ax,bx ;
- pop bx ; restore regs & exit
- ret
- btohex endp
-
- ntohex proc near ; convert nibble to ascii hex
- and ax,0Fh ; mask out all but low nibble
- cmp ax,10 ; branch if digit from 0 - 9
- jb short #digit ;
- add ax,'A' - 10 ; digit from A-F
- ret ;
- #digit:
- add ax,'0' ; digit from 0-9
- ret
- ntohex endp
- _codeseg ends
-
- end main
-