Category : Utilities for DOS and Windows Machines
Archive   : KBUF_MA.ZIP
Filename : KBUF.ASM

 
Output of file : KBUF.ASM contained in archive : KBUF_MA.ZIP
title KBUF -- extend keyboard buffer

comment #

KBUF version 1.1 Copyright (C) 1988 Mark Adler
All rights reserved.

Version history -

1.0 26 May 1988 First public version
1.1 18 Nov 1988 Added queue stuff call (AH=0FFh)

kbuf.com -

kbuf maintains a 127 entry (vs. 15 entry) typeahead buffer. Also the
original 15 character buffer is retained so a maximum of 142 characters
are buffered.

The following assumptions are made about the behavior of the keyboard
scan and support interrupts:

1. The shift status is a byte stored at location 0:417h.

2. The support routine is not re-entrant.

kbuf also adds a new function to interrupt 16h---if AH is 0FFh, then
the scan code in DX is put into the queue, behind what is already
there (i.e., as if it were just typed). This is different from
stacking, which puts the keystroke at the front of the queue. On
return, AL=0 indicates success, AL=1 indicates failure (no room in
queue).

#



;
; Interrupt vector segment definitions.
;

ints segment at 0
org 4*8h ;Timer interrupt.
int8 label word
org 4*9h ;Scan interrupt.
int9 label word
org 4*16h ;Keyboard BIOS interrupt.
int16 label word
org 417h
KB_FLAG db ? ;Keyboard shift status.
ints ends



;
; Program segment.
;

kbuf segment
assume CS:kbuf,DS:kbuf,ES:kbuf,SS:kbuf



;
; Put data as low as DOS will allow.
org 5Ch

oldtv label dword
oldt dw ?,? ;Old timer routine address.
oldsv label dword
olds dw ?,? ;Old keyboard scan routine address.
oldkv label dword
oldk dw ?,? ;Old keyboard service routine address.

ink db ?,? ;In kcopy--don't call it again.

kqs dw ? ;Queue size in bytes.
kqf dw ? ;Queue front.
kqr dw ? ;Queue rear.
kq label word ;Queue.
kqsz equ 128 ;Queue size in entries plus one.



;
; Start of .COM code - jump to installation.

org 100h
start:
jmp install

db 13,'KBUF version 1.1 Copyright (C) 1988 Mark Adler',13,10
db 'All rights reserved.',13,10,'Z'-64

org kq+kqsz*2 ;Start at end of queue.



;
; Traps and their subroutines -

assume CS:kbuf,SS:nothing ;For all traps and subroutines.



timer proc near

assume DS:nothing,ES:nothing

; save registers.
push AX
push BX
push DI
push DS
push ES

; enqueue keyboard data.
call kcopy
assume DS:kbuf,ES:kbuf

; restore registers and drop to next guy in chain.
pop ES
pop DS
assume DS:nothing,ES:nothing
pop DI
pop BX
pop AX
jmp oldtv

timer endp



kscan proc near

assume DS:nothing,ES:nothing

; save registers.
push AX
push BX
push DI
push DS
push ES

; call normal service routine.
pushf ;(simulate interrupt)
call oldsv ;Call original service routine.

; enqueue keyboard data.
call kcopy
assume DS:kbuf,ES:kbuf

; restore registers and return from interrupt.
pop ES
pop DS
assume DS:nothing,ES:nothing
pop DI
pop BX
pop AX
iret

kscan endp



ksupp proc near

assume DS:nothing,ES:nothing

; save registers, set data segment.
sti ;Allow interrupts.
push BX
push SI
push DS
mov BX,CS ;Set data segment.
mov DS,BX
assume DS:kbuf

; do function in AH.
cmp AH,0FFh ;See if key stuff.
je kstuff ;If so, stuff one.
test AH,AH ;See if read.
jz kread ;If so, wait for key data.
dec AH ;See if status.
jz kstat ;If so, get status.
dec AH ;See if shift status.
jnz kdone ;If not, just return.

; get shift status from original routine.
sub BX,BX ;Get shift status in AL.
mov DS,BX
assume DS:ints
mov AL,KB_FLAG
jmp short kdone ;Return AX.
assume DS:kbuf

; peek at queue for status.
kstat:
mov BX,offset kq ;Point to queue.
cli ;Freeze queue.
call pkq ;Get entry if any, set Z.
sti ;Set interrupts back.

; return, restore registers except AX, F.
pop DS
assume DS:nothing
pop SI
pop BX
retf 2 ;Discard flags on stack.
assume DS:kbuf

; stuff - try to stuff the scan code in DX.
kstuff:
push ES
push DI
mov ES,BX ;Point ES to data area also.
assume ES:kbuf
mov BX,offset kq ;Point to queue.
mov AX,DX ;Get code to stuff.
cli ;Freeze queue.
call enq ;Enqueue code.
sti ;Unfreeze.
mov AX,0FF00h ;Restore AH, zero AL -> ok.
jnz ksok
inc AX ;AL = 1 -> failure (no room to stuff).
ksok:
pop DI
pop ES
assume ES:nothing
jmp short kdone

; read - try to dequeue until successful.
kread:
mov BX,offset kq ;Point to queue.
cli ;Freeze queue.
call deq ;Try to get entry.
sti ;Allow scan interrupt.
jz kread ;Wait until something there.

; return, restore registers except AX.
kdone:
pop DS
assume DS:nothing
pop SI
pop BX
iret

