//----------------------------------------------------------------
//	manydots.s
//
//	Here is an example of "structured" programming, in which
//	the main routine is decomposed into three simpler steps.
//	In the first step the program's data is obtained through
//	an "interactive" dialogue between user and computer: two
//	standard functions from the C runtime library are called
//	to perform the asking of a question by the computer, via
//	the 'write()' function, and the listening for a response
//	from the user, via the 'read()' function.  In the second
//	phase, an algorithm is employed to convert the string of
//	decimal numerals (ascii character-codes which were typed 
//	in by the user) into a numerical value (called 'count').
//	In the final step, the value of 'count' is used for loop
//	control to repeat the printing of a 'dot' character.  
//
//	NOTE: The programmer will need to be acquainted with the  
//	prototypes for the two standard C library functions:
//
//	     int write( int fileno, void *buffer, int len );
//	     int read( int fileno, void *buffer, int len ); 
//
//	in order to properly transmit the function-arguments, in
//	the correct order, via the processor's stack. 
//
//	programmer: ALLAN CRUSE
//	written on: 09 SEP 2003
//----------------------------------------------------------------

	# symbolic constants
	.equ		STDIN, 0	# keyboard device-file ID
	.equ		STDOUT, 1	# display device-file ID
	.equ		MAXIN, 5	# maximum length of input

#-----------------------------------------------------------------

	.section	.data
query:	.ascii		"How many dots do you want to see? "
qsize:	.long		. - query	# number of message-bytes
reply:	.space		MAXIN		# storage-space for input
count:	.long		0		# number of dots to print
newln:	.byte		'\n'		# ascii-code for new line
dot:	.byte		'.'		# ascii-code for a period

#-----------------------------------------------------------------

	.section	.text
main:	call		obtain_input	# dialogue with the user
	call		process_data	# turn string into count 
	call		print_output	# show dot 'count' times
	ret				# give control to system

	.globl		main		# make entry-point visible

#-----------------------------------------------------------------
#-----------------------------------------------------------------
obtain_input:
#
# This subroutine uses standard C functions, write() and read(),
# to implement a simple "interactive dialogue" by which the user
# supplies the program-data to be used in the later steps.  
#
	# print a question for the user 
	pushl		qsize		# push argument #3
	pushl		$query		# push argument #2
	pushl		$STDOUT		# push argument #1
	call		write		# call runtime library
	addl		$12, %esp	# discard three arguments
	# obtain a reply from the user
	pushl		$MAXIN		# push argument #3
	pushl		$reply		# push argument #2
	pushl		$STDIN		# push argument #1
	call		read		# call runtime library
	addl		$12, %esp	# discard three arguments
	ret				# back to calling routine

#-----------------------------------------------------------------
process_data:
#
# This subroutine converts the user's input-string to an integer
# which it stores in a global variable named 'count'.  It scans
# the array of character-codes which were typed in by the user,
# stopping if it comes to one which does not represent a decimal
# numeral.  For each valid numeral, the previously accumulated
# total is multiplied by ten (the number base) and then the new
# digit's value is added.  The processor's source-index register
# (%esi) is used as a 'pointer' to the memory-location where the
# the currently scanned character-code was stored.    
#
	# program loop, to process the array of input characters 
	movl		$reply, %esi	# point ESI to input-buffer	
	movl		$0, count	# initialize our accumulator
	movl		$MAXIN, %ecx	# setup our loop-counter
nxnum:	# load the current array-element into register DL
	movb		(%esi), %dl	# fetch next character-code
	incl		%esi		# then advance array-index
	# make sure this character-code represents a valid numeral
	cmpb		$'0', %dl	# character preceeds '0'?
	jl		numxx		# yes, it's not a numeral
	cmpb		$'9', %dl	# character follows '9'?
	jg		numxx		# yes, it's not a numeral
	# convert 8-bit character-code to its 32-bit integer-value
	subb		$'0', %dl	# convert: ascii to number
	movzx		%dl, %edx	# extend number to 32-bits
	# add the new integer-value to ten times the prior count
	imul		$10, count, %eax   # ten times prior count
	addl		%edx, %eax	# plus new numeral's value
	movl		%eax, count	# save the resulting total
	loop		nxnum		# check for further digits 	
numxx:	ret				# back to calling routine
#-----------------------------------------------------------------
#-----------------------------------------------------------------
print_output:
#
# The job of this subroutine is to print the number of dots which
# are indicated by the value of the 'count' variable, and then to
# advance the screen's cursor to a new line before exiting.  Here
# once again the standard C runtime library's 'write()' function 
# is called to product the desired output to the display screen.
#
	cmp		$0, count	# check: count is zero? 
	je		fini		# yes, no dots to print 
nxdot:
	pushl		$1		# argument #3
	pushl		$dot		# argument #2
	pushl		$STDOUT		# argument #1
	call		write		# call runtime library
	addl		$12, %esp	# discard these arguments

	decl		count		# decrement loop-counter
	jnz		nxdot		# nonzeo? show more dots 

fini:	pushl		$1		# argument #3
	pushl		$newln		# argument #2
	pushl		$STDOUT		# argument #1
	call		write		# call runtime library
	addl		$12, %esp	# discard these argument
	ret				# back to calling routine

#-----------------------------------------------------------------