home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS - Coast to Coast
/
simteldosarchivecoasttocoast.iso
/
pcmag
/
vol7n08.zip
/
STAYDOWN.ASM
< prev
next >
Wrap
Assembly Source File
|
1988-04-26
|
18KB
|
432 lines
PAGE 60,132
;=============================================================================
; STAYDOWN holds the CTRL, ALT, and SHIFT keys temporarily toggled on,
; allowing keystroke combinations to be entered with sequential rather
; than simultaneous keypresses. Syntax is:
;
; STAYDOWN [/D | /U]
;
; where /D disables the program until it is run again from the
; command line, and /U uninstalls it.
;=============================================================================
KBDATA EQU 60H ;Keyboard data port
KBCTRL EQU 61H ;Keyboard control port
ALT EQU 38H ;Scan code for ALT key
CTRL EQU 1DH ;Scan code for CTRL key
LSHIFT EQU 2AH ;Scan code for left SHIFT key
RSHIFT EQU 36H ;Scan code for right SHIFT key
CR EQU 0DH
LF EQU 0AH
;=============================================================================
;BIOS Data Area
;=============================================================================
BIOS_DATA SEGMENT AT 40H
ORG 17H
SHIFT_STATE_1 DB ? ;Primary shift state byte
SHIFT_STATE_2 DB ? ;Left CTRL/ALT (bits 0, 1)
ORG 96H
SHIFT_STATE_3 DB ? ;Right CTRL/ALT (bits 2, 3)
BIOS_DATA ENDS
;=============================================================================
;Code Segment (code and data)
;=============================================================================
CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE, DS:CODE, ES:CODE, SS:CODE
ORG 100H
BEGIN: JMP INITIALIZE
PROGRAM DB "STAYDOWN 1.0 (c) 1988 Ziff Communications Co.",CR,LF
AUTHOR DB "PC Magazine ",254," Jeff Prosise",CR,LF,"$",1AH
CHECKFLAG DB ? ;Enable/disable flag
RESTORE_FLAG DB 0 ;Break code ignored flag
LAST_SCAN_CODE DB 0 ;Last scan code
EO_FLAG DB 0 ;80h = last code was E0h
KB_VECTOR DB 15H ;Vector altered to trap keys
BIOS_ISR LABEL DWORD
OLD_VECTOR DW 2 DUP (?) ;Old interrupt 9/15h vector
;-----------------------------------------------------------------------------
;INT9H handles interrupt 9 on machines that lack interrupt 15h keyboard
;processing facilities.
;-----------------------------------------------------------------------------
INT9H PROC FAR
ASSUME CS:CODE, DS:NOTHING, ES:NOTHING, SS:NOTHING
CMP CS:CHECKFLAG,0 ;Exit to BIOS if program
JE PASS_TO_BIOS ; isn't currently enabled
STI ;Interrupts on
PUSH AX
IN AL,KBDATA ;Read scan code from keyboard
CALL MAIN ;Perform internal processing
JNC RESET_KEYBOARD ;Ignore scan code if CF = 0
POP AX
PASS_TO_BIOS: JMP CS:BIOS_ISR ;Jump to BIOS int handler
RESET_KEYBOARD: IN AL,KBCTRL ;Reset the keyboard
MOV AH,AL
OR AL,80H
OUT KBCTRL,AL
MOV AL,AH
OUT KBCTRL,AL
CLI
MOV AL,20H ;Signal EOI to interrupt
OUT 20H,AL ; controller
STI
POP AX
IRET ;Exit without processing
INT9H ENDP
;-----------------------------------------------------------------------------
;INT15H handles interrupt 15h on machines with an extended BIOS.
;-----------------------------------------------------------------------------
INT15H PROC FAR
ASSUME CS:CODE, DS:NOTHING, ES:NOTHING, SS:NOTHING
CMP AH,4FH ;Exit to BIOS handler if
JNE EXIT_TO_BIOS ; function code <> 4Fh
STI ;Interrupt on
CMP CS:CHECKFLAG,0 ;Process scan code as normal
JE PROCESS_SCAN_CODE ; if program is disabled
CMP AL,0E0H ;Set flag and terminate if
JNE NOT_EO ; scan code = E0h
MOV CS:EO_FLAG,80H
JMP SHORT PROCESS_SCAN_CODE
NOT_EO: CMP CS:EO_FLAG,0 ;Branch if E0 flag not set
JE CHECK_CODE
CMP AL,2AH ;If this scan code is part of
JE RESET_EO_FLAG ; a 4-code sequence, then
CMP AL,0AAH ; reset E0 flag and process
JE RESET_EO_FLAG ; the scan code
CMP AL,36H
JE RESET_EO_FLAG
CMP AL,0B6H
JNE CHECK_CODE
RESET_EO_FLAG: MOV CS:EO_FLAG,0 ;Reset flag
JMP SHORT PROCESS_SCAN_CODE ;Process the scan code
CHECK_CODE: PUSH AX
CALL MAIN ;Perform internal processing
MOV CS:EO_FLAG,0
POP AX
RET 2 ;Return with flags intact
PROCESS_SCAN_CODE:
STC ;Set CF for BIOS processing
RET 2 ;Return with flags intact
EXIT_TO_BIOS: JMP CS:BIOS_ISR ;Pass to BIOS for processing
INT15H ENDP
;-----------------------------------------------------------------------------
;MAIN is called by the two interrupt handling routines to process a keystroke.
;Entry: AL - scan code
;-----------------------------------------------------------------------------
MAIN PROC NEAR
ASSUME CS:CODE, DS:NOTHING, ES:NOTHING, SS:NOTHING
TEST AL,80H ;Branch on break code
JNZ BREAK_CODE
;
;Process a make code by simply saving the scan code.
;
OR AL,CS:EO_FLAG ;Save E0h indicator
MOV CS:LAST_SCAN_CODE,AL ;Save make code
STC ;Exit with CF = 1
RET
;
;A break code was received.
;
BREAK_CODE: CMP CS:RESTORE_FLAG,0 ;Branch if shift bits are
JNE RESTORE_SHIFT_BYTES ; out of sync
AND AL,7FH ;Strip break bit
OR AL,CS:EO_FLAG ;Add E0h indicator
CMP AL,CS:LAST_SCAN_CODE ;Branch if the key released
JE CHECK_FOR_SHIFT ; was the last one pressed
PROCESS_BREAK: MOV LAST_SCAN_CODE,0 ;Process break code as normal
STC
RET
;
;Ignore the break if the key just released was a shift key.
;
CHECK_FOR_SHIFT:
CMP AL,ALT ;Check codes for ALT, CTRL,
JE IGNORE_BREAK ; and SHIFT keys
CMP AL,ALT+80H
JE IGNORE_BREAK
CMP AL,CTRL
JE IGNORE_BREAK
CMP AL,CTRL+80H
JE IGNORE_BREAK
CMP AL,LSHIFT
JE IGNORE_BREAK
CMP AL,RSHIFT
JNE PROCESS_BREAK
IGNORE_BREAK: MOV CS:RESTORE_FLAG,AL ;Ignore the break code
MOV CS:LAST_SCAN_CODE,0
CLC ;Return with CF = 0
RET
;
;Reset the BIOS shift bit(s) corresponding to the last key release ignored.
;
RESTORE_SHIFT_BYTES:
MOV AL,CS:RESTORE_FLAG ;Recover ignored scan code
MOV CS:RESTORE_FLAG,0 ;Reset flag
PUSH ES ;Point ES to BIOS data area
PUSH AX
MOV AX,40H
MOV ES,AX
POP AX
CMP AL,RSHIFT ;Reset a single bit if
JNE NOT_RSHIFT ; right SHIFT key was
AND ES:[SHIFT_STATE_1],0FEH ; released
JMP SHORT END_RESTORE
NOT_RSHIFT: CMP AL,LSHIFT ;Likewise for left SHIFT
JNE NOT_LSHIFT
AND ES:[SHIFT_STATE_1],0FDH
JMP SHORT END_RESTORE
NOT_LSHIFT: CMP AL,CTRL+80H ;Reset right CTRL key bit
JNE NOT_RCTRL
AND ES:[SHIFT_STATE_3],0FBH
JMP SHORT FIX_PRIMARY_SHIFT
NOT_RCTRL: CMP AL,CTRL ;Reset two left CTRL bits
JNE NOT_LCTRL
AND ES:[SHIFT_STATE_1],0FBH
AND ES:[SHIFT_STATE_2],0FEH
TEST ES:[SHIFT_STATE_3],10H ;Branch for further processing
JZ END_RESTORE ; if this is a 101-key
JMP SHORT FIX_PRIMARY_SHIFT ; keyboard
NOT_LCTRL: CMP AL,ALT+80H ;Reset right ALT bit
JNE NOT_RALT
AND ES:[SHIFT_STATE_3],0F7H
JMP SHORT FIX_PRIMARY_SHIFT
NOT_RALT: AND ES:[SHIFT_STATE_1],0F7H ;Reset two left ALT bits
AND ES:[SHIFT_STATE_2],0FDH
TEST ES:[SHIFT_STATE_3],10H ;Test for 101-key keyboard
JZ END_RESTORE ;Branch if it's not
FIX_PRIMARY_SHIFT:
MOV AH,ES:[SHIFT_STATE_2] ;Set CTRL/ALT bits in primary
SHL AH,1 ; shift state byte if either
SHL AH,1 ; left or right CTRL/ALT is
OR AH,ES:[SHIFT_STATE_3] ; pressed
AND AH,0CH
AND ES:[SHIFT_STATE_1],0F3H
OR ES:[SHIFT_STATE_1],AH
END_RESTORE: POP ES
JMP PROCESS_BREAK ;Process the break code
MAIN ENDP
;-----------------------------------------------------------------------------
;INITIALIZE installs the program into memory.
;-----------------------------------------------------------------------------
HEADMSG DB CR,LF,"STAYDOWN: $"
ERRMSG1 DB "Usage: STAYDOWN [/D][/U]",CR,LF,"$"
ERRMSG2 DB "Not Installed",CR,LF,"$"
ERRMSG3 DB "Cannot Uninstall",CR,LF,"$"
ERRMSG4 DB "Uninstall Error",CR,LF,"$"
CONFIRM_MSG1 DB "Disabled",CR,LF,"$"
CONFIRM_MSG2 DB "Uninstalled",CR,LF,"$"
CONFIRM_MSG3 DB "Activated",CR,LF,"$"
INSTALL_FLAG DB 0
INITIALIZE PROC NEAR
ASSUME CS:CODE,DS:CODE,ES:CODE,SS:CODE
;
;See if STAYDOWN is already installed.
;
CLD ;Clear DF
NOT WORD PTR [BEGIN] ;Initialize fingerprint
XOR BX,BX ;Initialize segment values
MOV AX,CS
ASSUME ES:NOTHING
INIT1: INC BX ;Advance to next segment
MOV ES,BX
CMP AX,BX ;End search if we loop back
JE PARSE ; to the current segment
MOV SI,OFFSET BEGIN ;Check for ASCII fingerprint
MOV DI,SI
MOV CX,16
REPE CMPSB
JNE INIT1 ;Loop if not found
MOV INSTALL_FLAG,1 ;Program is already installed
;
;Parse the command line for a /D or /U parameter.
;
PARSE: MOV SI,81H ;Point DS:SI to command line
PARSE1: CMP BYTE PTR [SI],32 ;Advance to first non-space
JNE PARSE2
INC SI
JMP SHORT PARSE1
PARSE2: CMP BYTE PTR [SI],CR ;End-of-line?
JE INSTALL ;Yes, then install/enable
AND BYTE PTR [SI+1],0DFH ;Capitalize entry
CMP WORD PTR [SI],442FH ;Qualifier /D?
JE DISABLE ;Yes, then disable program
CMP WORD PTR [SI],552FH ;Qualifier /U?
JE UNINSTALL ;Yes, then uninstall program
MOV AL,1 ;Error code
MOV DX,OFFSET ERRMSG1 ;Error message address
ERROR_EXIT:
PUSH AX ;Save registers
PUSH DX
MOV DX,OFFSET HEADMSG ;Display prologue
MOV AH,9
INT 21H
POP DX ;Display error
MOV AH,9
INT 21H
POP AX ;Error code
MOV AH,4CH ;Terminate with ERRORLEVEL set
INT 21H
;
;Disable STAYDOWN if a copy is present in memory.
;
DISABLE:
CMP INSTALL_FLAG,1 ;Error if not installed
JE DISABLE2
MOV AL,2
MOV DX,OFFSET ERRMSG2 ;Initialize error pointer
JMP ERROR_EXIT
DISABLE2:
MOV ES:[CHECKFLAG],0 ;Clear CHECKFLAG byte
MOV DX,OFFSET CONFIRM_MSG1 ;Print confirmation message
CONFIRM_AND_EXIT:
PUSH DX
MOV DX,OFFSET HEADMSG
MOV AH,9
INT 21H
POP DX
MOV AH,9
INT 21H
MOV AX,4C00H ;Exit with ERRORLEVEL = 0
INT 21H
;
;Uninstall STAYDOWN if a copy is present in memory.
;
UNINSTALL:
CMP INSTALL_FLAG,1 ;Error if not installed
JE UNINSTALL2
MOV AL,3
MOV DX,OFFSET ERRMSG2 ;Initialize error pointer
JMP ERROR_EXIT
UNINSTALL2:
CALL REMOVE ;Uninstall the program
JNC UNINSTALL3
MOV AL,4
JMP ERROR_EXIT
UNINSTALL3:
MOV DX,OFFSET CONFIRM_MSG2 ;Print confirmation message
JMP SHORT CONFIRM_AND_EXIT ;And exit
;
;Install the program if it isn't already installed, or enable it if it is.
;
INSTALL: MOV ES:[CHECKFLAG],1 ;Set enable byte
CMP INSTALL_FLAG,1 ;Branch if not installed
JNE INSTALL1
MOV DX,OFFSET CONFIRM_MSG3 ;Print confirmation message
JMP SHORT CONFIRM_AND_EXIT ;And exit
INSTALL1: MOV AH,0C0H ;Check for BIOS support of
INT 15H ; extended functions
MOV DX,OFFSET INT15H
JNC INSTALL2 ;Branch if support is there
MOV KB_VECTOR,9 ;Use int 9 rather than 15h
MOV DX,OFFSET INT9H ;Point DX to int 9 routine
INSTALL2: MOV AH,35H ;Save current vector
MOV AL,KB_VECTOR
INT 21H
MOV OLD_VECTOR,BX
MOV OLD_VECTOR[2],ES
MOV AH,25H ;Then point it to internal
MOV AL,KB_VECTOR ; interrupt handler
INT 21H
MOV AX,DS:[2CH] ;Get environment segment
MOV ES,AX ; address from PSP
MOV AH,49H ;Then deallocate environment
INT 21H ; space reserved by DOS
MOV AH,9 ;Print installation message
MOV DX,OFFSET PROGRAM
INT 21H
MOV AX,3100H ;Terminate but remain resident
MOV DX,(OFFSET INITIALIZE-OFFSET CODE+15) SHR 4
INT 21H
INITIALIZE ENDP
;-----------------------------------------------------------------------------
;REMOVE deallocates the memory block addressed by ES and restores the
;Interrupt vector displaced on installation.
;-----------------------------------------------------------------------------
REMOVE PROC NEAR
PUSH ES ;Get current interrupt 9/15h
MOV AH,35H ; vector and see if STAYDOWN
MOV AL,ES:[KB_VECTOR] ; still owns it
INT 21H
MOV BX,ES
POP ES
MOV AX,ES
CMP BX,AX ;Program cannot be uninstalled
JE RESTORE_VECTOR ; if interrupt 9/15h vector
MOV DX,OFFSET ERRMSG3 ; has been grabbed away
STC ;Return with CF = 1 for error
RET
RESTORE_VECTOR:
PUSH DS ;Restore displaced interrupt
ASSUME DS:NOTHING ; vector
LDS DX,ES:[BIOS_ISR]
MOV AH,25H
MOV AL,ES:[KB_VECTOR]
INT 21H
POP DS
ASSUME DS:CODE
NOT WORD PTR ES:[BEGIN] ;Remove fingerprint
MOV AH,49H ;Free memory given to
INT 21H ; original program block
MOV DX,OFFSET ERRMSG4 ;Initialize error pointer
RET ;Exit with CF intact
REMOVE ENDP
CODE ENDS
END BEGIN