⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 int31.gml

📁 开放源码的编译器open watcom 1.6.0版的源代码
💻 GML
📖 第 1 页 / 共 4 页
字号:
.note
When the Int 31h returns, the real-mode call structure will contain
the values that were returned by the real-mode procedure.
.note
The flags specified in the real-mode call structure will be pushed the
real-mode stack
.mono iret
frame. The procedure will be called with the interrupt and trace flags
clear.
.note
It is up to the caller to remove any parameters that were pushed on
the protected-mode stack.
.note
The flag to reset the interrupt controller and A20 line is ignored by
DPMI implementations that run in Virtual 8086 mode. It causes DPMI
implementations that return to real mode to set the interrupt
controller and A20 address line hardware to its normal real-mode
state.
.endnote
.*
.note Function 0303H
.*
.ix 'DPMI' 'allocate real-mode callback address'
(&dos4gprd Professional only)
This function allocates a real-mode callback address.
This service is used to obtain a unique real-mode SEG:OFFSET that will
transfer control from real mode to a protected-mode procedure.
.np
At times it is necessary to hook a real-mode interrupt or device
callback 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 callback to intercept the mouse
driver calls.
Pass the following information:
.begpoint $compact
.point AX = 0303H
.point DS:ESI = selector:offset of procedure to call
.point ES:EDI = selector:offset of real-mode call structure
.endpoint
.np
If the call succeeds, the carry flag is clear and CX:DX contains the
.mono segment:offset
of real-mode callback address.
.np
If the call fails, the carry flag is set.
.begnote
.note Callback Procedure Parameters
.illust begin
Interrupts disabled
DS:ESI = selector:offset of real-mode SS:SP
ES:EDI = selector:offset of real-mode call structure
SS:ESP = Locked protected-mode API stack
All other registers undefined
.illust end
.note Return from Callback Procedure
.illust begin
Execute an IRET to return
ES:EDI =  selector:offset of real-mode call structure
to restore (see note)
.illust end
.endnote
.autonote Notes:
.note
Since the real-mode call structure is static, you must be careful when
writing code that may be reentered. The simplest method of avoiding
reentrancy is to leave interrupts disabled throughout the entire call.
However, if the amount of code executed by the callback is large then
you will need to copy the real-mode call structure into another
buffer. You can then return with ES:EDI pointing to the buffer you
copied the data to &mdash. it does not have to point to the original real
mode call structure.
.note
The called procedure is responsible for modifying the real-mode CS:IP
before returning. If the real-mode CS:IP is left unchanged then the
real-mode callback will be executed immediately and your procedure
will be called again. Normally you will want to pop a return address
off of the real-mode stack and place it in the real-mode CS:IP. The
example code in the next section demonstrates chaining to another
interrupt handler and simulating a real-mode
.mono iret.
.note
To return values to the real-mode caller, you must modify the
real-mode call structure.
.note
Remember that all segment values in the real-mode call structure will
contain real-mode segments, not selectors. If you need to examine data
pointed to by a real-mode seg:offset pointer, you should not use the
segment to selector service to create a new selector. Instead,
allocate a descriptor during initialization and change the
descriptor's base to 16 times the real-mode segment's value. This is
important since selectors allocated though the segment to selector
service can never be freed.
.note
DPMI hosts should provide a minimum of 16 callback addresses per
task.
.endnote
.np
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.
.code begin
;******************************************************
; This procedure gets the current Int 21h real-mode
; Seg:Offset, allocates a real-mode callback 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 callback
;
        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 callback 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
