# ----------------------------------------------------------------------
# sIntToDec.s
#	interpret an integer as signed, and convert it to decimal string
# Takes signed int, and the address of a char array.
# Converts the int to a decimal text string representing the int.
# Negative integers will be rendered with a leading '-'.
# Non-negative integers will receive no leading sign character.
# Returns the number of characters in the string (not including NUL).
# ......................................................................
# calling sequence:
#	push string destination address
#	push integer to be converted
#	call	sIntToDec	
#	add 8 to stack pointer
# ......................................................................
# author: David Bozarth - 25 April 2004
# modified 26 April 2004
# ----------------------------------------------------------------------
#
# Stack frame
stkTop = -16	# top-of-stack marker	
intCount = -16	# character count (return value)
blnIsNeg = -12	# if nonzero then integer is negative, else non-negative
strLoc = -8	# local string address variable
intLoc = -4	# local integer variable
basePtr = 0
rtnAddr = 4
intIn = 8	# integer argument
strIn = 12	# string address argument

	.text
	.align 4
	.globl sIntToDec

sIntToDec:
	pushl	%ebp			# save caller's base pointer
	movl	%esp, %ebp		# establish our base pointer
	addl	$stkTop, %esp		# allocate local variables
	pushl	%ebx			# save registers
	pushl	%ecx
	pushl	%edx
	movl	strIn(%ebp), %ebx	# initialize local variables
	movl	%ebx, 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:
	# check & record sign of integer	
	movl	$0, blnIsNeg(%ebp)	# default is non-negative
	movl	intLoc(%ebp), %eax	
	andl	$0x80000000, %eax	# if high-order bit is one
	cmpl	$0, %eax		# .. then we have a negative int
	je	convertInt
	
	decl	blnIsNeg(%ebp)		# .. set marker to 'negative'
	negl	intLoc(%ebp)		# .. & take 2's complement

convertInt:
	# perform the conversion
	pushl	strLoc(%ebp)		# convert unsigned
	pushl	intLoc(%ebp)
	call	uIntToDec		# returns char count
	addl	$8, %esp

	movl	%eax, intCount(%ebp)	# update char count
	cmpl	$0, blnIsNeg(%ebp)	# check if integer is negative
	je	allDone

	# if negative: right-shift string to make space for '-'
	movl	strLoc(%ebp), %ecx	# fetch string base address
	addl	%eax, %ecx		# point to one past end of string
	incl	%ecx			# point to terminator byte
	movb	$0, (%ecx)		# .. & add string terminator
	movl	strLoc(%ebp), %ebx	# fetch string base address
	addl	%eax, %ebx		# point to one past end of string
	movl	$0, %edx		# clear byte holder
shiftLoop:
	cmpl	$0, %eax		# shift characters forward one position
	je	doneShift

	decl	%eax
	decl	%ebx			# new destination address
	decl	%ecx
	movb	(%ebx), %dl		# shift one character right
	movb	%dl, (%ecx)
	jmp	shiftLoop

doneShift:	
	movl	strLoc(%ebp), %ebx	# fetch string base address
	movb	$'-', (%ebx)		# insert 'negative sign'
	
allDone:
	movl	intCount(%ebp), %eax	# return #chars in new string
	popl	%edx			# restore registers
	popl	%ecx
	popl	%ebx
	movl	%ebp, %esp		# restore stack pointer
	popl	%ebp			# restore caller's base pointer
	ret
