home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power-Programmierung
/
CD1.mdf
/
assemblr
/
library
/
asm_kit
/
keybuff.asm
< prev
next >
Wrap
Assembly Source File
|
1983-11-14
|
8KB
|
252 lines
VECTORS SEGMENT AT 0H
ORG 9H*4
KEYBOARD_INT_VECTOR LABEL DWORD
ORG 16H*4
KEYBOARD_IO_VECTOR LABEL DWORD
VECTORS ENDS
;
ROM_BIOS_DATA SEGMENT AT 40H
ORG 17H
KBD_FLAG DB ?
ORG 1AH
ROM_BUFFER_HEAD DW ?
ROM_BUFFER_TAIL DW ?
KB_BUFFER DW 16 DUP (?)
KB_BUFFER_END LABEL WORD
ROM_BIOS_DATA ENDS
;
CODE_SEG SEGMENT
ASSUME CS:CODE_SEG
ORG 100H
BEGIN: JMP INIT_VECTORS ;Initialize vectors and attach to
; DOS
ROM_KEYBOARD_INT DD ;Address for ROM routine
ROM_KEYBOARD_IO DD
BUFFER_HEAD DW OFFSET KEYBOARD_BUFFER
BUFFER_TAIL DW OFFSET KEYBOARD_BUFFER
KEYBOARD_BUFFER DW 160 DUP (0) ;159 character input buffer
KEYBOARD_BUFFER_END LABEL WORD
;
; This procedure sends a short beep when the buffer fills:
;
KB_CONTROL EQU 61H ;Control bits for keyboard and
; speaker
ERROR_BEEP PROC NEAR
PUSH AX
PUSH BX
PUSH CX
PUSHF ;Save the old interrupt enable flag
CLI ;Turn off beep during interrupt
MOV BX,30 ;Number of cycles for 1/8 sec beep
IN AL,KB_CONTROL ;Get control info from speaker port
PUSH AX ;Save the control information
START_OF_ONE_CYCLE:
AND AL,0FCH ;Turn off the speaker
OUT KB_CONTROL,AL
MOV CX,60 ;Delay for one half cycle
OFF_LOOP: LOOP OFF_LOOP
OR AL,2 ;Turn on the speaker
OUT KB_CONTROL,AL
MOV CX,60 ;Delay for second half of cycle
ON_LOOP: LOOP ON_LOOP
DEC BX ;200 cycles yet?
JNZ START_OF_ONE_CYCLE
POP AX ;Recover old keyboard information
OUT KB_CONTROL,AL
POPF ;Restore interrupt flag
POP CX
POP BX
POP AX
RET
ERROR_BEEP ENDP
;
; This procedure checks the ROM keyboard buffer to see if some program tried to
; clear this buffer. We know it's been cleared when the ROM tail and header
; overlap. Normally, the new procedures below keep the dummy character,
; word 0, in the buffer.
;
; Uses BX,DS
; Writes: BUFFER_HEAD, BUFFER_TAIL, ROM_BUFFER_HEAD, ROM_BUFFER_TAIL
; Reads: KEYBOARD_BUFFER, KB_BUFFER
;
CHECK_CLEAR_BUFFER PROC NEAR
ASSUME DS:ROM_BIOS_DATA
MOV BX,ROM_BIOS_DATA ;Establish pointer to BIOS data
MOV DS,BX
CLI ;Turn of interrupts during check
MOV BX,ROM_BUFFER_HEAD ;Check to see if buffer cleared
CMP BX,ROM_BUFFER_TAIL ;Is the buffer empty?
JNE BUFFER_OK ;No, then everything is OK
; Yes, then clear internal buffer
MOV BX,OFFSET KB_BUFFER ;Reset buffer with word 0 in buffer
MOV ROM_BUFFER_HEAD,BX
ADD BX,2
MOV ROM_BUFFER_TAIL,BX
ASSUME DS:CODE_SEG
MOV BX,CS
MOV DS,BX
MOV BX,OFFSET KEYBOARD_BUFFER ;Reset internal buffer
MOV BUFFER_HEAD,BX
MOV BUFFER_TAIL,BX
BUFFER_OK:
ASSUME DS:CODE_SEG
STI ;Interrupts back on
RET
CHECK_CLEAR_BUFFER ENDP
;
; This procedure intercepts the keyboard interrupt and moves any new characters
; to the internal, 80 character buffer
;
INTERCEPT_KEYBOARD_INT PROC NEAR
ASSUME DS:NOTHING
PUSH DS
PUSH SI
PUSH BX
PUSH AX
CALL CHECK_CLEAR_BUFFER ;Check for buffer cleared
PUSHF
CALL ROM_KEYBOARD_INT ;Read scan code with BIOS routines
;
; Transfer any characters to the internal buffer
;
ASSUME DS:ROM_BIOS_DATA
MOV BX,ROM_BIOS_DATA
MOV DS,BX
MOV SI,BUFFER_TAIL
MOV BX,ROM_BUFFER_HEAD ;Check if real character in buffer
ADD BX,2 ;Skip over dummy character
CMP BX,OFFSET KB_BUFFER_END
JB DONT_WRAP ;No need to wrap pointer
MOV BX,OFFSET KB_BUFFER
DONT_WRAP:
CMP BX,ROM_BUFFER_TAIL ;Is there a real character?
JE NO_NEW_CHARACTERS ;No, then return to caller
MOV AX,[BX] ;Yes, move char to internal buffer
MOV CS:[SI],AX
ADD SI,2 ;Move to next position
CMP SI,OFFSET KEYBOARD_BUFFER_END
JB NOT_AT_END
MOV SI,OFFSET KEYBOARD_BUFFER
NOT_AT_END:
CMP SI,BUFFER_HEAD ;Buffer overrun?
JNE WRITE_TO_BUFFER ;Yes, beep and throw out character
CALL ERROR_BEEP
JMP SHORT NOT_AT_KB_END
WRITE_TO_BUFFER:
MOV BUFFER_TAIL,SI
NOT_AT_KB_END:
MOV ROM_BUFFER_HEAD,BX
;
; See if [Ctrl] + [Alt] pushed and clear buffer if so
;
NO_NEW_CHARACTERS:
MOV AL,KBD_FLAG ;Get status of shift keys into AL
AND AL,0CH ;Isolate Ctrl and Alt shift flags
CMP AL,0CH ;Both Ctrl and Alt keys pressed?
JNE DONT_CLEAR_BUFFER ;No, so don't clear buffer
MOV AX,BUFFER_TAIL ;Yes, so clear buffer
MOV BUFFER_HEAD,AX
DONT_CLEAR_BUFFER:
POP AX
POP BX
POP SI
POP DS
IRET
INTERCEPT_KEYBOARD_INT ENDP
;
; This procedure replaces the ROM BIOS routines for reading a character
;
ASSUME DS:CODE_SEG
INTERCEPT_KEYBOARD_IO PROC FAR
STI ;Interrupts back on
PUSH DS ;Save current DS
PUSH BX ;Save BX temporarily
CALL CHECK_CLEAR_BUFFER ;Check for buffer cleared
MOV BX,CS ;Establish pointer to Data Area
MOV DS,BX
OR AH,AH ;AH = 0?
JZ READ_CHARACTER ;Yes, read a character
DEC AH ;AH = 1?
JZ READ_STATUS ;Yes, return the status
DEC AH ;AH = 2?
JZ READ_SHIFT_STATUS ;Yes, return the shift status
POP BX ;Ignore other function numbers
POP DS
IRET
;
; Read the character
;
READ_CHARACTER: ;ASCII Read
STI ;Interrupts back on
NOP ;Allow an interrupt to occur
CLI ;Interrupts back off
MOV BX,BUFFER_HEAD ;Get pointer to head of buffer
CMP BX,BUFFER_TAIL ;Test end of buffer
JE READ_CHARACTER ;Loop until something appears
MOV AX,[BX] ;Get scan code and ASCII code
ADD BX,2 ;Move to next word in buffer
CMP BX,OFFSET KEYBOARD_BUFFER_END ;At end of buffer?
JNE SAVE_POINTER ;No, continue
MOV BX,OFFSET KEYBOARD_BUFFER ;Yes, reset to start
SAVE_POINTER:
MOV BUFFER_HEAD,BX ;Store value in variable
POP BX
POP DS
IRET ;Return to caller
;
; ASCII status
;
READ_STATUS:
CLI ;Interrupts off
MOV BX,BUFFER_HEAD ;Get head pointer
CMP BX,BUFFER_TAIL ;If equal then nothing there
MOV AX,[BX]
STI ;Interrupts back on
POP BX ;Recover registers
POP DS
RET 2 ;Throw away flags
;
; Shift status
;
READ_SHIFT_STATUS:
JMP ROM_KEYBOARD_IO ;Let ROM routine do this
INTERCEPT_KEYBOARD_IO ENDP
;
; This procedure initializes the interrupt vectors
;
INIT_VECTORS PROC NEAR
ASSUME DS:VECTORS
PUSH DS ;Save old Data Segment
MOV AX,VECTORS ;Set up Data Segment for vectors
MOV DS,AX
CLI ;Dont allow interrupts
MOV AX,KEYBOARD_INT_VECTOR ;Save addresses of BIOS
MOV ROM_KEYBOARD_INT,AX ;routines and set up new
MOV AX,KEYBOARD_INT_VECTOR[2] ;KEYBOARD_INT vector
MOV ROM_KEYBOARD_INT[2],AX ;
MOV KEYBOARD_INT_VECTOR,OFFSET INTERCEPT_KEYBOARD_INT
MOV KEYBOARD_INT_VECTOR[2],CS
STI ;allow interrupts again
MOV AX,KEYBOARD_IO_VECTOR ;Set up KEYBOARD_IO vector
MOV ROM_KEYBOARD_IO,AX
MOV AX,KEYBOARD_IO_VECTOR[2]
MOV ROM_KEYBOARD_IO[2],AX
MOV KEYBOARD_IO_VECTOR,OFFSET INTERCEPT_KEYBOARD_IO
MOV KEYBOARD_IO_VECTOR[2],CS
ASSUME DS:ROM_BIOS_DATA ;Now set up the keyboard buffer,
MOV AX,ROM_BIOS_DATA ;etc.
MOV DS,AX
CLI ;Dont allow interrupts
MOV BX,OFFSET KB_BUFFER
MOV ROM_BUFFER_HEAD,BX
MOV WORD PTR[BX],0
ADD BX,2
MOV ROM_BUFFER_TAIL,BX
STI ;Allow interrupts again
MOV DX,OFFSET INIT_VECTORS ;End of resident portion
INT 27H ;Terminate but stay resident
INIT_VECTORS ENDP
;
CODE_SEG ENDS
END BEGIN