# 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