# --------------------------------------------------------------------
# showStats.s
#	Find & display the sum and average of a list of integers.
# Takes 2 arguments: address of int array, number of ints in array.
# 1 May 2004: Now calculates & displays FIR filter average.
# Returns void.
# ....................................................................
# calling sequence:
#	push number_of_ints (array_size)
#	push base_address of int array
#	call	showStats
#	add 8 to stack pointer
# ....................................................................
# author: David Bozarth - 30 April 2004
# modified 1 May 2004
# --------------------------------------------------------------------
WORD = -4
LIST = 10
WINDOW = 3
#
# Stack frame
stkTop = intWin			# top-of-stack marker
intWin = intFirList + WORD	# window size for FIR filter
intFirList = intSum + WORD * LIST	# FIR filter output array
intSum = intAvg + WORD		# calculated_sum local variable
intAvg = basePtr + WORD		# calculated_average local variable
basePtr = 0
rtnAddr = basePtr - WORD
intPtrIn = rtnAddr - WORD	# int_array_base_address argument
intSize = intPtrIn - WORD	# number_of_integers (array size) argument
	
	.data
strSum:
	.string "Sum = "
strAvg:
	.string "Average = "
strFir:
	.string "Lo-pass filter:\n"
strSpace:
	.string " "
strNewl:
	.string "\n"
	
	.text
	.align	4
	.globl	showStats

showStats:
	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

	# initialize
	movl	$WINDOW, intWin(%ebp)	# window size for FIR filter
	
	# find the sum
	movl	intSize(%ebp), %ecx	# array size (n_ints)
	pushl	%ecx
	movl	intPtrIn(%ebp), %ebx	# array base address
	pushl	%ebx
	call	sumList			# sum -> eax
	addl	$8, %esp
	movl	%eax, intSum(%ebp)	# store sum locally

	# find the average
	pushl	intSize(%ebp)		# push divisor
	movl	$0x80000000, %ecx
	andl	%eax, %ecx
	cmpl	$0, %ecx		# if sum is negative
	je	notNeg			# .. then extend the sign

	negl	%eax
	pushl	%eax			# lo word
	pushl	$-1			# hi word
	jmp	doneNeg
	
notNeg:	
	pushl	%eax			# lo word
	pushl	$0			# hi word
doneNeg:
	call	divInt
	addl	$12, %esp
	movl	%eax, intAvg(%ebp)	# store quotient locally
	
	# display stats
	pushl	$strNewl		# send newline to display	
	call	writeStr
	addl	$4, %esp
	pushl	$strSum			# display sum
	call	writeStr
	addl	$4, %esp
	pushl	intSum(%ebp)
	call	putDec
	addl	$4, %esp
	pushl	$strNewl		# send newline to display	
	call	writeStr
	addl	$4, %esp
	pushl	$strAvg			# display average
	call	writeStr
	addl	$4, %esp
	pushl	intAvg(%ebp)
	call	putDec
	addl	$4, %esp
	pushl	$strNewl		# send newline to display	
	call	writeStr
	addl	$4, %esp

	# FIR filter
	pushl	intWin(%ebp)		# window size
	pushl	intSize(%ebp)		# number of list elements
	leal	intFirList(%ebp), %ebx
	pushl	%ebx
	pushl	intPtrIn(%ebp)
	call	doFir
	addl	$16, %esp
	pushl	# --------------------------------------------------------------------
# showStats.s
#	Find & display the sum and average of a list of integers.
# Takes 2 arguments: address of int array, number of ints in array.
# 1 May 2004: Now calculates & displays FIR filter average.
# Returns void.
# ....................................................................
# calling sequence:
#	push number_of_ints (array_size)
#	push base_address of int array
#	call	showStats
#	add 8 to stack pointer
# ....................................................................
# author: David Bozarth - 30 April 2004
# modified 1 May 2004
# --------------------------------------------------------------------
WORD = -4
LIST = 10
WINDOW = 3
#
# Stack frame
stkTop = intWin			# top-of-stack marker
intWin = intFirList + WORD	# window size for FIR filter
intFirList = intSum + WORD * LIST	# FIR filter output array
intSum = intAvg + WORD		# calculated_sum local variable
intAvg = basePtr + WORD		# calculated_average local variable
basePtr = 0
rtnAddr = basePtr - WORD
intPtrIn = rtnAddr - WORD	# int_array_base_address argument
intSize = intPtrIn - WORD	# number_of_integers (array size) argument
	
	.data
strSum:
	.string "Sum = "
strAvg:
	.string "Average = "
strFir:
	.string "Lo-pass filter:\n"
strSpace:
	.string " "
strNewl:
	.string "\n"
	
	.text
	.align	4
	.globl	showStats

showStats:
	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

	# initialize
	movl	$WINDOW, intWin(%ebp)	# window size for FIR filter
	
	# find the sum
	movl	intSize(%ebp), %ecx	# array size (n_ints)
	pushl	%ecx
	movl	intPtrIn(%ebp), %ebx	# array base address
	pushl	%ebx
	call	sumList			# sum -> eax
	addl	$8, %esp
	movl	%eax, intSum(%ebp)	# store sum locally

	# find the average
	pushl	intSize(%ebp)		# push divisor
	movl	$0x80000000, %ecx
	andl	%eax, %ecx
	cmpl	$0, %ecx		# if sum is negative
	je	notNeg			# .. then extend the sign

	negl	%eax
	pushl	%eax			# lo word
	pushl	$-1			# hi word
	jmp	doneNeg
	
notNeg:	
	pushl	%eax			# lo word
	pushl	$0			# hi word
doneNeg:
	call	divInt
	addl	$12, %esp
	movl	%eax, intAvg(%ebp)	# store quotient locally
	
	# display stats
	pushl	$strNewl		# send newline to display	
	call	writeStr
	addl	$4, %esp
	pushl	$strSum			# display sum
	call	writeStr
	addl	$4, %esp
	pushl	intSum(%ebp)
	call	putDec
	addl	$4, %esp
	pushl	$strNewl		# send newline to display	
	call	writeStr
	addl	$4, %esp
	pushl	$strAvg			# display average
	call	writeStr
	addl	$4, %esp
	pushl	intAvg(%ebp)
	call	putDec
	addl	$4, %esp
	pushl	$strNewl		# send newline to display	
	call	writeStr
	addl	$4, %esp

	# FIR filter
	pushl	intWin(%ebp)		# window size
	pushl	intSize(%ebp)		# number of list elements
	leal	intFirList(%ebp), %ebx
	pushl	%ebx
	pushl	intPtrIn(%ebp)
	call	doFir
	addl	$16, %esp
	pushl	$strNewl	
	call	writeStr		# send newline to display
	addl	$4, %esp
	pushl	$strFir	
	call	writeStr		# send data label to display
	addl	$4, %esp
	pushl	$strNewl	
	call	writeStr		# send newline to display
	addl	$4, %esp
	pushl	$strSpace		# delimiter string for display
	pushl	intSize(%ebp)		# list count to display function
	pushl	%ebx			# address of filtered data
	call	showList		# display list of integers
	addl	$12, %esp	
	pushl	$strNewl	
	call	writeStr		# send newline to display
	addl	$4, %esp
				
allDone:
	popl	%edx			# restore registers
	popl	%ecx			# restore registers
	popl	%ebx
	movl	%ebp, %esp		# restore stack pointer
	popl	%ebp			# restore caller's base pointer
	ret
