This service is used to obtain a unique real mode SEG:OFFSET that will transfer control from real mode to a protected mode procedure.
At times it is necessary to hook a real mode interrupt or device call-back in a protected mode driver. For example, many mouse drivers call an address whenever the mouse is moved. Software running in protected mode can use a real mode call-back to intercept the mouse driver calls.
To Call
AX = 0303h
DS:(E)SI = Selector:Offset of procedure to call
ES:(E)DI = Selector:Offset of real mode call structure
Returns
If function was successful:
Carry flag is clear.
CX:DX = Segment:Offset of real mode call address
If function was not successful:
Carry flag is set.
Call-Back Procedure Parameters
Interrupts disabled
DS:(E)SI = Selector:Offset of real mode SS:SP
ES:(E)DI = Selector:Offset of real mode call structure
SS:(E)SP = Locked protected mode API stack
All other registers undefined
Return from Call-Back Procedure
Execute an IRET to return
ES:(E)DI = Selector:Offset of real mode call structure
to restore (see note)
Programmer's Notes
Example Code
The following code is a sample of a real mode interrupt hook. It hooks the DOS Int 21h and returns an error for the delete file function (AH=41h). Other calls are passed through to DOS. This example is somewhat silly but it demonstrates the techniques used to hook a real mode interrupt. Note that since DOS calls are reflected from protected mode to real mode, the following code will intercept all DOS calls from both real mode and protected mode.
;******************************************************
; This procedure gets the current Int 21h real mode
; Seg:Offset, allocates a real mode call-back address,
; and sets the real mode Int 21h vector to the call-
; back address.
;******************************************************
Initialization_Code:
;
; Create a code segment alias to save data in
;
mov ax, 000Ah
mov bx, cs
int 31h
jc ERROR
mov ds, ax
ASSUMES DS,_TEXT
;
; Get current Int 21h real mode SEG:OFFSET
;
mov ax, 0200h
mov bl, 21h
int 31h
jc ERROR
mov [Orig_Real_Seg], cx
mov [Orig_Real_Offset], dx
;
; Allocate a real mode call-back
;
mov ax, 0303h
push ds
mov bx, cs
mov ds, bx
mov si, OFFSET My_Int_21_Hook
pop es
mov di, OFFSET My_Real_Mode_Call_Struc
int 31h
jc ERROR
;
; Hook real mode int 21h with the call-back address
;
mov ax, 0201h
mov bl, 21h
int 31h
jc ERROR
;******************************************************
;
; This is the actual Int 21h hook code. It will return
; an "access denied" error for all calls made in real
; mode to delete a file. Other calls will be passed
; through to DOS.
;
; ENTRY:
; DS:SI -> Real mode SS:SP
; ES:DI -> Real mode call structure
; Interrupts disabled
;
; EXIT:
; ES:DI -> Real mode call structure
;
;******************************************************
My_Int_21_Hook:
cmp es:[di.RealMode_AH], 41h
jne Chain_To_DOS
;
; This is a delete file call (AH=41h). Simulate an
; iret on the real mode stack, set the real mode
; carry flag, and set the real mode AX to 5 to indicate
; an access denied error.
;
cld
lodsw ; Get real mode ret IP
mov es:[di.RealMode_IP], ax
lodsw ; Get real mode ret CS
mov es:[di.RealMode_CS], ax
lodsw ; Get real mode flags
or ax, 1 ; Set carry flag
mov es:[di.RealMode_Flags], ax
add es:[di.RealMode_SP], 6
mov es:[di.RealMode_AX], 5
jmp My_Hook_Exit
;
; Chain to original Int 21h vector by replacing the
; real mode CS:IP with the original Seg:Offset.
;
Chain_To_DOS:
mov ax, cs:[Orig_Real_Seg]
mov es:[di.RealMode_CS], ax
mov ax, cs:[Orig_Real_Offset]
mov es:[di.RealMode_IP], ax
My_Hook_Exit:
iret