📄 cint16.asm
字号:
TITLE LC Interrupt trap routine
NAME LCINT
INCLUDE DOS.MAC ; BE SURE TO INCLUDE THE CORRECT
; DOS.MAC!!
;****************************************************************************
;
; This is the heart of a C driven interrupt handler. This file was used to
; write a critical error handler that remained resident. (It replaced the
; "Abort, Retry, Ignore" prompt with a window.) This file can be adapted to
; any interrupt and any C routine with a little work. THIS HAS BEEN USED ONLY
; IN THE S MODEL.
;
; REVISION HISTORY:
;
; 7/19/87 Thomas A. Lundin
; Graphics Unlimited Inc.
; 3000 Second St. No.
; Minneapolis, MN 55411
; (612) 588-7571
;
; Implemented DOS stack save/restore for a more stable exit from & reentry to
; the original DOS environment which called us.
;
; 8/4/87 TAL again
;
; Now try the keyboard interrupt vector. Also added some routines (but did
; not activate them here) which save/restore the caller's PSP and DTA. Why?
; I had some silly notion that it might help my TSR program from bombing when
; issuing DOS calls when other DOS calls are in process. Hah! I should have
; known better. But I left them in, in case you are interested. The kludge I
; ended up with checks the DOS "Critical Section Flag" and disables any calls
; to DOS when other calls are in process. That section of code has also been
; commented out. Also made some changes to my 7/19/87 modifications.
;****************************************************************************
DOS_INT EQU 16H ; int to be replaced (keyboard)
WRITE_INT EQU 25H ; DOS write int vector
READ_INT EQU 35H ; DOS read int vector
;******************************************************************************
HOTKEY EQU 1300H ; ALT-R here - can be anything you want
;******************************************************************************
STAK_LEN EQU 800H ; size of stack area to save ;;;;;;;;;;
XREG STRUC
REG_AX DW ? ; general purpose registers
REG_BX DW ?
REG_CX DW ?
REG_DX DW ?
REG_SI DW ?
REG_DI DW ?
XREG ENDS
SREGS STRUC
REG_ES DW ? ; segment registers
REG_CS DW ?
REG_SS DW ?
REG_DS DW ?
SREGS ENDS
DSEG
INT_REGS XREG <> ; saved regs. at int time
INT_SEGREGS SREGS <> ; saved seg. regs.
EXTRN _TOP:WORD ; declared by C.ASM -- points
; to top of stack
EXTRN _STACK:WORD ; size of stack
PUBLIC _INDOS ; if _INDOS is non-zero...
_INDOS DW 0 ; ...then don't interrupt DOS
ENDDS
EXTRN INTTIME:NEAR ; your int routine goes here!
PSEG
;;
; interrupt time data storage
;;
C_ENVIRONMENT_DS DW ? ; filled by int init, used...
C_ENVIRONMENT_ES DW ? ; ...to recreate C environment
C_ENVIRONMENT_SS DW ?
C_ENVIRONMENT_SP DW ?
INT_TIME_ES DW ?
INT_TIME_DS DW ? ; temp save of DS at int time
INT_TIME_SI DW ? ; temp save of SI at int time
INT_TIME_BP DW ? ; added to account for no BP or SP...
INT_TIME_SP DW ? ; ...in above structures
RETURN_VALUE DW ? ; return value from C service routine
DOS_SERVICE DD ? ; address of DOS Service routine
INT_TWOONE DD ? ; old INT 21 vector
INT_IN_PROGRESS DB 0 ; interrupt in progress flag
CALSTK DB STAK_LEN DUP(?) ;caller's stack save area ;;;;;;;;;;;;;;;;;;;;;
STKSEG DW ? ;which stack segment ;;;;;;;;;;;;;;;;;;;;;;;;;;
FLAGS DW ? ;caller's flags ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;DOSDTA DD ? ;caller's DTA
;C_DTA DD ? ;C's DTA
;DOSPSP DW ? ;caller's PSP
;C_PSP DW ? ;C's PSP
;;**************************************************************************
; name LC_SERVICE_INT
;
; description Entered at (software) interrupt time, this routine
; restores the C enviroment and processes the interrupt
; trapping all references to the quad file
;;
IF LPROG
LC_SERVICE_INT PROC FAR
ELSE
LC_SERVICE_INT PROC NEAR
ENDIF
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; This section of code can be commented out if you don't wish to trap the
; keyboard interrupt. Remember, then, to change the DOS_INT EQUate to whatever
; interrupt it is you DO want to trap.
CMP CS:INT_IN_PROGRESS,1 ; already in this interrupt?
JNE FIRST_TIME ; no, check the key
EXIT16:
JMP DWORD PTR CS:DOS_SERVICE ; else forget it
FIRST_TIME:
CMP AH,0 ; is this character request
JNE EXIT16 ; no, exit immediately
PUSHF
CALL DWORD PTR CS:DOS_SERVICE ; get the next character from buffer
CMP AX,HOTKEY ; is it the hot key?
JE HOT_HIT ; yes, dive into the interrupt
IRET ; no, send the char back to caller
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
HOT_HIT:
MOV CS:INT_IN_PROGRESS,1 ; set int in progress flag
MOV CS:INT_TIME_ES,ES ; save ES so it can be overwritten
MOV CS:INT_TIME_DS,DS ; save DS so it can be overwritten
MOV CS:INT_TIME_SI,SI ; save SI so it can be overwritten
MOV CS:INT_TIME_BP,BP ; save BP as structs do not have it
MOV CS:INT_TIME_SP,SP ; save SP as structs do not have it
MOV DS,CS:C_ENVIRONMENT_DS ; set up C enviroment
MOV SI,OFFSET INT_REGS ; point to input regs struct
MOV DS:[SI].REG_AX,AX ; save general purpose regs
MOV DS:[SI].REG_BX,BX
MOV DS:[SI].REG_CX,CX
MOV DS:[SI].REG_DX,DX
MOV DS:[SI].REG_DI,DI
MOV AX,CS:INT_TIME_SI ; SI has been overwritten
MOV DS:[SI].REG_SI,AX
MOV SI,OFFSET INT_SEGREGS ; point to input segment regs struct
MOV AX,CS:INT_TIME_ES ; ES has been overwritten
MOV DS:[SI].REG_ES,AX
MOV DS:[SI].REG_SS,SS
MOV AX,CS:INT_TIME_DS ; DS has been overwritten
MOV DS:[SI].REG_DS,AX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUSHF
POP AX
MOV CS:FLAGS,AX ;save caller's flags
MOV SI,SS
MOV WORD PTR CS:STKSEG,SI ;save caller's stack segment
PUSH DS
CLI
MOV AX,CS ;save area address
MOV ES,AX
MOV AX,WORD PTR CS:STKSEG ;caller's stack address
MOV DS,AX
MOV SI,0 ;stack offset
MOV DI,OFFSET CS:CALSTK
MOV CX,STAK_LEN ;length to save
CLD
REP MOVSB ;save caller's stack
STI
;........................................
; MOV AX,2F00H ;get caller's DTA
; INT 21H
; MOV WORD PTR CS:DOSDTA+2,ES ;save it
; MOV WORD PTR CS:DOSDTA,BX
;
; MOV AX,5100H ;get caller's PSP
; INT 21H
; MOV CS:DOSPSP,BX ;save it
;
; MOV AX,1A00H ;set C's DTA
; MOV DX,WORD PTR CS:C_DTA
; MOV DS,WORD PTR CS:C_DTA+2
; INT 21H
;
; MOV BX,CS:C_PSP
; MOV AX,5000H ;set C's PSP
; INT 21H
;........................................
POP DS
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV ES,CS:C_ENVIRONMENT_ES ; complete C environment
MOV SS,CS:C_ENVIRONMENT_SS
MOV SP,CS:C_ENVIRONMENT_SP
;----------------------------------------
; PUSH ES ;
; PUSH BX ;
; PUSH AX ;
; MOV AX,3400H ; the "Critical Section Flag"
; INT 21H ; determines DOS interruptability
; MOV AL,BYTE PTR ES:[BX] ;
; MOV BYTE PTR CS:_INDOS,AL ; save it for INTTIME
; POP AX ;
; POP BX ;
; POP ES ;
;----------------------------------------
CALL INTTIME ; call the C routine
MOV CS:RETURN_VALUE,AX ; save return value
XOR AX,AX
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
PUSH DS
;........................................
; MOV AX,1A00H ;reinstate DOS DTA
; MOV DX,WORD PTR CS:DOSDTA
; MOV DS,WORD PTR CS:DOSDTA+2
; INT 21H
;
; MOV BX,CS:DOSPSP
; MOV AX,5000H ;and DOS PSP
; INT 21H
;........................................
CLI
MOV AX,WORD PTR CS:STKSEG ;restore caller's stack area
MOV ES,AX
MOV DI,0 ;restore data areas
MOV AX,CS
MOV DS,AX
MOV SI,OFFSET CS:CALSTK
MOV CX,STAK_LEN ;length to restore
CLD
REP MOVSB ;copy stack data
STI
POP DS
MOV AX,CS:FLAGS
PUSH AX
POPF ;restore caller's flags
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
MOV SI,OFFSET INT_REGS ; point to input regs struct
MOV AX,DS:[SI].REG_SI ; SI needs to be saved while used
MOV CS:INT_TIME_SI,AX
MOV AX,DS:[SI].REG_AX ; restore general purpose regs
MOV BX,DS:[SI].REG_BX
MOV CX,DS:[SI].REG_CX
MOV DX,DS:[SI].REG_DX
MOV DI,DS:[SI].REG_DI
MOV SI,OFFSET INT_SEGREGS ; point to input segment regs struct
MOV ES,DS:[SI].REG_DS ; DS needs to be saved while used
MOV CS:INT_TIME_DS,ES
MOV ES,DS:[SI].REG_ES
MOV SS,DS:[SI].REG_SS
MOV SI,CS:INT_TIME_SI ; restore pointing registers
MOV DS,CS:INT_TIME_DS
MOV BP,CS:INT_TIME_BP ; special BP restore
MOV SP,CS:INT_TIME_SP ; special SP restore
MOV CS:INT_IN_PROGRESS,0 ; clear int in progress flag
MOV AX,CS:RETURN_VALUE ; move the return value
OR AX,AX ;;;;;;;;;;;;;;;;;;; return value ?
JNZ DONE ;;;;;;;;;;;;;;;;;;; yes, pass it through as keystroke
JMP CS:LC_SERVICE_INT ;;;;;;; no, fetch the next keystroke
DONE:
IRET ; return from interrupt
LC_SERVICE_INT ENDP
;****************************************************************************
; description set up the LC interrupt routines
;
; INT_INIT -- Hooks into the specified int.
; INT_TERM -- Unhooks (restores) the specified int.
;
; NOTE: INT_INIT must be called be int processing can begin...it saves the
; current C environment for use at interrupt time.
;;
PUBLIC INT_INIT
IF LPROG
INT_INIT PROC FAR
ELSE
INT_INIT PROC NEAR
ENDIF
PUSH DS ; save changed seg regs
PUSH ES
MOV CS:C_ENVIRONMENT_DS,DS ; save C environment for int time
MOV CS:C_ENVIRONMENT_ES,ES
MOV CS:C_ENVIRONMENT_SS,SS
MOV AX,_TOP ; determine int time SP
MOV BX,_STACK ; get size of STACK ;;;;;;;;;;;;;;;;;;;
ROR BX,1 ; div by 2 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;
SUB AX,BX ; split it in two ;;;;;;;;;;;;;;;;;;;;;
MOV CS:C_ENVIRONMENT_SP,AX
MOV AH,READ_INT ; read int vector function
MOV AL,DOS_INT ; specify DOS service vector
INT 21H
MOV WORD PTR CS:DOS_SERVICE+2,ES ; save current vector
MOV WORD PTR CS:DOS_SERVICE,BX
LEA DX,LC_SERVICE_INT ; Use DOS to set new int address
PUSH CS
POP DS
MOV AH,WRITE_INT
MOV AL,DOS_INT
INT 21H
;::::::::::::::::::::::::::::::::::::::::
; MOV AX,2F00H ;get C's DTA
; INT 21H
; MOV WORD PTR CS:C_DTA+2,ES ;save it
; MOV WORD PTR CS:C_DTA,BX
;
; MOV AX,5100H ;get C's PSP
; INT 21H
; MOV CS:C_PSP,BX ;save it
;::::::::::::::::::::::::::::::::::::::::
POP ES ; restore changed seg regs
POP DS
RET
INT_INIT ENDP
;********************* INT_TERM -- kill ints. *******************************
PUBLIC INT_TERM
IF LPROG
INT_TERM PROC FAR
ELSE
INT_TERM PROC NEAR
ENDIF
PUSH DS ; DS gets changed
MOV DS,WORD PTR CS:DOS_SERVICE+2 ; Restore previous DOS service vector
MOV DX,WORD PTR CS:DOS_SERVICE
MOV AH,WRITE_INT
MOV AL,DOS_INT
INT 21H
POP DS ; restore DS
RET
INT_TERM ENDP
ENDPS
END
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -