handlers.asm

来自「这是一些例程」· 汇编 代码 · 共 1,284 行 · 第 1/4 页

ASM
1,284
字号
        .MODEL  small, pascal
        INCLUDE tsr.inc

        .CODE

; Stack buffer used by TSR. Size is determined by constant STACK_SIZ,
; declared in TSR.INC file. NewStack points to top of stack.

         EVEN
         BYTE   STACK_SIZ DUP(?)        ; Stack buffer
NewStack LABEL BYTE                     ; Pointer to top of stack

; Structures for interrupt handlers or "interrupt service routines."
; The following handlers are replaced during installation. Such routines
; usually set a flag to indicate they are active, call the original
; interrupt handler, optionally do some processing (such as detecting a
; hot key), and when finished clear the active flag.

HandArray       LABEL   BYTE                    ; Array of handler structures
;                Num   Flag     OldHand  NewHand
intClock  INTR  < 8h,  FALSE,   NULL,    Clock>
intKeybrd INTR  < 9h,  FALSE,   NULL,    Keybrd>
intVideo  INTR  <10h,  FALSE,   NULL,    Video>
intDiskIO INTR  <13h,  FALSE,   NULL,    DiskIO>
intMisc   INTR  <15h,  FALSE,   NULL,    SkipMiscServ>
intIdle   INTR  <28h,  FALSE,   NULL,    Idle>
intMultex INTR  <2Fh,  FALSE,   NULL,    Multiplex>

CHAND   EQU     ($ - HandArray) / (SIZEOF INTR) ; Number of handlers in array

; Interrupt trap routines. These interrupt routines are set up
; temporarily to trap keyboard break errors and critical errors
; while the TSR is active. When the TSR finishes its tasks, it
; restores the old interrupts before returning.

TrapArray       LABEL   BYTE                    ; Array of trap structures
;                Num   Flag     OldHand  NewHand
intCtrlBk INTR  <1Bh,  FALSE,   NULL,    CtrlBreak>
intCtrlC  INTR  <23h,  FALSE,   NULL,    CtrlC>
intCritEr INTR  <24h,  FALSE,   NULL,    CritError>

CTRAP   EQU     ($ - TrapArray) / (SIZEOF INTR) ; Number of traps in array

; Address of application's stack. Before calling the main body of the TSR,
; the Activate procedure stores the application's stack address, then resets
; SS:SP to point to LABEL NewStack (see above). This gives the TSR its own
; stack space without making demands on the current stack. Activate restores
; the application's stack before returning.

OldStackAddr    FPVOID  ?               ; SS:SP pointer to application stack