ksupp endp



kcopy proc near

assume DS:nothing,ES:nothing

; kcopy - copy data from old queue to new queue.
; Hits DS, ES, DI, BX, AX, and F.

; set up segments.
mov AX,CS
mov DS,AX
mov ES,AX
assume DS:kbuf,ES:kbuf

; lock out use of this routine.
mov AL,1 ;Try to lock out this routine.
xchg AL,ink ;(Indivisible operation.)
test AL,AL ;See if already locked out.
jnz nogo ;If so, do nothing.

; check for data in old queue.
kloop:
mov AH,1 ;See if any data there.
pushf ;(Simulate interrupt.)
call oldkv ;Call original support routine.
jz kfin ;If queue is empty, then done.
mov BX,offset kq ;Point to keyboard queue.
test AX,AX ;See if Ctrl Break.
jnz knbrk ;If not, go on.

; empty queue on break (before enqueueing 0).
mov AX,kqsz ;Queue size.
call mtq ;Empty queue.
sub AX,AX ;Restore AX.
knbrk:

; try to enqueue data.
cli ;Freeze queue.
call enq ;Enqueue code.
sti ;Unfreeze.
jz kfin ;If failure, leave the code in the old queue.
mov AH,0 ;Delete the code from the old queue.
pushf ;(Simulate interrupt.)
call oldkv ;Call original support routine.
jmp short kloop ;See if there is more.

; finished---unlock this routine.
kfin:
mov ink,0

; return.
nogo:
ret

kcopy endp



mtq proc near

assume DS:kbuf,ES:kbuf

; Initialize and empty queue.
; ES:BX points to queue, AX is ring size in words.
; F, AX, DI hit.
cld
lea DI,[BX-6] ;Point to queue size.
shl AX,1 ;Convert size to bytes.
stosw ;Set size.
mov AX,BX ;Set pointers equal.
stosw ;Set front.
stosw ;Set rear.
ret

mtq endp



enq proc near

assume DS:kbuf,ES:kbuf

; Put entry in queue if possible.
; DS/ES:BX points to queue, AX is value to enqueue.
; On return Z reset indicates success, Z set failure.
; F, DI hit.
std ;Set reverse direction.
mov DI,[BX-2] ;Get rear pointer.
cmp DI,BX ;See if pointer will underflow.
stosw ;Store word in queue.
ja enq1 ;If pointer not underflowed go on.
add DI,[BX-6] ;Else, add size of queue in bytes.
enq1:
cmp DI,[BX-4] ;See if queue full.
je enq2 ;If so, return zero set.
mov [BX-2],DI ;Else, update rear pointer.
enq2: ;Zero reset indicates success.
ret

enq endp



deq proc near

assume DS:kbuf,ES:nothing

; Remove entry from queue if possible.
; DS:BX points to queue.
; On return Z reset indicates success and AX contains
; the queue entry, else Z is set and AX is unchanged.
; F, SI hit.
std ;Set reverse direction.
mov SI,[BX-4] ;Get front pointer.
cmp SI,[BX-2] ;See if queue empty.
je deq2 ;If so, return zero set.
cmp SI,BX ;See if pointer will underflow.
lodsw ;Get word from queue.
ja deq1 ;If pointer not underflowed, go on.
add SI,[BX-6] ;Else, add size of queue.
deq1:
mov [BX-4],SI ;Update front pointer.
deq2: ;Zero reset indicates success.
ret

deq endp



pkq proc near

assume DS:kbuf,ES:nothing

; Peek at entry in queue, if any.
; DS:BX points to queue.
; On return Z set if queue empty. Else, AX contains next entry
; to be dequeued. SI, F hit.
mov SI,[BX-4] ;Get front pointer.
cmp SI,[BX-2] ;See if queue empty.
lodsw ;Get entry (if any).
ret

pkq endp



;
; Installation code - all segment registers set.

install:

assume CS:kbuf,DS:kbuf,ES:kbuf,SS:kbuf

; initialize new keyboard queue.
mov BX,offset kq ;Point to queue.
mov AX,kqsz ;Queue size.
call mtq ;Empty queue.

; initialize flag.
mov ink,0 ;Not currently in support routine.

; insert trap in timer interrupt vector.
sub AX,AX
mov ES,AX ;Point to interrupt area.
assume ES:ints
cli ;Disable interrupts during change.
mov AX,int8 ;Save old pointer.
mov oldt,AX
mov AX,int8+2
mov oldt+2,AX
mov int8,offset timer ;Set new interrupt.
mov int8+2,CS

; insert trap in scan interrupt vector.
mov AX,int9 ;Save old pointer.
mov olds,AX
mov AX,int9+2
mov olds+2,AX
mov int9,offset kscan ;Set new interrupt.
mov int9+2,CS

; insert trap in keyboard BIOS interrupt vector.
mov AX,int16 ;Save old pointer.
mov oldk,AX
mov AX,int16+2
mov oldk+2,AX
mov int16,offset ksupp ;Set new interrupt.
mov int16+2,CS
sti ;Interrupts OK now.

; copy data from old queue to new queue.
call kcopy
assume DS:kbuf,ES:kbuf

; tell DOS to keep the traps in memory and exit.
mov DX,offset install ;Amount to keep.
int 27h ;Exit and remain resident.



kbuf ends


end start



  3 Responses to “Category : Utilities for DOS and Windows Machines
Archive   : KBUF_MA.ZIP
Filename : KBUF.ASM

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/