home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
magazine
/
pcmagazi
/
1989
/
05
/
lites.asm
< prev
next >
Wrap
Assembly Source File
|
1988-12-16
|
16KB
|
553 lines
;=============================================================================
; LITES displays the realtime status of the UART's DTR, RTS, CTS, DSR, DCD,
; and RI lines as well as its Baud rate and data format settings. Syntax is:
; LITES [comport] [U]
; where comport is a number indicating which COM port is to be monitored,
; and U uninstalls the program from memory.
;=============================================================================
CODE SEGMENT PARA PUBLIC 'CODE'
ASSUME CS:CODE
ORG 100H
BEGIN: JMP INITIALIZE
PROGRAM DB "LITES 1.0 (c) 1989 Ziff Communications Co.",13,10
AUTHOR DB "PC Magazine ",254," Jeff Prosise",13,10
HOTKEY DB "Hotkey is Alt-L",32,32,32,13,10,"$"
;-----------------------------------------------------------------------------
; Patch points to modify the program's operation.
;-----------------------------------------------------------------------------
KEYCODE DB 26H ;scan code for "L" key
VIDEO_ATTR DB 70H ;status line video attribute
ROWNUM DB 0 ;row number of status line
COL_OFFSET DB 0 ;offset from right margin
TICKS DB 2 ;ticks between refreshes
COMPORT DW 0 ;COM port designator (COM1)
;-----------------------------------------------------------------------------
; Other program variables.
;-----------------------------------------------------------------------------
INT09H DD ? ;interrupt 9h vector
INT08H DD ? ;interrupt 8h vector
COUNTER DB 0FFH ;refresh counter
PINS DB ? ;bit 0 = DTR, 1 = RTS
; 2 = CTS, 3 = DSR
; 4 = RI, 5 = DCD
BAUDRATE DW ? ;Baud rate
PARITY DB ? ;parity setting
DATABITS DB ? ;number of data bits
STOPBITS DB ? ;number of stop bits
VIDEOSEG DW ? ;video segment address
VIDEOADDR DW ? ;video offset address
SYNCFLAG DB ? ;0 = no video sync, 1 = sync
PINTEXT DB "DTRRTSCTSDSRRI",32,"DCD"
;=============================================================================
; KBINT intercepts and handles the keyboard interrupt 9h.
;=============================================================================
KBINT PROC FAR
PUSHF ;save flags
PUSH AX ;save AX
STI ;interrupts on
IN AL,60H ;get scan code from keyboard
CMP AL,CS:[KEYCODE] ;exit to BIOS if it's not
JNE NOT_HOT ; the hotkey
MOV AH,2 ;get keyboard shift state
INT 16H
AND AL,0FH ;mask off the upper 4 bits
CMP AL,8 ;exit if Alt isn't held down
JNE NOT_HOT
MOV AH,0FH ;get current video mode
INT 10H
CMP AL,7 ;abort if not in text mode
JE RESET
CMP AL,4
JB RESET
NOT_HOT: POP AX ;exit to BIOS int 9 handler
POPF
JMP CS:INT09H
;
;Reset the keyboard controller and interrupt controller.
;
RESET: CLI ;interrupts off
IN AL,61H ;reset the keyboard controller
MOV AH,AL
OR AL,80H
OUT 61H,AL
XCHG AH,AL
MOV AL,20H ;signal EOI to interrupt
OUT 20H,AL ; controller
STI ;interrupts back on
PUSH BX ;save registers
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
PUSH BP
;
;Deactivate the status line if it is currently displayed.
;
CMP CS:[COUNTER],0FFH ;branch if status line is
JE SETVIDEO ; dormant
MOV CS:[COUNTER],0FFH ;disable counter
MOV AX,CS ;point DS:SI to buffer
MOV DS,AX
MOV SI,OFFSET INITIALIZE
MOV ES,CS:[VIDEOSEG] ;point ES:DI to video memory
MOV DI,CS:[VIDEOADDR]
MOV CX,32
CALL VIDEO_XFER ;erase the status line
JMP SHORT KB_EXIT
;
;Initialize video parameters.
;
SETVIDEO: MOV CS:[VIDEOSEG],0B800H ;set default video parms
MOV CS:[SYNCFLAG],0
MOV AX,40H ;point ES to BIOS data
MOV ES,AX ; area
TEST BYTE PTR ES:[63H],20H ;set video segment value
JZ COLOR ; (monochrome or color)
MOV CS:[VIDEOSEG],0B000H
JMP SHORT NOSYNC
COLOR: MOV AH,12H ;if a color adapter is
MOV BL,10H ; detected, determine
INT 10H ; whether or not it's
CMP BL,10H ; a CGA and set SYNCFLAG
JNE NOSYNC ; if it is
MOV CS:[SYNCFLAG],1
NOSYNC: MOV AX,ES:[4AH] ;calculate offset address
SHL AX,1 ; within video segment
MOV BL,CS:[ROWNUM] ;multiply number of columns
MUL BL ; by row number
MOV BX,ES:[4AH] ;add column offset
SUB BL,32
SUB BL,CS:[COL_OFFSET]
SHL BL,1
ADD AX,BX
ADD AX,ES:[4EH] ;add page address
MOV CS:[VIDEOADDR],AX ;store it
;
;Save the portion of the screen that will be overwritten by the status line.
;
MOV DS,CS:[VIDEOSEG] ;point DS:SI to video memory
MOV SI,CS:[VIDEOADDR]
MOV AX,CS ;point ES:DI to save buffer
MOV ES,AX
MOV DI,OFFSET INITIALIZE
MOV CX,32
CALL VIDEO_XFER ;block move
;
;Activate the status line, restore registers, and exit.
;
MOV AL,CS:[TICKS] ;enable counter
MOV CS:[COUNTER],AL
KB_EXIT: POP BP ;restore registers
POP ES
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX ;restore AX and flags
POPF
IRET
KBINT ENDP
;=============================================================================
; TIMERINT intercepts and handles the timer tick interrupt 8h.
;=============================================================================
TIMERINT PROC FAR
PUSHF ;push flags for int call
CALL CS:INT08H ;call old interrupt handler
CMP CS:[COUNTER],0FFH ;exit if status line is
JE TIMER_EXIT ; dormant
DEC CS:[COUNTER] ;decrement timer
JNZ TIMER_EXIT ;exit if nonzero
PUSH AX
MOV AL,CS:[TICKS] ;reset counter
MOV CS:[COUNTER],AL
PUSH BX ;save remaining registers
PUSH CX
PUSH DX
PUSH SI
PUSH DI
PUSH DS
PUSH ES
STI ;enable interrupts
CALL SETPARMS ;set output variables
CALL REFRESH ;refresh the status display
POP ES ;restore registers and exit
POP DS
POP DI
POP SI
POP DX
POP CX
POP BX
POP AX
TIMER_EXIT: IRET ;exit
TIMERINT ENDP
;-----------------------------------------------------------------------------
; SETPARMS is called by TIMERINT to set UART parameter values.
;-----------------------------------------------------------------------------
PSETTINGS DB "NONE"
DLAB_REG DB ?
SETPARMS PROC NEAR
MOV DX,CS:[COMPORT] ;get UART base address
ADD DX,3 ;point DX to Data Format
PUSH DX
IN AL,DX ;read Data Format byte
MOV CS:[DLAB_REG],AL ;save it
OR AL,80H ;set DLAB
OUT DX,AL
SUB DX,3 ;read divisor LSB
IN AL,DX
MOV BL,AL
INC DX
IN AL,DX ;read divisor MSB
MOV BH,AL
OR BX,BX ;don't divide if BX = 0
JNZ SP1
MOV WORD PTR CS:[BAUDRATE],0
JMP SHORT SP2
SP1: MOV AX,0C200H ;calculate Baud rate from
MOV DX,1 ; clock and divisor
DIV BX
MOV CS:[BAUDRATE],AX ;save it
SP2: POP DX ;restore Data Format register
MOV AL,CS:[DLAB_REG]
OUT DX,AL
;
;Determine what the parity, data bits, and stop bits settings are.
;
MOV AL,CS:[DLAB_REG] ;data bits in bits 0 and 1
AND AL,3
ADD AL,5
MOV CS:[DATABITS],AL
MOV AL,CS:[DLAB_REG] ;stop bits in bit 2
SHR AL,1
SHR AL,1
AND AL,1
ADD AL,1
MOV CS:[STOPBITS],AL
MOV BL,CS:[DLAB_REG] ;parity in bits 3 and 4
MOV CL,3
SHR BL,CL
AND BL,3
XOR BH,BH
MOV AL,BYTE PTR CS:[PSETTINGS][BX]
MOV CS:[PARITY],AL
;
;Determine the states of the CTS, DSR, DCD, and RI input pins.
;
MOV DX,CS:[COMPORT] ;point DX to Modem Status
ADD DX,6
IN AL,DX ;read register
AND AL,0F0H ;mask off the lower 4 bits
SHR AL,1 ;then save them
SHR AL,1
MOV CS:[PINS],AL
;
;Determine the states of the RTS and DTR output pins.
;
SUB DX,2 ;point DX to Modem Control
IN AL,DX ;read register
AND AL,3 ;strip the upper 6 bits
OR CS:[PINS],AL ;store in PINS byte
RET
SETPARMS ENDP
;-----------------------------------------------------------------------------
; REFRESH is called by TIMERINT to display the status line.
;-----------------------------------------------------------------------------
REFRESH PROC NEAR
MOV AX,CS ;copy the underlying line
MOV DS,AX ; into the status buffer
MOV ES,AX
MOV SI,OFFSET INITIALIZE
MOV DI,OFFSET INITIALIZE + 64
MOV CX,32
CLD
REP MOVSW
;
;Construct the portion of the string pertaining to the 6 pins.
;
MOV SI,OFFSET PINTEXT ;point SI to text
MOV DI,OFFSET INITIALIZE + 64 ;point DI to buffer
MOV BL,1
MOV AH,CS:[VIDEO_ATTR]
MOV CX,6 ;6 pins to test
RLOOP1: PUSH CX
PUSH SI
PUSH DI
TEST CS:[PINS],BL ;copy pin name to buffer if
JZ PINLOW ; corresponding bit is set
MOV CX,3
RLOOP2: LODSB
STOSW
LOOP RLOOP2
PINLOW: POP DI
POP SI
SHL BL,1
ADD SI,3
ADD DI,8
POP CX
LOOP RLOOP1 ;loop unitl all 6 are done
;
;Add Baud rate, parity, data bits, and stop bits indicators to the string.
;
MOV AX,CS:[BAUDRATE] ;Baud rate
CALL BIN2ASC
MOV DI,OFFSET INITIALIZE + 64 + 58
MOV AL,CS:[PARITY] ;parity
MOV AH,CS:[VIDEO_ATTR]
STOSW
MOV AL,CS:[DATABITS] ;data bits
ADD AL,30H
STOSW
MOV AL,CS:[STOPBITS] ;stop bits
ADD AL,30H
STOSW
;
;Display the status string.
;
MOV SI,OFFSET INITIALIZE + 64
MOV ES,CS:[VIDEOSEG]
MOV DI,CS:[VIDEOADDR]
MOV CX,32
CALL VIDEO_XFER
RET
REFRESH ENDP
;-----------------------------------------------------------------------------
; VIDEO_XFER transfers a block of data to or from the video buffer.
; Entry: DS:SI - source
; ES:DI - destination
; CX - number of words
;-----------------------------------------------------------------------------
VIDEO_XFER PROC NEAR
CLD ;clear DF
TEST CS:[SYNCFLAG],1 ;don't wait if this isn't
JZ NOWAIT ; a CGA
MOV DX,3DAH ;wait if it is
MWAIT1: IN AL,DX ;wait for non-retrace period
TEST AL,8
JNZ MWAIT1
MWAIT2: IN AL,DX ;wait for the next vertical
TEST AL,8 ; retrace
JZ MWAIT2
NOWAIT: CLI ;interrupts off
REP MOVSW ;block move
STI ;interrupts back on
RET
VIDEO_XFER ENDP
;-----------------------------------------------------------------------------
; BIN2ASC converts a single binary word value into its ASCII decimal
; equivalent and writes it to the designated output buffer.
; Entry: AX - binary value
; ES:DI - destination
;-----------------------------------------------------------------------------
BASE DW 10 ;base 10 divisor
BIN2ASC PROC NEAR
XOR CX,CX ;zero digit counter
BALOOP1: INC CX ;increment counter
XOR DX,DX
DIV CS:[BASE] ;divide by base
PUSH DX ;save remainder on stack
OR AX,AX ;loop until quotient is zero
JNZ BALOOP1
BALOOP2: POP AX ;pull digits back off the
ADD AL,30H ; stack and output them
MOV AH,CS:[VIDEO_ATTR]
STOSW
LOOP BALOOP2
RET
BIN2ASC ENDP
;=============================================================================
; INITIALIZE installs or uninstalls the program.
;=============================================================================
ERRMSG1 DB "Usage: LITES [comport] [U]$"
ERRMSG2 DB "Not Installed$"
ERRMSG3 DB "Cannot Uninstall$"
ERRMSG4 DB "Already Installed$"
ERRMSG5 DB "Invalid COM Port$"
OUTTEXT DB "Uninstalled$"
INSTALLED DB 0
INITIALIZE PROC NEAR
ASSUME CS:CODE, DS:CODE
;
;See if a copy of LITES is already resident in memory.
;
CLD ;clear DF for string ops
MOV WORD PTR [BEGIN],0 ;initialize fingerprint
XOR BX,BX ;zero BX for start
MOV AX,CS ;keep CS value in AX
INIT1: INC BX ;increment search segment value
MOV ES,BX
CMP AX,BX ;not installed if current
JE PARSE1 ; segment is reached
MOV SI,OFFSET BEGIN ;search this segment for ASCII
MOV DI,SI ; fingerprint
MOV CX,16
REPE CMPSB
JNE INIT1 ;loop back if not found
MOV INSTALLED,1 ;set installed flag
;
;Parse the command line for entries.
;
PARSE1: MOV SI,81H ;point SI to command line
PARSE2: LODSB ;get a character
CMP AL,20H ;skip it if it's a space
JE PARSE2
CMP AL,0DH ;exit loop when a carriage
JE INSTALL ; return is encountered
CMP AL,"0" ;branch if numeral is found
JB ERROR1
CMP AL,"9"
JBE CHECK_COM
AND AL,0DFH ;capitalize the character
CMP AL,"U" ;branch to uninstall code if
JE UNINSTALL ; character is a "U"
;
;An error was encountered in parsing. Display error message and exit.
;
ERROR1: MOV DX,OFFSET ERRMSG1 ;load message address
ERROR2: MOV AH,9 ;display error message
INT 21H
MOV AX,4C01H ;exit with ERRORLEVEL = 1
INT 21H
;
;Make sure the COM port entered on the command line exists.
;
CHECK_COM: SUB AL,"1" ;normalize the entry
MOV BL,AL ;save it
INT 11H ;determine number of COM
SHR AH,1 ; ports installed
AND AH,07H
MOV DX,OFFSET ERRMSG5
CMP AH,BL ;exit on error if COM port
JNA ERROR2 ; number is invalid
MOV BYTE PTR COMPORT,BL ;save port designator
JMP SHORT INSTALL ;go to install routine
;
;Uninstall the program.
;
UNINSTALL: MOV DX,OFFSET ERRMSG2 ;error if program isn't
CMP INSTALLED,0 ; installed
JE ERROR2
CALL REMOVE ;call uninstall routine
MOV DX,OFFSET ERRMSG3 ;error if uninstall failed
JC ERROR2
MOV DX,OFFSET OUTTEXT ;display "Uninstalled"
MOV AH,9 ; message
INT 21H
MOV AX,4C00H ;exit with ERRORLEVEL = 0
INT 21H
;
;Make sure LITES isn't already installed, then get the UART base address.
;
INSTALL: MOV DX,OFFSET ERRMSG4 ;exit on error if program
CMP INSTALLED,0 ; is already installed
JNE ERROR2
MOV AX,40H ;get UART address from BIOS
MOV ES,AX ; data area using the port
XOR DI,DI ; number as an index into
MOV BX,COMPORT ; the table
SHL BX,1
MOV AX,WORD PTR ES:[DI][BX]
MOV COMPORT,AX
;
;Hook into interrupts 9h and 8h and deallocate the environment block.
;
MOV AX,3509H ;save old interrupt 9h vector
INT 21H
MOV WORD PTR INT09H,BX
MOV WORD PTR INT09H[2],ES
MOV AX,2509H ;then set the new 9h vector
MOV DX,OFFSET KBINT
INT 21H
MOV AX,3508H ;save old interrupt 8h vector
INT 21H
MOV WORD PTR INT08H,BX
MOV WORD PTR INT08H[2],ES
MOV AX,2508H ;then set the new 8h vector
MOV DX,OFFSET TIMERINT
INT 21H
MOV AX,DS:[2CH] ;deallocate the program's
MOV ES,AX ; environment block
MOV AH,49H
INT 21H
;
;Display copyright notice, then terminate and remain resident in memory.
;
MOV AH,9 ;display copyright and hotkey
MOV DX,OFFSET PROGRAM ; information
INT 21H
MOV AX,3100H
MOV DX,(OFFSET INITIALIZE - OFFSET CODE + 15 + 128) SHR 4
INT 21H
INITIALIZE ENDP
;-----------------------------------------------------------------------------
; REMOVE deallocates the memory block addressed by ES and restores the
; interrupt vectors displaced on installation.
; Entry: ES - segment to release
; Exit: CF clear - program uninstalled
; CF set - can't uninstall
;-----------------------------------------------------------------------------
REMOVE PROC NEAR
MOV CX,ES ;abort if either interrupt
MOV AX,3509H ; vector has been altered
INT 21H ; since installation
MOV AX,ES
CMP AX,CX
JNE REMOVE_ERROR
MOV AX,3508H
INT 21H
MOV AX,ES
CMP AX,CX
JNE REMOVE_ERROR
;
;Free memory given to the original program block.
;
MOV ES,CX ;Ask DOS to free it
MOV AH,49H
INT 21H
JC REMOVE_ERROR ;exit if call failed
;
;Restore the interrupt 9h and 8h vectors to their installation values.
;
PUSH DS
ASSUME DS:NOTHING
MOV AX,2509H ;restore interrupt 9h vector
LDS DX,ES:[INT09H]
INT 21H
MOV AX,2508H ;restore interrupt 8h vector
LDS DX,ES:[INT08H]
INT 21H
POP DS
ASSUME DS:CODE
NOT WORD PTR ES:[BEGIN] ;destroy ASCII fingerprint
CLC ;clear CF for exit
RET
REMOVE_ERROR: STC ;set CF to indicate program
RET ; couldn't be uninstalled
REMOVE ENDP
CODE ENDS
END BEGIN