One interrupt routine you may want to redefine is the routine called by INTO. The INTO (Interrupt on Overflow) instruction is a variation of the INT instruction. It calls interrupt 04h when the overflow flag is set. By default, the routine for interrupt 4 simply consists of an IRET, so it returns without doing anything. Using INTO is an alternative to using JO (Jump on Overflow) to jump to an overflow routine.
To replace or redefine an existing interrupt, your routine must
Replace the address in the interrupt descriptor table with the address of your new routine and save the old address
Provide new instructions to handle the interrupt
Restore the old address when your routine ends
An interrupt routine can be written like a procedure by using the PROC and ENDP directives. The routine should always be defined as FAR and should end with an IRET instruction instead of a RET instruction.
NOTE:
Since the assembler doesn't know whether you are going to terminate with RET or IRET, you can use the full extended PROC syntax (described in Section 7.3.3, “Declaring Parameters with the PROC Directive”) to write interrupt procedures. However, you should not make interrupt procedures NEAR or specify arguments for them. You can use the USES keyword, however, to correctly generate code to save and to restore a register list in interrupt procedures.
The STI (Set Interrupt Flag) and CLI (Clear Interrupt Flag) instructions turn interrupts on or off. You can use CLI to turn off interrupt processing so that an important routine cannot be stopped by a hardware interrupt. After the routine has finished, use STI to turn interrupt processing back on. Interrupts received while interrupt processing was turned off by CLI are saved and executed when STI turns interrupts back on.
MASM 6.0 provides two new forms of the IRET instruction that suppress epilogue sequences. This allows an interrupt to have local variables or use a user-defined prologue. IRETF pops a FAR16 return address, and IRETFD pops a FAR32 return address.
The following example uses DOS functions to save the address of the initial interrupt routine in a variable and to put the address of the new interrupt routine in the interrupt descriptor table. Once the new address has been set, the new routine is called any time the interrupt is called. This new routine prints a message and sets AX and DX to 0.
To replace the address in the interrupt descriptor table with the address of your procedure, AL needs to be loaded with 04h and AH loaded with 35, the Get Interrupt Vector function. The Set Interrupt Vector function requires 25 in AH.
Follow this example to replace an existing interrupt routine. To write an interrupt handler for an unused interrupt, see online help for available vectors.
.MODEL LARGE, C, DOS
FPFUNC TYPEDEF FAR PTR
.DATA
msg BYTE "Overflow - result set to 0",13,10,"$"
vector FPFUNC ?
.CODE
.STARTUP
mov ax, 3504h ; Load interrupt 4 and call DOS
int 21h ; Get Interrupt Vector function
mov WORD PTR vector[2],es ; Save segment
mov WORD PTR vector[0],bx ; and offset
push ds ; Save DS
mov ax, cs ; Load segment of new routine
mov ds, ax
mov dx, OFFSET ovrflow ; Load offset of new routine
mov ax, 2504h ; Load interrupt 4 and call DOS
int 21h ; Set Interrupt Vector function
pop ds ; Restore
.
.
.
add ax, bx ; Do addition (or multiplication)
into ; Call interrupt 4 if overflow
.
.
.
lds dx, vector ; Load original interrupt address
mov ax, 2504h ; Restore interrupt number 4
int 21h ; with DOS set vector function
mov ax, 4C00h ; Terminate function
int 21h
ovrflow PROC FAR
sti ; Enable interrupts
; (turned off by INT)
mov ah, 09h ; Display string function
mov dx, OFFSET msg ; Load address
int 21h ; Call DOS
sub ax, ax ; Set AX to 0
sub dx, dx ; Set DX to 0
iret ; Return
ovrflow ENDP
END
Before your program ends, you should restore the original address by loading DX with the original interrupt address and using the DOS set vector function to store the original address at the correct location.