handlers.asm
来自「这是一些例程」· 汇编 代码 · 共 1,284 行 · 第 1/4 页
ASM
1,284 行
mov WORD PTR [si].INTR.OldHand[2], es ; application's handler
mov dx, WORD PTR [si].INTR.NewHand[0] ; DS:DX points to TSR's hand
mov ah, 25h ; Request DOS Function 25h
int 21h ; Set interrupt vector
add si, SIZEOF INTR ; DS:SI points to next in list
.UNTILCXZ
; Step 4. Disable MS-DOS break checking during disk I/O
mov ax, 3300h ; Request DOS Function 33h
int 21h ; Get CTRL+BREAK flag in DL
mov BreakCheckFlag, dl ; Preserve it
sub dl, dl ; DL = 0 to disable I/O break checking
mov ax, 3301h ; Request DOS Function 33h
int 21h ; Set CTRL+BREAK flag from DL
; Step 5. If TSR requires a disk transfer area, store address of current
; DTA and switch buffer address to this segment. See Help and section
; "Preserving Existing Data" in Chapter 11 of the Programmer's Guide for
; more information about the DTA.
IFDEF DTA_SIZ
mov ah, 2Fh ; Request DOS Function 2Fh
int 21h ; Get DTA Address into ES:BX
mov WORD PTR OldDtaAddr[0], bx ; Store address
mov WORD PTR OldDtaAddr[2], es
mov dx, OFFSET DtaBuff ; DS:DX points to new DTA
mov ah, 1Ah ; Request DOS Function 1Ah
int 21h ; Set DTA Address
ENDIF
; Call main body of TSR.
mov ax, @data
mov ds, ax ; Initialize DS and ES
mov es, ax ; to data segment
call cs:TsrAddr ; Call main part of TSR
push cs
pop ds ; Reset DS to this segment
; Undo step 5. Restore previous DTA (if required)
IFDEF DTA_SIZ
push ds ; Preserve DS
lds dx, OldDtaAddr ; DS:DX points to application's DTA
mov ah, 1Ah ; Request DOS Function 1Ah
int 21h ; Set DTA Address
pop ds
ENDIF
; Undo step 4. Restore previous MS-DOS break checking
mov dl, BreakCheckFlag ; DL = previous break state
mov ax, 3301h ; Request DOS Function 33h
int 21h ; Set CTRL+BREAK flag from DL
; Undo step 3. Restore previous vectors for error-trapping handlers
mov cx, CTRAP
mov di, OFFSET TrapArray
push ds ; Preserve DS
push ds ; ES = resident code segment
pop es
.REPEAT
mov al, es:[di] ; AL = interrupt number
lds dx, es:[di].INTR.OldHand; DS:DX points to application's handler
mov ah, 25h ; Request DOS Function 25h
int 21h ; Set interrupt vector from DS:DX
add di, SIZEOF INTR ; ES:DI points to next in list
.UNTILCXZ
pop ds
; Undo step 2. Restore registers from stack
pop es
pop bp
pop di
pop si
pop dx
pop cx
pop bx
pop ax
; Undo step 1. Restore address of original stack to SS:SP
cli
mov sp, WORD PTR OldStackAddr[0]
mov ss, WORD PTR OldStackAddr[2]
sti
; Clear request flag and return to caller (Clock or Idle procedure)
mov TsrRequestFlag, FALSE
ret
Activate ENDP
;* INSTALLATION SECTION - The following code is executed only during
;* the TSR's installation phase. When the program terminates through
;* Function 31h, the above code and data remain resident; memory
;* occupied by the following code segment is returned to the operating
;* system.
DGROUP GROUP INSTALLCODE
INSTALLCODE SEGMENT PARA PUBLIC 'CODE2'
ASSUME ds:@code
;* Install - Prepares for installation of a TSR by chaining interrupt
;* handlers and initializing pointers to DOS flags. Install does not
;* call the Terminate-and-Stay-Resident function.
;*
;* This library of routines accommodates both keyboard-activated and
;* time-activated TSRs. The latter are TSRs that activate at a preset
;* time. If the first parameter (Param1) is a valid scan code, Install
;* assumes the TSR is activated from the keyboard and sets up a keyboard
;* handler to search for the hot key. If Param1 is null, Install assumes
;* the next two parameters (Param2 and Param3) are respectively the hour
;* and minute at which the TSR is to activate. In this case, Install
;* calls GetTimeToElapse to initialize the variable CountDown and sets
;* up KeybrdMonitor as the keyboard handler. CountDown and the secondary
;* counter Tick91 serve here the same functions as they do for the
;* ALARM.ASM program presented in Chapter 11 of the Programmer's Guide.
;* Install is callable from a high-level language.
;*
;* Uses: InDosAddr, CritErrAddr, CHAND,
;* HandArray, CTRAP, TrapArray
;*
;* Keyboard-activated Time-activated
;* ------------------ --------------
;* Params: Param1 - Scan code for hot key 0
;* Param2 - Bit value for shift hot key Hour to activate
;* Param3 - Bit mask for shift hot key Minute to activate
;* Param4 - Far address of main TSR procedure (same)
;*
;* Return: AX = 0 if successful, or one of the following codes:
;* IS_INSTALLED FLAGS_NOT_FOUND NO_IDNUM
;* ALREADY_INSTALLED WRONG_DOS
Install PROC FAR USES ds si di,
Param1:WORD, Param2:WORD, Param3:WORD, Param4:FAR PTR FAR
mov ax, @code
mov ds, ax ; Point DS to code segment
; Get and store parameters passed from main program module
mov al, BYTE PTR Param1
mov HotScan, al ; Store hot-key scan code
mov al, BYTE PTR Param2 ; or flag for time activate
mov HotShift, al ; Store hot-key shift value
mov al, BYTE PTR Param3 ; or hour value
mov HotMask, al ; Store hot-key shift mask
; or minute value
mov ax, WORD PTR Param4[0]
mov bx, WORD PTR Param4[2]
mov WORD PTR TsrAddr[0], ax ; Store segment:offset of
mov WORD PTR TsrAddr[2], bx ; TSR's main code
; Get addresses of DOS flags, then check for prior installation
call GetDosFlags ; Find DOS service flags
or ax, ax
jnz exit ; If flags not found, quit
sub al, al ; Request multiplex function 0
call CallMultiplex ; Invoke Interrupt 2Fh
cmp ax, NOT_INSTALLED ; Check for presence of resident TSR
.IF !zero? ; If TSR is installed,
cmp ax, IS_INSTALLED ; return with appropriate
jne exit ; error code
mov ax, ALREADY_INSTALLED
jmp exit
.ENDIF
; Check if TSR is to activate at the hour:minute specified by Param2:Param3.
; If so, determine the number of 5-second intervals that must elapse before
; activation, then set up the code at the far LABEL KeybrdMonitor to serve
; as the keyboard handler.
.IF HotScan == 0 ; If valid scan code given,
mov ah, HotShift ; AH = hour to activate
mov al, HotMask ; AL = minute to activate
call GetTimeToElapse ; Get number of 5-second intervals
mov CountDown, ax ; to elapse before activation
.ELSE ; Force use of KeybrdMonitor as
; keyboard handler
cmp Version, 031Eh ; DOS Version 3.3 or higher?
jb setup ; No? Skip next step
; Test for IBM PS/2 series. If not PS/2, use Keybrd and SkipMiscServ as
; handlers for Interrupts 09 and 15h respectively. If PS/2 system, set up
; KeybrdMonitor as the Interrupt 09 handler. Audit keystrokes with MiscServ
; handler, which searches for the hot key by handling calls to Interrupt 15h
; (Miscellaneous System Services). For more information about keyboard
; handlers, refer to the section "Auditing Hardware Events for TSR Requests"
; in Chapter 11 of the Programmer's Guide
mov ax, 0C00h ; Function 0Ch (Get System
int 15h ; Configuration Parameters)
sti ; Compaq ROM may leave interrupts
; disabled
jc setup ; If carry set,
or ah, ah ; or if AH not 0,
jnz setup ; services are not supported
test BYTE PTR es:[bx+5], 00010000y ; Test bit 4 to see if
jz setup ; intercept is implemented
mov ax, OFFSET MiscServ ; If so, set up MiscServ as
mov WORD PTR intMisc.NewHand, ax ; Interrupt 15h handler
.ENDIF
mov ax, OFFSET KeybrdMonitor ; Set up KeybrdMonitor as
mov WORD PTR intKeybrd.NewHand, ax ; Interrupt 09 handler
; Interrupt structure is now initialized for either PC/AT or PS/2 system.
; Get existing handler addresses from interrupt vector table, store in
; OldHand member, and replace with addresses of new handlers.
setup:
mov cx, CHAND ; CX = count of handlers
mov si, OFFSET HandArray ; SI = offset of handler structures
.REPEAT
mov ah, 35h ; Request DOS Function 35h
mov al, [si] ; AL = interrupt number
int 21h ; Get interrupt vector in ES:BX
mov WORD PTR [si].INTR.OldHand[0], bx ; Save far address
mov WORD PTR [si].INTR.OldHand[2], es ; of current handler
mov dx, WORD PTR [si].INTR.NewHand[0] ; DS:DX points to TSR handler
mov ah, 25h ; Request DOS Function 25h
int 21h ; Set interrupt vector from DS:DX
add si, SIZEOF INTR ; DS:SI points to next in list
.UNTILCXZ
sub ax, ax ; Clear return code
exit:
ret ; Return to caller
Install ENDP
;* Deinstall - Prepares for deinstallation of a TSR. Deinstall is the
;* complement of the Install procedure. It restores to the vector table
;* the original addresses replaced during installation, thus unhooking
;* the TSR's handlers. Checks to see if another TSR has installed handlers
;* for the interrupts in array HandArray. If so, the procedure fails with
;* an appropriate error code. Callable from a high-level language.
;*
;* Params: None
;*
;* Return: AX = Segment address of resident portion's PSP or
;* one of the following error codes:
;* CANT_DEINSTALL WRONG_DOS
Deinstall PROC FAR USES ds si di
mov ax, @code
mov ds, ax ; Point DS to code segment
sub al, al ; Request multiplex function 0
call CallMultiplex ; Get resident code segment in ES
cmp ax, IS_INSTALLED ; If not resident,
jne exit ; exit with error
push es ; Else point DS to
pop ds ; resident code segment
mov cx, CHAND ; Count of handlers
mov si, OFFSET HandArray ; SI points to handler structures
; Read current vectors for TSR's interrupt handlers and compare with far
; addresses. If mismatch, another TSR has installed new handlers and ours
; cannot be safely deinstalled.
.REPEAT
mov al, [si] ; AL = interrupt number
mov ah, 35h ; Request DOS Function 35h
int 21h ; Get interrupt vector in ES:BX
cmp bx, WORD PTR [si].INTR.NewHand[0] ; If offset different,
jne e_exit ; error
mov ax, es
cmp ax, WORD PTR [si].INTR.NewHand[2] ; If segment different,
jne e_exit ; error
add si, SIZEOF INTR ; DS:SI points to next in list
.UNTILCXZ
; If no interrupts replaced, call TSR's multiplex handler to locate
; address of resident portion's PSP. Although the PSP is not required
; until memory is returned to DOS, the call must be done now before
; unhooking the multiplex handler.
mov al, 1 ; Request multiplex function 1
call CallMultiplex ; Get resident code's PSP in ES
push es ; Save it
; Unhook all handlers by restoring the original vectors to vector table.
mov cx, CHAND ; Count of installed handlers
mov si, OFFSET HandArray ; SI points to handler structures
.REPEAT
mov al, [si] ; AL = interrupt number
push ds ; Preserve DS segment
lds dx, [si].INTR.OldHand ; Put vector in DS:DX
mov ah, 25h ; Request DOS Function 25h
int 21h ; Set interrupt vector from DS:DX
pop ds
add si, SIZEOF INTR ; DS:SI points to next in list
.UNTILCXZ
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?