; The TSR must set up its own disk transfer area if it calls DOS functions
; that use the DTA (see section "Preserving Existing Data" in Chapter 11 of
; the Programmer's Guide). DTA_SIZ is defined in the TSR.INC include file.

                IFDEF   DTA_SIZ
OldDtaAddr      FPVOID  ?               ; Address of application's DTA
DtaBuff         BYTE    DTA_SIZ DUP(?)  ; DTA buffer
                ENDIF

; Multiplex data. STR_LEN is defined in the TSR.INC include file

IDnumber        BYTE    0               ; TSR's identity number
IDstring        BYTE    STR_LEN DUP (0) ; Copy of identifier string
IDstrlen        WORD    ?               ; Length of identifier string
ShareAddr       FPVOID  ?               ; Address of shared memory

; Miscellaneous data

TsrRequestFlag  BYTE    FALSE           ; Flag set when hot key is pressed
TsrActiveFlag   BYTE    FALSE           ; Flag set when TSR executes
BreakCheckFlag  BYTE    ?               ; Break-checking status of application
TsrPspSeg       WORD    ?               ; Segment address of PSP
TsrAddr         FPVOID  ?               ; Pointer to main part of TSR
CritErrAddr     FPVOID  ?               ; Pointer to MS-DOS critical error flag
InDosAddr       FPVOID  ?               ; Pointer to MS-DOS InDos flag

; Scan and shift codes for hot key. Install procedure initializes
; HotScan, HotShift, and HotMask during installation.

HotScan         BYTE    ?               ; Scan code hot key
HotShift        BYTE    ?               ; Shift value of hot key
HotMask         BYTE    ?               ; Mask unwanted shift values

Version         LABEL   WORD            ; DOS version number
minor           BYTE    ?
major           BYTE    ?

; Timer data, used when the TSR is activated at a preset time instead
; of activated from the keyboard. The following variables serve the
; same purposes as the counter variables used in the ALARM.ASM program
; presented in Chapter 11 of the Programmer's Guide. Refer to the
; header comments in the Install procedure for an explanation of how
; to set up a time-activated TSR.

Tick91          BYTE    91              ; Measures 91 timer ticks (5 seconds)
CountDown       WORD    0               ; Counts 5-second intervals



;* Clock - Interrupt handler for Interrupt 08 (timer). Executes at each
;* timer interrupt; these occur an average of 18.2 times per second. Clock
;* first allows the original timer service routine to execute. It then
;* checks the flag TsrRequestFlag maintained either by the keyboard handler
;* (if keyboard activated) or by this procedure (if time activated). If
;* TsrRequestFlag = TRUE and system is okay, Clock invokes the TSR by
;* calling the Activate procedure. Uses an active flag to prevent the
;* Clock procedure from being reentered while executing.
;*
;* Uses:   intClock, TsrActiveFlag, CountDown
;*
;* Params: None
;*
;* Return: None

Clock   PROC    FAR

        pushf                           ; Simulate interrupt by pushing flags,
        call    cs:intClock.OldHand     ;   far calling orig Int 08 routine

        .IF     cs:intClock.Flag == FALSE ; If not already in this handler:
        mov     cs:intClock.Flag, TRUE  ; Set active flag

        sti                             ; Interrupts are okay
        push    ds                      ; Save application's DS
        push    cs
        pop     ds                      ; Set DS to resident code segment
        ASSUME  ds:@code

        call    CheckRequest            ; Check conditions
        .IF     !carry?                 ; If TSR requested and safe,
        mov     TsrActiveFlag, TRUE     ;   activate TSR
        call    Activate
        mov     TsrActiveFlag, FALSE
        .ENDIF                          ; End carry flag check

        cmp     CountDown, 0            ; If CountDown = 0, TSR is not time
        je      ticked                  ;   activated or has already executed
        dec     Tick91                  ; Else count down 91 timer ticks
        jnz     ticked                  ; If 91 ticks have not elapsed, exit
        mov     Tick91, 91              ; Else reset secondary counter and
        dec     CountDown               ;   subract one 5-second interval
        ja      ticked                  ; If counter not yet drained, exit
        mov     TsrRequestFlag, TRUE    ; Else raise request flag
ticked:
        mov     intClock.Flag, FALSE    ; Clear active flag
        pop     ds                      ; Recover application's DS
        ASSUME  ds:NOTHING

        .ENDIF                          ; End in-handler check
        iret

Clock   ENDP


;* Keybrd - Interrupt handler for Interrupt 09 (keyboard).
;*
;* IBM PC/AT and compatibles:
;*      Gets the scan code of the current keystroke from port 60h. Then
;*      compares the scan code and shift state to the hot key. If they
;*      match, sets TsrRequestFlag to signal the handlers Clock and Idle
;*      that the TSR is requested.
;* 
;* IBM PS/2 series:
;*      Only the instructions at KeybrdMonitor (see below) are installed
;*      as Interrupt 09 handler, since above method should not be used to
;*      determine current keystroke in IBM PS/2 series. In this case, the
;*      Interrupt 15h handler MiscServ takes care of checking the scan codes
;*      and setting the request flag when the hot key is pressed.
;*
;* Time-activated TSRs:
;*      If the TSR is activated by time instead of by a hotkey, KeybrdMonitor
;*      serves as the Interrupt 09 handler for both PC/AT and PS/2 systems.
;*
;* Uses:   intKeybrd, TsrRequestFlag
;* 
;* Params: None
;*
;* Return: None

Keybrd  PROC    FAR

        sti                             ; Interrupts are okay
        push    ax                      ; Save AX register
        in      al, 60h                 ; AL = scan code of current key
        call    CheckHotKey             ; Check for hot key
        .IF     !carry?                 ; If not hot key:

; Hot key pressed. Reset the keyboard to throw away keystroke.

        cli                             ; Disable interrupts while resetting
        in      al, 61h                 ; Get current port 61h state
        or      al, 10000000y           ; Turn on bit 7 to signal clear keybrd
        out     61h, al                 ; Send to port
        and     al, 01111111y           ; Turn off bit 7 to signal break
        out     61h, al                 ; Send to port
        mov     al, 20h                 ; Reset interrupt controller
        out     20h, al
        sti                             ; Reenable interrupts

        pop     ax                      ; Recover AX
        mov     cs:TsrRequestFlag, TRUE ; Raise request flag
        iret                            ; Exit interrupt handler
        .ENDIF                          ; End hot-key check

; No hot key was pressed, so let normal Int 09 service routine take over

        pop     ax                      ; Recover AX and fall through
        cli                             ; Interrupts cleared for service

KeybrdMonitor LABEL FAR                 ; Installed as Int 09 handler for
                                        ;   PS/2 or for time-activated TSR
        mov     cs:intKeybrd.Flag, TRUE ; Signal that interrupt is busy
        pushf                           ; Simulate interrupt by pushing flags,
        call    cs:intKeybrd.OldHand    ;   far calling old Int 09 routine
        mov     cs:intKeybrd.Flag, FALSE
        iret

Keybrd  ENDP


;* Video - Interrupt handler for Interrupt 10h (video). Allows the original
;* video service routine to execute. Maintains an active flag to prevent
;* the TSR from being called while Interrupt 10h is executing.
;*
;* Uses:   intVideo
;*
;* Params: Registers passed to Interrupt 10h
;*
;* Return: Registers returned by Interrupt 10h

Video   PROC    FAR

        mov     cs:intVideo.Flag, TRUE  ; Set active flag
        pushf                           ; Simulate interrupt by pushing flags,
        call    cs:intVideo.OldHand     ;   far calling old Int 10h routine
        mov     cs:intVideo.Flag, FALSE ; Clear active flag
        iret

Video   ENDP


;* DiskIO - Interrupt handler for Interrupt 13h (disk I/O). Allows the
;* original disk I/O service routine to execute. Maintains an active flag
;* to prevent the TSR from being called while Interrupt 13h is executing.
;*
;* Uses:   intDiskIO
;*
;* Params: Registers passed to Interrupt 13h
;*
;* Return: Registers and the carry flag returned by Interrupt 13h

DiskIO  PROC    FAR

        mov     cs:intDiskIO.Flag, TRUE ; Set active flag
        pushf                           ; Simulate interrupt by pushing flags,
        call    cs:intDiskIO.OldHand    ;   far calling old Int 13h routine
        mov     cs:intDiskIO.Flag, FALSE; Clear active flag without
                                        ;   disturbing flags register
        sti                             ; Enable interrupts
        ret     2                       ; Simulate IRET without popping flags
                                        ;   (since services use carry flag)
DiskIO  ENDP


;* MiscServ - Interrupt handler for Interrupt 15h (Miscellaneous System
;* Services).
;*
;* IBM PC/AT and compatibles:
;*     Stub at SkipMiscServ is used as handler, bypassing all calls to
;*     Interrupt 15h. Keypresses are checked by Keybrd (Int 09 handler).
;* 
;* IBM PS/2 series:
;*     This procedure handles calls to Interrupt 15h, searching for
;*     Function 4Fh (Keyboard Intercept Service). When AH = 4Fh, gets
;*     scan code of current keystroke in AL register. Then compares the
;*     scan code and shift state to the hot key. If they match, sets
;*     TsrRequestFlag to signal the handlers Clock and Idle that the
;*     TSR is requested.
;*
;* Uses:   intMisc, TsrRequestFlag
;*
;* Params: Registers passed to Interrupt 15h
;*
;* Return: Registers returned by Interrupt 15h

MiscServ PROC   FAR

        sti                             ; Interrupts okay
        .IF     ah == 4Fh               ; If Keyboard Intercept Service,
        push    ax                      ;   preserve AX,
        call    CheckHotKey             ;   check for hot key
        pop     ax
        .IF     !carry?                 ; If hot key,
        mov     cs:TsrRequestFlag, TRUE ;   raise request flag,
        clc                             ;   signal BIOS not to process the key,
        ret     2                       ;   simulate IRET without popping flags
        .ENDIF                          ; End carry flag check
        .ENDIF                          ; End Keyboard Intercept check

        cli                             ; Disable interrupts and fall through

SkipMiscServ LABEL FAR                  ; Interrupt 15h handler if PC/AT

        jmp     cs:intMisc.OldHand

MiscServ ENDP


;* CtrlBreak - Interrupt trap for Interrupt 1Bh (CTRL+BREAK Handler).
;* Disables CTRL+BREAK processing.
;*
;* Params: None
;*
;* Return: None

CtrlBreak PROC  FAR

        iret

CtrlBreak ENDP

⌨️ 快捷键说明

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