summaryrefslogblamecommitdiff
path: root/HW3/CS424_HW3_Carpenter_Adam.asm
blob: 7e0c15ba7e9fce361237b9bcf9fb2bbac5bef9c4 (plain) (tree)









































































































































































































































































                                                                                                           
# CSCI 424, Homework 3
# Adam Carpenter - username acarpent - acarpenter@email.wm.edu
	.text
	.globl	main
main:
	la	$s0, array1 		# create array
	la	$t0, ($s0) 		# create pointer
	add	$s1, $zero, $zero 	# represents n-1 of array
	la 	$a0, startMsg 
	jal	Print_string 		# print message
InputLoop: # Take in only positive integers and store them in array until user enters -1
	la 	$a0, prompt
	jal 	Print_string 		# Print prompt
	jal 	Read_integer 		# read integer
	beq	$v0, -1, isArrayEmpty 	# Exit if user enters -1
	sw	$v0, ($t0) 		# Store integer
	add	$t0, $t0, 4 		# increment pointer
	add	$s1, $s1, 1 		# increment counter
	j 	InputLoop
isArrayEmpty: # If the user only enters -1, there is nothing to sort
	bne 	$t0, $s0, arrayNotEmpty
	la	$a0, emptyMsg
	jal 	Print_string	
	jal 	Exit
arrayNotEmpty: # The array isn't empty, continue execution
	add	$t0, $s0, $zero
	add	$t1, $zero, $zero
	la	$a0, unsortedMsg
	jal 	Print_string
printLoopUnsorted:
	lw	$a0, ($t0)
	jal 	Print_integer
	la	$a0, separator
	jal 	Print_string
	add	$t0, $t0, 4
	add	$t1, $t1, 1
	bne	$s1, $t1, printLoopUnsorted

	# Call MergeSort for first time
	sub	$s1, $s1, 1		# set s1 to length-1
	add	$a0, $zero, $zero 	# low stored in $a0
	add	$a1, $zero, $zero 	# mid stored in $a1
	add	$a2, $zero, $s1		# high stored in $a2
	jal	MergeSort
			
	# Finish execution in main by printing sorted array
	add	$t0, $s0, $zero
	add	$t1, $zero, $zero
	la 	$a0, sortedMsg
	jal	Print_string
	addi	$s1, $s1, 1		# set s1 to length
printLoopSorted:
	lw	$a0, ($t0)
	jal 	Print_integer
	la	$a0, separator
	jal 	Print_string
	add	$t0, $t0, 4
	add	$t1, $t1, 1
	bne	$s1, $t1, printLoopSorted
	jal 	Exit 			# End the program
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# How it works: This mergesort algorithm does not follow the algorithm listed in the
# homework prompt. I believe it is simpler. Mergesort() takes in low and high arguments
# (the array is globally saved and accessed) and then makes recursive calls to 
# mergesort(low, mid) and then mergesort(mid+1, high) and then calls merge(low, mid, high). 
# Merge() creates L1 and L2 to look at the elements of the array. It creates a second 
# array (b) of the required size and places elements from a into b based on the 
# divide and conquer conditions passed. Once the merge is done, control is returned
# to Mergesort which continues the algorithm. For more information, visit 
# https://www.tutorialspoint.com/data_structures_algorithms/merge_sort_program_in_c.htm

# --- MergeSort Procedure ---
MergeSort:
	addi	$sp, $sp, -16		# adjust stack, push return address
	sw	$ra, 12($sp)
	
	bge	$a0, $a2, MergeSortEnd 	# if low >= high, end procedure
	add	$a1, $zero, $zero 	# reset mid
	add	$t0, $a0, $a2 		# temp = low + high
	div 	$a1, $t0, 2		# mid = temp / 2 
	
	# push arguments onto stack
	sw	$a0, 0($sp)
	sw	$a1, 4($sp)
	sw	$a2, 8($sp)
	
	add	$a2, $a1, $zero		# Call MergeSort(low, mid)
	jal 	MergeSort
	
	# load arguments back
	lw	$a0, 0($sp)
	lw	$a1, 4($sp)
	lw	$a2, 8($sp)
	# lw	$ra, 12($sp)

	addi	$a0, $a1, 1		# Call MergeSort(mid+1, high)
	jal MergeSort
	
	# load arguments back
	lw	$a0, 0($sp)
	lw	$a1, 4($sp)
	lw	$a2, 8($sp)
	lw	$ra, 12($sp)

	jal 	Merge			# Call Merge
MergeSortEnd:
	lw	$ra, 12($sp)		# Load return address
	addi	$sp, $sp, 16 		# Readjust stack pointer
	jr	$ra			# Return
# ---------------------------

# --- Merge Procedure ---
Merge:
	add	$s2, $zero, $zero	# initialize
	add	$t3, $zero, $zero
	add	$t9, $zero, $zero
	add	$t0, $a0, $zero		# i = low
	add	$t1, $a0, $zero		# L1 = low
	addi	$t2, $a1, 1		# L2 = mid + 1
	
	add	$s2, $a0, $zero		# Protect a0 from being overwritten permanently
	add	$a0, $a2, $zero		# create array b for merging
	li	$v0, 9
	syscall

	add	$t3, $v0, $zero 	# tmp3 points to arrayb
	add	$a0, $s2, $zero
	add	$s2, $t3, $zero		# s2 points to arrayb as backup
	
