159 lines
3.4 KiB
Plaintext
159 lines
3.4 KiB
Plaintext
;
|
||
; buf128: a 128 character type-ahead buffer for the IBM-PC
|
||
;
|
||
; This program works by intercepting the calls to the BIOS
|
||
; interrupt routines at 9 for the keystroke interrupts and
|
||
; 16H for the program requests
|
||
; Everything is kept in CS.
|
||
;
|
||
; Caution: buf128 must be linked with the -A option, e.g.
|
||
; BIND B:BUF128 -A
|
||
|
||
cseg
|
||
public main_,key_int,request,buffer,head,tail
|
||
|
||
KEYINT: equ 24H ; int 9 vector offset
|
||
REQINT: equ 58H ; int 16H vector offset
|
||
B_HEAD: equ 1AH ; offset to BUFFER_HEAD
|
||
B_TAIL: equ 1CH ; offset to BUFFER_TAIL
|
||
KB_FLAG: equ 17H ; offset to KB_FLAG
|
||
|
||
main_: jmp init_code
|
||
;
|
||
buffer: dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
dw 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
|
||
|
||
head: dw buffer
|
||
tail: dw buffer
|
||
|
||
;
|
||
; the keystroke interrupt routine. Interrcept the key interrupt, run
|
||
; it through the standard key input routine, and remove it from the buffer.
|
||
;
|
||
|
||
key_int:
|
||
cli
|
||
pushf ; simulate an interrupt
|
||
;
|
||
; long call to F000:E987
|
||
;
|
||
db 9AH
|
||
dw 0E987H
|
||
dw 0F000H
|
||
;
|
||
push bx
|
||
push es
|
||
mov bx,40H ; BIOS data segment
|
||
mov es,bx
|
||
mov bx, es:[B_HEAD] ; pointer to datum
|
||
cmp bx, es:[B_TAIL] ; test for character
|
||
je k_esbx
|
||
mov es:[B_TAIL], bx ; clear the buffer
|
||
mov bx, es:[bx]
|
||
push si
|
||
mov si, cs:tail
|
||
push si ; save tail value
|
||
add si,2 ; test for full
|
||
cmp si, offset buffer+256
|
||
jb k_over1
|
||
mov si, offset buffer
|
||
k_over1:
|
||
cmp si, cs:head
|
||
pop si
|
||
je k_siesbx ; jump if buffer full
|
||
mov cs:[si], bx ; store the character
|
||
add si,2
|
||
cmp si, offset buffer+256
|
||
jb k_over2
|
||
mov si, offset buffer
|
||
k_over2:
|
||
mov cs:tail, si
|
||
k_siesbx:
|
||
pop si
|
||
k_esbx:
|
||
pop es ; no character, return
|
||
pop bx
|
||
iret
|
||
|
||
;
|
||
; The request interrupt routine.
|
||
;
|
||
; simulate the BIOS routine
|
||
; ah = 0 read next char
|
||
; ah = 1 set Z flag on character status, ZF=1 if no char
|
||
; ZF=0 and AX = char if char ready
|
||
; ah = 2 shift status
|
||
|
||
|
||
request:
|
||
sti
|
||
or ah,ah
|
||
jz do_read
|
||
dec ah
|
||
jz do_stat
|
||
dec ah
|
||
jz do_shift
|
||
iret
|
||
|
||
do_read: ; return the next character
|
||
sti
|
||
nop
|
||
cli
|
||
mov ax,cs:head
|
||
cmp ax,cs:tail
|
||
je do_read ; loop until a character
|
||
push bx
|
||
mov bx,ax
|
||
mov ax, cs:[bx] ; ax gets the character
|
||
add bx,2
|
||
cmp bx, offset buffer+256
|
||
jb r_over
|
||
mov bx, offset buffer
|
||
r_over:
|
||
cmp bx, cs:tail
|
||
mov cs:head, bx ; new head
|
||
pop bx
|
||
iret
|
||
|
||
do_stat: ; return key status
|
||
cli
|
||
push bx
|
||
mov bx,cs:head
|
||
cmp bx,cs:tail
|
||
mov ax,cs:[bx]
|
||
pop bx
|
||
sti
|
||
lret 2 ; throw out the flags
|
||
|
||
do_shift:
|
||
push es
|
||
mov ax,40H ; BIOS data segment
|
||
mov es,ax
|
||
mov al, es:[KB_FLAG]
|
||
pop es
|
||
iret
|
||
|
||
init_code: cli ; turn off interrupts for now
|
||
mov ax,0
|
||
mov es,ax ; segment base for vectors
|
||
mov es:[KEYINT], offset key_int
|
||
mov es:[KEYINT+2], cs
|
||
mov es:[REQINT], offset request
|
||
mov es:[REQINT+2], cs
|
||
mov cs:head, offset buffer
|
||
mov cs:tail, offset buffer
|
||
sti
|
||
mov ds:byte[1], 27H ; change PCB terminate to resident
|
||
push ds
|
||
mov dx,0
|
||
push dx
|
||
mov dx, offset init_code+100H
|
||
lret ; long return to the int 27H
|
||
end
|
||
|