TITLE KBPRT_INT -- EXAMPLE 8 - 2
;Keyboard input and print a message on the printer
;*************************************************
dseg	  segment	     ;defint data segment		
addr_point  dw  ?
count	    dw  ?
buffer	    db  20h dup(' ')
prompt	    db  'please enter the characters :'
	    db  0dh,0ah,'$'
message	    db  'buffer overflow',0dh,0ah
save_ip9    dw  ?
save_cs9    dw  ?
save_ipf    dw  ?
save_csf    dw  ?
dseg	  ends
;*************************************************
cseg	 segment	     ;define code segment
;-------------------------------------------------
main proc far	 	     ;main part of program
	assume  cs:cseg,  ds:dseg
start:
	push	ds	  ;set up stack for return
	sub	ax,ax
	push	ax	

	mov	ax,dseg	  ;set DS to dseg segment
	mov	ds,ax	  
  
	mov	ax,offset buffer  ;initialize
	mov	addr_point,ax
	mov	count,0

	mov	al,09h		   ;save interrupt
	mov	ah,35h		   ;  vector of
	int	21h		   ;   type 09h
	mov	save_ip9,bx
	mov	save_cs9,es

	mov	dx,offset kbint	   ;set interrupt
	push	ds		   ; vector of 09
	mov	ax,seg kbint
	mov	ds,ax
	mov	al,09h
	mov	ah,25h
	int 	21h
	pop	ds

	mov	al,0fh		   ;save interrupt
	mov	ah,35h		   ;  vector of
	int	21h		   ;   type 0Fh
	mov	save_ipf,bx
	mov	save_csf,es
	cli
	mov	dx,offset prtint   ;set interrupt
	push	ds		   ; vector of 0Fh
	mov	ax,seg prtint
	mov	ds,ax
	mov	al,0fh
	mov	ah,25h
	int	21h
	pop	ds

	in	al,21h		;set KB interrupt
	and	al,0fdh		;  mask bit
	out	21h,al

	mov	ah,09h		;print prompt mess.
	lea	dx,prompt
	int	21h

	sti
	mov	di,2000
mainp:	mov	si,3000
mainp1:	dec	si
	jnz	mainp1
	dec	di
	jnz	mainp

	mov	ah,2		;'$' means end
	mov	dl,'$'		; of main process
	int	21h

retn:	cli
	push	ds
	mov	dx,save_ip9	;restore interrupt
	mov	ax,save_cs9	; vector of 09h
	mov	ds,ax
	mov	al,09h
	mov	ah,25h
	int	21h
	pop	ds

	push	ds
	mov	dx,save_ipf	;restore interrupt
	mov	ax,save_csf	; vector of 0Fh
	mov	ds,ax
	mov	al,0fh
	mov	ah,25h
	int	21h
	pop	ds

	in	al,21h		;enable KB interrupt
	and	al,0fdh
	out	21h,al

	sti
	ret			;return DOS
main	endp
;--------------------------------------------------
kbint proc near
	push	ax		;save the working
	push	bx		;  register
	cld			;forward direction

	in	al,60h		;read in the char.
	push	ax		;save it
	in	al,61h		;get the control port
	mov	ah,al		;save value
	or	al,80h		;reset bit for kbd.
	out	61h,al		;
	xchg	ah,al		;get back org control
	out	61h,al		;KB has been reset
	pop	ax		;recover scan code

	test 	al,80h	  	;is press or release code?
	jnz	cont	  	;don't process release code

	mov	bx,addr_point	;buffer point
	mov	[bx],al		;store in buffer
	call	disp		;display scan code
	inc	bx		;inc address
	inc	count		;count characters
	mov	addr_point,bx	;save the point

check:	cmp	count,32	;is buffer overflow? 
	jb	cont		;no,return
	in	al,21h		;yes, then
	or	al,02		; mask KB bit
	and	al,7fh		;  enable PRT bit
	out	21h,al
	call	intip		;initialize printer

cont:	cli
	mov	al,20h		;end of interrupt
	out	20h,al
	pop	bx		;restore register
	pop	ax
	iret
kbint	endp
;--------------------------------------------------
intip proc near
	push	ax		;save working reg.
	push	bx
	push	dx
	cli
	mov	bx,offset message 
	mov	addr_point,bx	;save addr of mess

	mov	dx,378h	        ;start printer adapter
	mov	al,0dh
	out	dx,al

	mov	dx,37ah		;send a strobe to
	mov	al,1dh		;  control byte
	out	dx,al
	jmp	$+2
	mov	al,1ch
	out	dx,al

	pop	dx		;restore registers
	pop	bx
	pop	ax
	ret
intip endp
;--------------------------------------------------
prtint proc near
	push	ax		;save registers
	push	bx
	push	dx

	mov	bx,addr_point	;message addr.in BX
	mov	al,[bx]		

	mov	dx,378h		;printer data port
	out	dx,al		;output a character

	push	ax
	mov	dx,37ah		;PRT control port
	mov	al,1dh		;send control code
	out	dx,al		;  and strobe
	jmp	$+2
	mov	al,1ch
	out	dx,al
	pop	ax

	inc	bx		;next character addr.
	mov	addr_point,bx	;save it
	cmp	al,0ah		;end of message ?
	jnz	return		;no,return

	in	al,21h		;disnable printer
	or	al,80h		;  interrupt
	out	21h,al

return:	mov	al,20h		;end of interrupt
	out	20h,al
	pop	dx
	pop	bx
	pop	ax
	iret			;interrupt return
prtint	endp
;---------------------------------------------------
disp    proc near		;display with hex
	push	ax
	push	cx
	push	dx
	mov	ch,2		;number of digits
	mov	cl,4
nextb:	rol	al,cl		;highest 4 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 digit?
	jnz	nextb		;not yet
	mov	ah,2
	mov	dl,','		;display','
	int	21h
	pop	dx
	pop	cx
	pop	ax
	ret			;return from disp
disp	endp
;--------------------------------------------------
cseg 	ends
	end	start		;end assembly
