home *** CD-ROM | disk | FTP | other *** search
- .386p
- .387
- ;************************************************************************/
- ;* 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 how to write a protected mode hardware
- ; interrupt handler. It takes over the coprocessor exception (IRQ13),
- ; and then causes a 387 exception to let the handler get invoked.
- ;
-
- ;
- ; 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 irq8_vec,irq13_offs,irq13_sel,envblk
- irq8_vec db ? ; interrupt vector for IRQ8 interrupt
- align 4
- irq13_offs dd ? ; original IRQ13 handler address
- irq13_sel dw ? ;
- align 4
- ctl_387 dw 0 ; 387 control word with exceptions unmasked
- align 4
- minus_one dq -1.0 ; floating point constant
- envblk dd 7 dup (?) ; buffer for 387 environment block
-
- no387msg db 'No 387 coprocessor on this machine',0Dh,0Ah,'$'
- pmenvmsg db '80387 environment block:',0Dh,0Ah,'$'
-
- _data ends
-
- ;****************************************************************************
- ; Program entry point
- ;****************************************************************************
-
- assume cs:_codeseg,ds:_data
- _codeseg segment
-
- public main
- main proc near
-
- ;
- ; Check for a 387 present, exit if not
- ;
- int 11h ; BIOS equipment check
- test ax, 2 ; branch if no coprocessor
- jz #no_coproc ;
-
- ;
- ; Save current IRQ13 handler vector and install our own handler. We
- ; only need to hook protected mode interrupts because we are only going
- ; to execute coprocessor instructions in protected mode, so the coprocessor
- ; exception will never occur in real mode.
- ;
- mov ax, 250Ch ; get H/W int vector mappings
- int 21h ;
- mov irq8_vec, ah ;
- mov cl, irq8_vec ; save current IRQ13 handler
- add cl, 5 ;
- mov ax, 2502h ;
- int 21h ;
- mov irq13_sel, es ;
- mov irq13_offs, ebx ;
- push ds ; install our IRQ13 handler
- lea edx, irq13_hndlr ;
- mov cl, irq8_vec ;
- add cl, 5 ;
- mov ax, cs ;
- mov ds, ax ;
- mov ax, 2504h ;
- int 21h ;
- pop ds ;
-
- ;
- ; Cause a coprocessor exception
- ;
- finit ; init the 387
- fldcw ctl_387 ; unmask all exceptions
- fld minus_one ; square root of a negative number
- fsqrt ;
-
- ;
- ; Restore original IRQ13 handler and exit
- ;
- push ds ; restore original handler
- mov cl, irq8_vec ;
- add cl, 5 ;
- mov edx, irq13_offs ;
- mov ax, irq13_sel ;
- mov ds, ax ;
- mov ax, 2504h ;
- int 21h ;
- pop ds ;
- mov ax, 4C00h ; exit to DOS
- int 21h ;
-
- #no_coproc:
- ;
- ; No 387; print an error message and exit
- ;
- lea edx, no387msg ; print message
- mov ah, 9 ;
- int 21h ;
- mov ax, 4C01h ; exit to DOS
- int 21h ;
- main endp
-
- ;****************************************************************************
- ; IRQ13_HNDLR - Protected Mode Coprocessor Exception Handler
- ; This handler just stores the coprocessor environment and prints it
- ; out, clears the source of the exception, and returns.
- ;****************************************************************************
- public irq13_hndlr
- irq13_hndlr proc near
- ;
- ; Save regs and re-enable interrupts. It's good to re-enable interrupts
- ; when possible in an interrupt handler, so other hardware interrupts can
- ; occur.
- ;
- sti ; re-enable interrupts
- push eax ; save all registers we modify
- push ds ;
-
- ;
- ; Acknowledge the interrupt. Until we do this, neither this interrupt
- ; (IRQ13) nor any lower priority hardware interrupt can occur. After
- ; we do this, we must be prepared to deal with being reentered. In the
- ; case of a coprocessor exception handler, we don't have to worry about
- ; reentrancy because we won't cause another coprocessor exception inside
- ; the handler.
- ;
- mov al, 20h ; issue EOI to master 8259 interrupt
- out 20h, al ; controller
- out 0A0h, al ; issue EOI to slave 8259
- xor ax, ax ; Clear 387 BUSY signal
- out 0F0h, al ;
-
- ;
- ; Get the coprocessor environment and print it out
- ;
- mov ax, SS_DATA ; set DS to our data segment
- mov ds, ax ;
- fstenv envblk ; get 387 environment
- call display_env ; displays coprocessor environment
-
- ;
- ; Clear the 387 status and return to interrupted code.
- ;
- wait ; clear exception bits in 387 status
- fclex ;
- fldcw ctl_387 ; unmask all 387 exceptions
- pop ds ; restore regs
- pop eax ;
- iretd ; return to interrupted code
- irq13_hndlr endp
-
- ;****************************************************************************
- ; DISPLAY_ENV - Routine that displays the saved 387 environment block
- ; Destroys EAX, preserves all other registers.
- ;****************************************************************************
- public display_env
- display_env proc near
- push ecx ; save regs we use
- push edx ;
-
- lea edx, pmenvmsg ; print message
- mov ah, 09h ;
- int 21h ;
-
- mov ecx, 7 ; 7 DWORDs in environment
- lea edx, envblk ; ptr to beginning of block
- #loop:
- mov ax, [edx+2] ; print this doubleword
- call hwout ;
- mov ax, [edx] ;
- call hwout ;
- call newline ; output newline
- add edx, 4 ; step to next dword in env
- loop #loop ; continue loop
-
- pop edx ; restore registers and exit
- pop ecx ;
- ret ;
-
- display_env endp
-
- ;****************************************************************************
- ; hwout - Print word in AX in ascii hex, without modifying any regs except
- ; EAX.
- ;****************************************************************************
- hwout proc near
- push edx ; save regs
-
- push ax ; save current AX value
- shr ax,8 ; convert MS byte to ascii
- call btohex ;
- push ax ; save result
- mov dl,al ; print MS digit
- mov ah,2 ;
- int 21h ;
- pop dx ; print LS digit
- mov dl,dh ;
- int 21h ;
- pop ax ; convert LS byte to ascii
- call btohex ;
- push ax ; save result
- mov dl,al ; print MS digit
- mov ah,2 ;
- int 21h ;
- pop dx ; print LS digit
- mov dl,dh ;
- int 21h ;
-
- pop edx ; restore modifed regs & exit
- ret
- hwout endp
-
- 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
-
- ;****************************************************************************
- ; newline - output newline without modifying any regs
- ;****************************************************************************
- newline proc near
- push eax ; save regs
- push edx ;
-
- mov dl,0Dh ; output CR/LF
- mov ah,2 ;
- int 21h ;
- mov dl,0Ah ;
- int 21h ;
-
- pop edx ; restore regs & exit
- pop eax ;
- ret
- newline endp
-
- _codeseg ends
-
- end main
-