.code end
.*
.note Function 0304H
.*
.ix 'DPMI' 'free real-mode callback address'
(&dos4gprd Professional only)
This function frees a real-mode callback address that was allocated
through the allocate real-mode callback address service.
Pass the following information:
.begpoint $compact
.point AX = 0304H
.point CX:DX = Real-mode callback address to free
.endpoint
.np
If the call succeeds, the carry flag is clear; if it fails, the carry
flag is set.
.autonote Notes:
.note
Real-mode callbacks are a limited resource. Your code should free any
break point that it is no longer using.
.endnote
.*
.endnote
.*
.section DPMI Version
.*
.begnote
.*
.note Function 0400H
.*
.ix 'DPMI' 'get DPMI version'
This function returns the version of DPMI services supported. Note
that this is not necessarily the version of any operating system that
supports DPMI. It should be used by programs to determine what calls
are legal in the current environment.
Pass the following information:
.begpoint $compact
.point AX = 0400H
.endpoint
.np
The information returned is:
.begpoint $compact
.point AH = Major version
.point AL = Minor version
.point BX = Flags
Bit 0 = 1 if running under an 80386 DPMI implementation.
Bit 1 = 1 if processor is returned to real mode for reflected
interrupts (as opposed to Virtual 8086 mode).
Bit 2 = 1 if virtual memory is supported.
Bit 3 is reserved and undefined.
All other bits are zero and reserved for later use.
.point CL = Processor type
.illust begin
02 = 80286
03 = 80386
04 = 80486
05 = Pentium
.illust end
.point DH = Current value of virtual master PIC base interrupt
.point DL = Current value of virtual slave PIC base interrupt
.point Carry flag clear (call cannot fail)
.endpoint
.*
.endnote
.*
.section Memory Management Services
.*
.begnote
.*
.note Function 0500H
.*
.ix 'memory management services'
.ix 'DPMI' 'get free memory information'
This function gets information about free memory.
Pass the following information:
.begpoint $compact
.point AX = 0500H
.point ES:EDI = the selector:offset of a 30H byte buffer.
.endpoint
.np
If the call fails, the carry flag is set.
.np
If the call succeeds, the carry flag is clear and ES:EDI contains the
.mono selector:offset
of a buffer with the structure shown in the figure below.
.np
.se c0=&INDlvl-1+11
.se c1=&INDlvl-1+19
.se c2=&INDlvl-1+60
.cp 28
.tb set $
.* .tb 9 16 50
.tb &c0 &c1 &c2
.* .bx on 1 8 43
.* .bx on 1 10 50
.se t0=&c0-5
.se t1=&c1-3
.se t2=58
.bx on &t0 &t1 &t2
$Offset$Description
.bx
$00H$Largest available block, in bytes
.bx
$04H$Maximum unlocked page allocation
.bx
$08H$Largest block of memory (in pages) that could$
$   $be allocated and then locked
.bx
$0CH$Total linear address space size, in pages, including$
$   $already allocated pages
.bx
$10H$Total number of free pages and pages currently$
$   $unlocked and available for paging out
.bx
$14H$Number of physical pages not in use
.bx
$18H$Total number of physical pages managed by host
.bx
$1CH$Free linear address space, in pages
.bx
$20H$Size of paging/file partition, in pages
.bx
$24H -$Reserved
$2FH$
.bx off
.tb set
.tb
.np
Only the first field of the structure is guaranteed to contain a valid
value.
Any field that is not returned by &dos4g is set to -1 (0FFFFFFFFH).
.*
.note Function 0501H
.*
.ix 'DPMI' 'allocate memory block'
This function allocates and commits linear memory.
Pass the following information:
.begpoint $compact
.point AX = 0501H
.point BX:CX = size of memory to allocate, in bytes.
.endpoint
.np
If the call succeeds, the carry flag is clear, BX:CX contains the
linear address of the allocated memory, and SI:DI contains the memory
block handle used to free or resize the block.
If the call fails, the carry flag is set.
.np
No selectors are allocated for the memory block.
The caller must allocate and initialize selectors needed to access the
memory.
.np
If VMM is present, the memory is allocated as unlocked, page granular
blocks.
Because of the page granularity, memory should be allocated in
multiples of 4KB.
.*
.note Function 0502H
.*
.ix 'DPMI' 'free memory block'
This function frees a block of memory allocated through function
0501H.
Pass the following information:
.begpoint $compact
.point AX = 0502H
.point SI:DI = handle returned with function 0501H when memory was allocated
.endpoint
.np
If the call succeeds, the carry flag is clear; if it fails, the carry
flag is set.
You must also free any selectors allocated to point to the freed
memory block.
.*
.note Function 0503H
.*
.ix 'DPMI' 'resize memory block'
This function resizes a block of memory allocated through the 0501H
function.
If you resize a block of linear memory, it may have a new linear
address and a new handle.
Pass the following information:
.begpoint $compact
.point AX = 0503H
.point BX:CX = new size of memory block, in bytes
.point SI:DI = handle returned with function 0501H when memory was allocated
.endpoint
.np
If the call succeeds, the carry flag is clear, BX:CX contains the new
linear address of the memory block, and SI:DI contains the new handle
of the memory block.
If the call fails, the carry flag is set.
.np
If either the linear address or the handle has changed, update the
selectors that point to the memory block.
Use the new handle instead of the old one.
.np
You cannot resize a memory block to zero bytes.
.endnote
.*
.section Page Locking Services
.*
.np
.ix 'page locking services'
These services are only useful under DPMI implementations that support
virtual memory.
Although memory ranges are specified in bytes, the actual unit of
memory that will be locked will be one or more pages.
Page locks are maintained as a count.
When the count is decremented to zero, the page is unlocked and can be
swapped to disk.
This means that if a region of memory is locked three times then it
must be unlocked three times before the pages will be unlocked.
.begnote
.*
.note Function 0600H
.*
.ix 'DPMI' 'lock linear region'
This function locks a specified linear address range.
Pass the following information:
.begpoint $compact
.point AX = 0600H
.point BX:CX = starting linear address of memory to lock
.point SI:DI = size of region to lock (in bytes)
.endpoint
.np
If the call fails, the carry flag is set and none of the memory will
be locked.
.np
If the call succeeds, the carry flag is clear.
If the specified region overlaps part of a page at the beginning or
end of a region, the page(s) will be locked.
.*
.note Function 0601H
.*
.ix 'DPMI' 'unlock linear region'
This function unlocks a specified linear address range that was
previously locked using the "lock linear region" function (0600h).
Pass the following information:
.begpoint $compact
.point AX = 0601H
.point BX:CX = starting linear address of memory to unlock
.point SI:DI = size of region to unlock (in bytes)
.endpoint

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -