Purpose:
accept keyboard input and print messages on the printer
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
;eg8-6.asm
;Purpose: accept keyboard input and print messages on the printer
;* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* * * *
.model tiny
;-------------------------------------------------------------------------
.stack
;-------------------------------------------------------------------------
.data
old_ip09 dw ?
old_cs09 dw ?
old_ip0f dw ?
old_cs0f dw ?
count dw ?
buffer db 20h dup(' ')
buf_p dw ?
start_msg db 0ah, 0dh, 'RUN', 0ah, 0dh, '$'
end_msg db 0ah, 0dh, 'END', 0ah, 0dh, '$'
full_msg db 0ah, 0dh, 'Buffer full!$'
;-------------------------------------------------------------------------
.code
; Main program
main proc far
start:
mov ax, @data ;ds<=data segment
mov ds, ax
; initialize
lea ax, buffer ;buf_p<=buffer address
mov buf_p, ax
mov count, 0 ;count<=0
; save old interrupt 09h
mov al, 09h ;al<=vector#
mov ah, 35h ;to get interrupt vector
int 21h ;call DOS
mov old_cs09, es ;save registers for restore
mov old_ip09, bx
push ds ;save ds
;set new interrupt 09h
lea dx, kbdint ;dx<=offset of procedure kbdint
mov ax, seg kbdint ;ax<=segment of procedure kbdint
mov ds, ax ;ds<=ax
mov al, 09h ;al<=intrrupt number
mov ah, 25h ;to set interrupt vector
int 21h ;call DOS
pop ds ;restore ds
;set keyboard interrupt mask bits
in al, 21h
and al, 0fdh
out 21h, al
;save old interrupt 0fh
mov al, 0fh ;al<=vector#
mov ah, 35h ;to get interrupt vector
int 21h ;call DOS
mov old_cs0f, es ;save registers for restore
mov old_ip0f, bx
push ds ;save ds
;set new interrupt 0fh
lea dx, prtint ;dx<=offset of procedure prtint
mov ax, seg prtint ;ax<=segment of procedure prtint
mov ds, ax ;ds<=ax
mov al, 0fh ;al<=vector#
mov ah, 25h ;to set interrupt vector
int 21h ;call DOS
pop ds ;restore ds
mov ah, 09h ;print start message
lea dx, start_msg
int 21h
sti
mov di,20000 ;main process
mainp: mov si,30000
mainp1:dec si
jnz mainp1
dec di
jnz mainp
mov ah, 09h ;print end msg of main process
lea dx, end_msg
int 21h
cli
;restore old interrupt 09h
push ds ;save ds
mov dx, old_ip09 ;ds:dx<=old handler address
mov ax, old_cs09
mov ds, ax
mov al, 09h ;al<=vector#
mov ah, 25h ;to restore interrupt vector
int 21h ;call DOS
pop ds ;restore ds
; restore old interrupt 0fh
push ds ;save ds
mov dx, old_ip0f ;ds:dx<=old address
mov ax, old_cs0f
mov ds, ax
mov al, 0fh ;al<=vector#
mov ah, 25h ;to restore interrupt
int 21h ;call DOS
pop ds ;restore ds
; enable keyboard interrupt
in al, 21h
and al, 0fdh
; enable keyboard interrupt
in al, 21h
and al, 0fdh
out 21h, al
sti
mov ax, 4c00h
int 21h
main endp
;-----------------------------------------------------
; Interrupt Handler kbd
; Purpose: fill buffer until full when substituted for interrupt
09h
kbdint proc near
push ax ; save registers
push
bx
cld
;direction: forward
in al, 60h ;read a character
push ax ;save it
in al, 61h ;get the control port
mov ah, al ;save the value in ah
or al, 80h ;reset bits for kbd
out 61h, al ;send out
xchg ah, al ;restore control value
out 61h, al ;kdb has been reset
pop ax
;restore scan code
test al, 80h ;press or release?
jnz return1 ;ignore when release
mov bx, buf_p ;bx<=buffer
pointer
mov [bx], al ;store in buffer
call display_hex ;display in hex
inc bx ;move pointer
inc count ;count characters
mov buf_p, bx ;save the pointer
check:
cmp count, 20h ;judge whether full
jb return1
in al, 21h
or al, 02 ;mask kdb bits
and al, 7fh ;enable prt bits
out 21h, al
call init_prt ;initiate printer
return1:
cli
mov al, 20h ;end of interrupt
out 20h, al
;restore registers
pop bx
pop ax
iret ;interrupt return
kbdint endp
;------------------------------------------------------------------------
; Interrupt Handler prtint
; Purpose: print characters when substituted for interrupt 0fh
prtint proc near
push ax ;save registers
push bx
push dx
mov bx, buf_p ;bx<=buffer
pointer
mov al, [bx] ;get from buffer
mov dx, 378h ;printer data port
out dx, al ;output a character
push ax ;save ax
mov dx, 37ah ;printer control port
mov al, 1dh ;al<=control code
out dx, al ;send out
jmp $+2 ;slight delay
mov al, 1ch ;al<=control code
out dx, al ;send out
pop ax ;restore ax
inc bx ;move pointer
mov buf_p, bx ;save the pointer
cmp al, 0ah ;end of message?
jnz return2
in al, 21h ;disable printer
or al, 80h ; interrupt
out 21h, al
return2:
mov al, 20h ;end of interrupt
out 20h, al
pop dx ;restore
registers
pop bx
pop ax
iret ;interrupt return
prtint endp
;------------------------------------------------------------------------
; Procedure init_prt
init_prt proc near
push ax ;save registers
push bx
push dx
cli
lea bx, full_msg ;bx<=offset of full_msg
mov buf_p, bx ;save full_msg address
mov dx, 378h ;printer data port
mov al, 0dh ;CR
out dx, al ;output a character
mov dx, 37ah ;printer
control port
mov al, 1dh ;al<=control code
out dx, al ;send out
jmp $+2 ;slight delay
mov al, 1ch ;al<=control code
out dx, al ;send out
pop dx ;restore
registers
pop bx
pop ax
ret
init_prt endp
;------------------------------------------------------------------------
display_hex proc near ;display
char with hex
push ax
push cx
push dx
mov ch, 2 ;number of digits
mov cl, 4
nextb:
rol al, cl ;highest of bits to lowest
push ax
mov dl, al
and dl, 0fh ;mask off left digit
or dl, 30h ;convert to ASCII
cmp dl, 3ah
jl dispit
add dl,7h ;digit is A to F
dispit:
mov ah, 2 ;display character
int 21h
pop ax
dec ch ;done 2 digits?
jnz nextb ;not yet
mov ah, 2
mov dl,',' ;display ','
int 21h
pop dx
pop cx
pop ax
ret ;return from display_hex
display_hex endp
;------------------------------------------------------------------------
end start