While1:
	mul	$t9, $t1, 4		# tmp9 is the array index converter (turn i into address increment)
	add	$t5, $t9, $s0		# tmp5 = &a[L1]
	lw	$t5, ($t5)		# tmp5 = *a[L1]
	mul	$t9, $t2, 4
	add	$t6, $t9, $s0		# tmp6 = &a[L2]
	lw	$t6, ($t6)		# tmp6 = *a[L2]
	add	$t3, $s2, $zero		# tmp3 = &b[0]
	mul	$t9, $t0, 4
	add	$t3, $t3, $t9		# tmp3 = &b[i]
	
	bgt	$t5, $t6, Else1		# if *a[L1] <= *a[L2] then
	sw	$t5, ($t3)		# *b[i] = *a[L1]
	addi	$t1, $t1, 1		# L1 = L1 + 1
	j	Final1
Else1:					# else
	sw	$t6, ($t3)		# *b[i] = *a[L2]
	addi	$t2, $t2, 1		# L2 = L2 + 1
Final1:
	addi	$t0, $t0, 1		# i = i + 1
	bgt	$t1, $a1, End1		# loop only if L1 <= mid
	bgt	$t2, $a2, End1		# loop only if L2 <= high
	# addi	$t0, $t0, 1		# i = i + 1
	j	While1
End1:
	bgt	$t1, $a1, End2		# loop only if L1 <= mid
	
While2:
	mul	$t9, $t1, 4
	add	$t5, $t9, $s0		# tmp5 = &a[L1]
	lw	$t5, ($t5)		# tmp5 = *a[L1]
	add	$t3, $s2, $zero		# tmp3 = &b[0]
	mul	$t9, $t0, 4
	add	$t3, $t3, $t9		# tmp3 = &b[i]
	sw	$t5, ($t3)		# *b[i] = *a[L1]
	addi	$t1, $t1, 1		# L1 = L1 + 1
	addi	$t0, $t0, 1		# i = i + 1	
	bgt	$t1, $a1, End2		# loop only if L1 <= mid
	j	While2
End2:
	bgt	$t2, $a2, End3		# loop only if L2 <= high
	
While3:
	mul	$t9, $t2, 4
	add	$t6, $t9, $s0		# tmp6 = &a[L2]
	lw	$t6, ($t6)		# tmp6 = *a[L2]
	add	$t3, $s2, $zero		# tmp3 = &b[0]
	mul	$t9, $t0, 4
	add	$t3, $t3, $t9		# tmp3 = &b[i]
	sw	$t6, ($t3)		# *b[i] = *a[L2]
	addi	$t2, $t2, 1		# L2 = L2 + 1
	addi	$t0, $t0, 1		# i = i + 1
	bgt	$t2, $a2, End3		# loop only if L2 <= high
	j	While3
	
End3:
	add	$t0, $a0, $zero		# i = low
	add	$t7, $s0, $zero		# tmp7 = &a[0]
	
While4:
	add	$t3, $s2, $zero		# tmp3 = &b[0] 
	mul	$t9, $t0, 4
	add	$t3, $t3, $t9		# tmp3 = &b[i]
	lw	$t3, ($t3)		# tmp3 = *b[i]
	add	$t7, $s0, $zero		# tmp7 = &a[0]
	add	$t7, $t7, $t9		# tmp7 = &a[i]
	sw	$t3, ($t7)		# *a[i] = *b[i]
	addi	$t0, $t0, 1		# i = i + 1
	bgt	$t0, $a2, MergeEnd	# loop only if i <= high
	j	While4
	
MergeEnd:
	jr	$ra			# Return
# ---------------------------

# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
	.data
startMsg:
	.asciiz "\nPlease enter positive integers. When you are finished enter -1.\n"
prompt:
	.asciiz "Enter integer: "
emptyMsg:
	.asciiz "Nothing to sort -- the array is empty!\n"
unsortedMsg:
	.asciiz "\nUnsorted array: "
sortedMsg:
	.asciiz "\nSorted array:   "
separator:
	.asciiz " "
	
	.align 4
array1: 
	.space 60 # 60 bytes for max 15 integers
	
	.align 4
arrayL:
	.space 32 # 32 bytes for max 8 integers
	
	.align 4
arrayR:
	.space 32 # 32 bytes for max 8 integers
	
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

# Wrapper functions around some of the system calls
# From P&H COD, Fig. A.9.1
	.text

	.globl Read_integer
Read_integer: 	# input an integer to be stored in v0
	addi	$v0, $zero, 5
	syscall
	jr	$ra

	.globl Print_integer
Print_integer: # print the integer in register a0
	addi 	$v0, $zero, 1
	syscall
	jr 	$ra

	.globl	Print_string
Print_string:	# print the string whose starting address is in register a0
	addi	$v0, $zero, 4
	syscall
	jr	$ra

	.globl	Exit
Exit:		# end the program, no explicit return status
	addi	$v0, $zero, 10
	syscall
	jr	$ra

	.globl	Exit2
Exit2:		# end the program, with return status from register a0
	addi	$v0, $zero, 17
	syscall
	jr	$ra