Mail Archives: djgpp/1997/12/18/08:36:32
I have written and tested a program in Assembler (hereinunder) which sets up
a TSR which does this:-
(1) Hooks the system interrupt 9 so it also records the keyboard events in a
255-byte buffer called KEYEVENT. If the key-event buffer was full, the latest
entry in it is replaced by 0xff. It does not stop the ordinary keyboard buffer
from getting full : the user should keep the keyboard buffer emptied himself.
(2) Hooks the user interrupt 0xFD so that it does this:-
AX = 0x9900 : read from the key-event buffer one keyboard event and return
it in AL. Carry is clear. Prefix-code combinations are sent on as two events
as they are and are not decoded. Note two special return codes:-
AL==0xff : here the key-event buffer got full, see above.
AL==0x00 and carry set : the key-event buffer was empty.
AX = 0x9901 : empty the key-event buffer.
AX = any other 0x99** value: do nothing.
------------------------------------------------------------------
Query: When a TSR is set up, it seems that the installer program's PSP remains
as 256 dead bytes taking up space below the TSR. Would any disaster happen if
the interrupt handler in the TSR used this dead PSP as working space? How
would the DOS instruction MEM react if such an old embedded PSP was corrupted?
==================================================================
CODE SEGMENT
ASSUME CS:CODE
JMP INSTALL
KEYEVENT DB 256 DUP 0 ; circular buffer, can be empty, can't be completely full
INPTR DB 0
OUTPTR DB 0
SIGNATUR DW 0BEEF
HOOK09 LABEL BYTE ; new int09 handler code
PUSHF ; needed to match the implicit extra POPF in IRET
DB 09A ; code for FAR CALL :: call the old int09 handler
OFF09 DW 0 ; for offset & seg of ind int09 handler
SEG09 DW 0
PUSH AX
PUSH BX
PUSH DS
DB 0B8 ; MOV AX,number
SETDS09 DW 0
MOV DS,AX
CLI ; disable interrupts
IN AL,060 ; get key scan code
MOV BL,INPTR ; buffer input pointer
MOV BH,0
MOV KEYEVENT[BX],AL ; put key event in buffer
MOV AH,BL ; save old BL
INC BX ; +=1
MOV BH,0 ; BX&=255
CMP BL,OUTPTR ; if inptr has not hit outptr, OK
JNE INOK
MOV BL,AH ; that would make buffer full, so restore old BL
MOV KEYEVENT[BX],0AB ; & replace previous key value by 0xff
JMP INEND
INOK:
MOV INPTR,BL ; update pointer
INEND:
POP DS
POP BX
POP AX
IRET
HOOKFD PROC FAR ; new intFD handler code
CMP AH,099
JE MYFD ; if AH==0x99, call my intFD handler
DB 0EA ; code for JMP FAR
OFFFD DW 0 ; for offset & seg of ind intFD handler
SEGFD DW 0
MYFD: PUSH DS ; if AH==0x99, call my intFD handler
DB 0BB ; MOV AX,number ; set DS as the installer was compiled for
SETDSFD DW 0
MOV DS,BX
CMP AL,0 ; if AL==0, read a key event
JE GETEVENT
CMP AL,1 ; if AL==1, empty the key event buffer
JE EMPTYBUF
WHOA: POP DS
IRET
EMPTYBUF: MOV BL,0
MOV INPTR,BL
MOV OUTPTR,BL
JMP WHOA
GETEVENT:
MOV BL,OUTPTR ; buffer output pointer
CMP BL,INPTR
JE EMPTY
CLC ; clear carry
MOV BH,0
MOV AL,KEYEVENT[BX]
INC BX ; +=1
MOV OUTPTR,BL
JMP WHOA
EMPTY: STC ; carry set = nothing in buffer
MOV AL,0
JMP WHOA
ALREADY DB,10,13,"program AAKEYS already in memory",13,10,'$'
NOWINST DB,10,13,"program AAKEYS installed",13,10,'$'
INSTALL: MOV AX,03509 ; ES:BX := current vector INT 09h
INT 021
MOV AX,[ES:BX-2]
CMP AX,SIGNATUR
JE ALREDDY
MOV CS:OFF09,BX
MOV CS:SEG09,ES
MOV CS:SETDS09,DS ; set instr to set DS
MOV AX,CS ; change int09 vector
MOV DS,AX
MOV DX,OFFSET HOOK09
MOV AX,02509
INT 021
MOV AX,035FD ; ES:BX := current vector INT FDh
INT 021
MOV CS:OFFFD,BX
MOV CS:SEGFD,ES
MOV CS:SETDSFD,DS ; set instr to set DS
MOV AX,CS ; change intFD vector
MOV DS,AX
MOV DX,OFFSET HOOKFD
MOV AX,025FD
INT 021
LEA DX,NOWINST ; print remark
MOV AH,9
INT 021
LEA DX,ALREADY ; install TSR
ADD DX,15
MOV CX,4
SHR DX,CL
ADD DX,16
MOV AX,03100
PUSH CS
POP DS
INT 021
ALREDDY:
; PUSH CS
; POP DS
LEA DX,ALREADY
MOV AH,9
INT 021
MOV AX,04C00
INT 021
END INSTALL
- Raw text -