|
Get, Set, and Restore Interrupt VectorsAs we start writing our own interrupt handlers, we will need to replace or chain to interrupts. We will also need to restore the original vectors before we leave our program. If we don't, our code will be reclaimed by the operating system and used for subsequent programs. This isn't so bad, but the interrupt vector will still point to the place where our code was! If that interrupt is generated, it will jump to garbage and try to execute! So how do we get an interrupt vector? Well, one approach is to allocate some memory in your data or code segment using labels. Next, you can use the DOS service routines to get or set an interrupt. I recommend making a macro for this to save yourself some effort. The following code should help you on your way. Notice that the interrupt routine is simply a FAR procedure. This means we can start writing our interrupt service routines as procedures that we call until we know they work. The only difference is that we need to balance the stack so we must do a pushf before we call the function.
TITLE int_test.asm
;=======================================================================
; gets, sets, and restores an interrupt vector
;=======================================================================
_DATA SEGMENT USE16 BYTE PUBLIC 'DATA'
_DATA ENDS
_TEXT SEGMENT USE16 WORD PUBLIC 'CODE'
ASSUME cs:_TEXT, ds:_DATA
orig80hVector LABEL DWORD
orig80hOffset DW ?
orig80hSegment DW ?
PROC newInt80h FAR ; this should go in its own module
iret ; or library routine !!!!
ENDP ; notice this is a FAR procedure - required
; for interrupt code that we will write
Start:
mov ax, _DATA
mov ds, ax
;----------------------------------------------------------------
; Get Old Vector
;----------------------------------------------------------------
mov al, 80h ; vector to retrieve
mov ah, 35h ; function: get interrupt vector
int 21h
mov cs:orig80hOffset, bx ; save the old seg:off of 80h vector
mov cs:orig80hSegment, es
;----------------------------------------------------------------
; Set New Vector
;----------------------------------------------------------------
mov dx, OFFSET newInt80h
mov ax, SEG newInt80h
mov ds, ax ; ds:dx points to our interrupt routine
mov al, 80h ; interrupt function to get
mov ah, 25h ; function: set interrupt vector
int 21h
;----------------------------------------------------------------
; Call our Vector as a procedure (good method of testing...)
;----------------------------------------------------------------
pushf
call newInt80h
;----------------------------------------------------------------
; We could call the old vector, but we don't know what this will do
;----------------------------------------------------------------
;pushf
;call cs:orig80hVector
;----------------------------------------------------------------
; Call our Vector as an interrupt
;----------------------------------------------------------------
int 80h
;----------------------------------------------------------------
; Restore Old Vector
;----------------------------------------------------------------
mov dx, cs:orig80hOffset
mov ax, cs:orig80hSegment
mov ds, ax ; ds:dx points to our interrupt routine
mov al, 80h ; interrupt function to get
mov ah, 25h ; function: set interrupt vector
int 21h
;----------------------------------------------------------------
; Exit Program (just like normal :)
;----------------------------------------------------------------
mov ax, 4C00h ; function: exit program and return to DOS
int 21h
_TEXT ENDS
_STACK SEGMENT USE16 STACK 'STACK'
DW 100 dup(?)
_STACK ENDS
END Start
download the file here Last Modified: January 26, 1999 - Barry E. Mapen |