# ---------------------------------------------------------------
# readStr.s
#	store a string from the keyboard, to a specified location
# Takes 2 arguments: address of char buffer, size of buffer.
# Reads chars from standard input and stores them in the buffer.
# Flushes the buffer. Returns number of chars stored.
# ...............................................................
# calling sequence:
#	push integer n_chars to store
#	push address where string to be stored
#	call	readStr
#	add 8 to stack pointer
# ...............................................................
# adapted from Robert G. Plantz - 20 March 2000
# adapted by David Bozarth - 18 April 2004
# modified 30 April 2004
# ---------------------------------------------------------------
STDIN = 0
STDOUT = 1
WORD = -4

# Stack frame
stkTop = basePtr
basePtr = 0
rtnAddr = basePtr - WORD
strPtr = rtnAddr - WORD		# string destination address passed as argument
intSize = strPtr - WORD		# n_chars to store

	.text
	.align	4
	.globl	readStr

readStr:
	pushl	%ebp			# save caller's base pointer
	movl	%esp, %ebp		# establish our base pointer
	addl	$stkTop, %esp		# allocate local variable
	pushl	%ebx			# save registers - using read()
	pushl	%ecx
	pushl	%edx

	xorl	%ebx, %ebx		# reset character count
	# prime the buffer		
	movl	strPtr(%ebp), %eax	# address of next byte in buffer
	pushl	$1			# read a byte
	pushl	%eax
	pushl	$STDIN
	call	read
	addl	$12, %esp		# fix stack
readLoop:
	movl	strPtr(%ebp), %eax	# address of next byte in buffer
	cmpb	$'\n', (%eax)		# if newline char found in buffer
	je	eol			# .. then exit loop

	incl	%ebx			# increment char count
	cmpl	intSize(%ebp), %ebx	# if excess chars were entered
	ja	nextAddr		# .. then overwrite last char
	
	incl	strPtr(%ebp)		# increment pointer
nextAddr:	
	movl	strPtr(%ebp), %eax	# address of next byte in buffer
	pushl	$1			# read a byte
	pushl	%eax
	pushl	$STDIN
	call	read
	addl	$12, %esp		# fix stack
	jmp	readLoop
	
eol:
	movb	$0, (%eax)		# replace newline with nil
	movl	%ebx, %eax		# return # chars written		
	popl	%edx			# restore registers
	popl	%ecx
	popl	%ebx
	movl	%ebp, %esp		# restore stack pointer
	popl	%ebp			# restore caller's base pointer
	ret
