i know this looks like alot of code for this forum but i dont know where the problem is. The problem is that when the user selects "E" to enter text everytime a key is pressed it writes it twice.....WHY?!?!

Code:
.model small
.stack	100h

.data	
message db " Adrians Encryption Program",0dh,0ah,0dh,0ah,'$'


buff	DB	2000 DUP(0) 
cashe   DB      80 DUP(?)   
finval	DW	?	   
temp	DB	?	   

menu	DB	"------------------------------------- ",0dh,0ah
	DB	" ",0dh,0ah
	DB	" Enter E to Enter text text",0dh,0ah
	DB	" Enter D to Display text",0dh,0ah
	DB	" Enter C to Clear the screen",0dh,0ah
	DB	" Enter L to deLete one character",0dh,0ah
	DB	" Enter Q to Quit",0dh,0ah
	DB	" Enter N to eNcrypt",0dh,0ah
	DB	" Enter R to decRypt",0dh,0ah
	DB	" ",0dh,0ah
	DB	" Type in a command",0Dh,0Ah
	DB	" ",0dh,0ah
	DB	"-------------------------------------",0dh,0ah
	DB	" ",0dh,0ah
	DB	" Press Escape to return to this menu",0dh,0ah,'$'

delfrom	DB	"Enter character position to delete from",0dh,0Ah,'$'
delto	DB	"Enter number of characters to delete",0dh,0Ah,'$'

runout	DB	"Buffer Overrun error!",0dh,0ah,'$'
endline	EQU	79	;its the end of the line!
perline	EQU	80	;number of characters on a line.


.code


mdisplay macro string
	push	ax
	push	dx
	mov	ah,9
	mov	dx,offset string
	int	21h
	pop	dx
	pop	ax
endm



main	proc

	mov	ax,@data
	mov	ds,ax

	mov     ah,9
	mov     dx,offset message
	int     21h

	.repeat

start:	mdisplay  menu		;display the menu.	
	call	readchr		;returns with key character in al.
	
	.if AL=='e' 
	  call Entertx
	  jmp start
	.endif  
	.if AL=='d' 
	  call display
	  jmp start
	.endif  
	.if AL=='c' 
	  call clear
	  jmp start
	.endif  
	.if AL=='l' 
	  call deltx
	  jmp start
	.endif  

	
term:	
	.until(AL=='q')


	mov	ax,4c00h
	int	21h
	ret
main	endp


readchr   proc near
	mov  ah,0
	int  16h
	ret
readchr   endp



readecho  proc near
	mov  ah,1
	int  21h
	ret
readecho  endp

; Displays the character in AL reg.                   


dispchar	proc near
	push	ax
	push	bx
	mov	bx,0	
	mov	ah,0Eh	
	int	10h	
	pop	bx
	pop	ax		
	ret
dispchar  endp	


newline	proc  near
	push	ax
	push	bx
	mov	al,0dh
	call	dispchar
	mov	al,0ah
	call	dispchar
	pop	bx
	pop	ax
	ret
newline  endp




entertx	proc near
	mov	bx,offset buff		;get buffer base address.
	mov	cl,0			;set up character pointer.
.repeat
	call	readecho		;get a character from KB with echo.
	mov	byte ptr [bx],al	;place it into the buffer
	call	dispchar			;send it to the screen.
	inc	cl			;bump up the line char pointer.
	inc	bx			;bump up pointer to nxt one
	.if     bx==07cfh		;compare with last elemnt
	  mov	al,1bh			;if it is - get ESC char
	mdisplay runout			;diaplay buffer overrun mess.
	.endif
	.if	cl==endline		;is it the end of the line?
		call  newline		;issue a new line sequence.
	.endif
.until	al==1bh				;exit if ESC character entered.
	ret
entertx	endp







display	proc near
	
	call	newline
			
				;it gets the number of lines to display.
;	call	readecho	;get the number of lines to display.
;	and	al,0fh		;convert ascii to decimal.

	mov	ch,al		;store the number of lines to display.	
	mov	ax,0050h	;get the 80 value.
	mul	ch		;multiply no of lines by 80 to get char's
	mov	finval,ax	;and store it for later.
	mov	bx,offset buff	;get buffer origin.
	mov	cl,0		;initialise character counter.
	.repeat
	mov	al,byte ptr[bx]	;get current character gtom buffer.
	call	dispchar	;send it to the screen.
	inc	bx		;bump up to next character
	inc	cl		;bump up character counter value
	.if	cl==endline	;check to see if last char of line?
	mov	cl,0		;initialise character countr again.	
	call	newline		;if end of line issue CR+LF.
	.endif
	.until (bx==finval) ;until last character of last line.			
  
	.repeat
   	call	readchr		;get user action (wait for ESC).
	.until (al==1bh)	;will wait in this loop for an ESC.
	ret
display	endp


clear	proc near
	push	ax
	xor	ax,ax
	.repeat
	call	newline
	inc	al
	.until (al == 24)
	pop	ax
	ret
clear	endp



deltx	proc near

	ret
deltx	endp


	end	main