# ----------------------------------------------------------------------
# uIntToDec.s
#	convert an unsigned integer to a decimal string
# Takes an unsigned int, and the address of a char array.
# Converts the int to a decimal text string representing the int.
# Returns the number of characters in the string (not incl. terminator).
# ......................................................................
# calling sequence:
#	push the destination address of string
#	push an integer
#	call	uIntToDec
#	add 8 to stack pointer
# ......................................................................
# author: David Bozarth - 24 April 2004
# modified 26 April 2004
# ----------------------------------------------------------------------
#
# Stack frame
stkTop = -28	# top-of-stack marker
intRem = -28	# remainder
intLeft = -24	# left string position pointer
intRight = -20	# right string position pointer
intCount = -16	# character count
charOne = -12	# single character
strLoc = -8	# local copy of string address argument
intLoc = -4	# local copy of integer argument
basePtr = 0
rtnAddr = 4
intIn = 8	# integer passed as argument
strIn = 12	# string address passed as argument

	.data
byTen:
	.long	10			# divisor for decimal conversion
	
	.text
	.align 4
	.globl uIntToDec

uIntToDec:
	pushl	%ebp			# save caller's base pointer
	movl	%esp, %ebp		# establish our base pointer
	addl	$stkTop, %esp		# allocate stack variables
	pushl	%ebx			# save registers
	pushl	%ecx
	pushl	%edx
	movl	strIn(%ebp), %eax	# initialize local variables
	movl	%eax, strLoc(%ebp)
	movl	intIn(%ebp), %eax
	movl	%eax, intLoc(%ebp)

	movl	$0, intCount(%ebp)	# reset character count
	cmpl	$0, intLoc(%ebp)	# detect & process zero value
	jne	nonZero			

	movl	strLoc(%ebp), %ebx	# fetch string base adx
	movb	$'0', (%ebx)		# first char = '0'
	incl	intCount(%ebp)		# increment character count
	incl	%ebx
	movb	$0, (%ebx)		# terminate string
	jmp	allDone				

nonZero:	
	movl	$0, intLeft(%ebp)	# reset position pointers
	movl	$0, intRight(%ebp)
convertLoop:
	movl	intLoc(%ebp), %eax	# begin setup for divide operation
	cmpl	$0, %eax		# detect end of conversion		
	je	doneConvert
	
	movl	$0, %edx		# finish setup for divide operation
	divl	byTen
	orl	$0x30, %edx		# convert remainder to ascii
	movl	strLoc(%ebp), %ebx	# fetch string base address
	addl	intRight(%ebp), %ebx	# point to next available string posn
	movb	%dl, (%ebx)		# .. and place next decimal digit
	movl	%eax, intLoc(%ebp)	# quotient becomes next dividend
	incl	intRight(%ebp)		# increment string position pointer
	jmp	convertLoop	

doneConvert:
	incl	%ebx			# point to one past end of string
	movb	$0, (%ebx)		# .. apply terminator
	movl	intRight(%ebp), %ecx	# update character count
	movl	%ecx, intCount(%ebp)	# .. with final (Right) position index
invertLoop:		
	movl	intLeft(%ebp), %eax	# set up Left pointer in register
	cmpl	%eax, %ecx		# while Left < Right, continue
	jbe	allDone			# .. else done

	# swap 2 characters in palindrome-fashion
	movl	strLoc(%ebp), %ebx	# fetch string base adx
	addl	%ebx, %eax		# .. add to Left index
	movb	(%eax), %dl		# swap character out ..
	movb	%dl, charOne(%ebp)	# .. to temp holder
	decl	%ecx			# decrement ..
	decl	intRight(%ebp)		# .. Right pointer
	addl	%ebx, %ecx		# add string base adx to Right index
	movb	(%ecx), %dl		# replace swapped-out char ..
	movb	%dl, (%eax)		# .. with new char
	incl	%eax			# increment ..
	incl	intLeft(%ebp)		# .. Left pointer
	movb	charOne(%ebp), %dl	# move swapped-out char ..
	movb	%dl, (%ecx)		# .. to its new position
	movl	intRight(%ebp), %ecx	# set up Right pointer in register
	jmp	invertLoop	
		
allDone:
	movl	intCount(%ebp), %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
