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
|
|||
|
|