MIPS汇编合并排序算法

时间:2017-04-20 19:48:53

标签: assembly architecture mips computer-science

我必须用汇编代码MIPS编写一个算法。我选择了合并排序算法,下面是我到目前为止所做的。每当我尝试通过MARS模拟器运行程序时,我得到"错误:无效程序计数器值:0x00000000。"我该如何解决这个错误?

    ## We begin by checking to see if the array has size 0 or 1, and also some error cases.

## The arrays are designed so that the length of the array is located at the first index of each array.

## Then, the values in the array follow the length.

#First, we will check the input for errors.

bgt $a0, $sp, ErrorCase #If maze address is higher than the stack pointer, error

blt $a0, $gp, ErrorCase #If maze pointer is in text or below zero, both < $gp, error

#Second, we will load the length of the parameter array.

lw $t0, 0($a0) # Check the array at spot 0 for the length of the array

li $t1, 1 # Checking for one element in array

#Check for negative length value

blt $t0, $zero, ErrorCase #If length < 0, error

#Check if length exceeds $gp

bge $t0, $gp, checkHeap #If length > $gp and goes into stack, error

#Checks for 0 or one element in array

ble $t0, $t1, ReturnOriginal #return original array if size is 0 or 1

#Otherwise, jump to the main function.

j recursion

checkHeap:

## This will check to see if the heap overlaps the stack.

bge $sp, $gp, ErrorCase

j recursion

ReturnOriginal:

## This will handle arrays of size 0 or 1. Return the array as is.

move $v0, $a0

jr $ra

ErrorCase:

## This will handle any errors. Sets output to null (0)

li $v0, 0

jr $ra

## Recursion function

## Parameters:

## $a0 = input array

## $v0 = output array

## Temp Registers:

## $t0 = increment variable

## $t1 = 2 constant

## $t2 = 4 constant

## $t3 = first subarray length (l1)

## $t4 = first subarray (sub1)

## $t5 = second subarray length (l2)

## $t6 = second subarray (sub2)

## $t7 = length of the original array, later used to move things from original array to sub array

## $t8 = a[index]

## $t9 = a[index+l1]

recursion:

## This is the recursive step where we will check to see if we should still be dividing the array

## into subarrays of size 1.

#save current return address and array we are manipulating on the stack

addi $sp, $sp, -8

sw $ra, 0($sp)

sw $a0, 4($sp)

#constants

li $t0, 1 #$t0 = 1 loop counter

li $t1, 2 #$t1 = 2 check to see if array is fully split up

li $t2, 4 #$t2 = 4 4 bytes per int value

lw $t7, 0($a0) #$t7 = length of array we are currently working on

bge $t7, $t1, divide #check the array if it is greater than 2 in size, if not, go to base case

#If it is the base case, just return the array

move $v0, $a0 #move array to result $v0

lw $ra, 0($sp) #obtain return address

addi $sp, $sp, 8 #deallocate memory

jr $ra

divide:

## This function will effectively divide the array we are working on in half.

li $t2, 4 #$t2 = 4, 4 bytes per int value

#divide the length of the array by 2 for first sub array length

div $t7, $t1 #divide orig_array length by 2

mflo $t3 #obtain length of sub array 1 (l1)

mul $a0, $t3, $t2 #get the size = index * data, load it into $a0

addi $a0, $a0, 4 #extra space added for length in array

#initialize the first sub array

li $v0, 9 #load 9 into $v0

syscall

move $t4, $v0 #obtain the first subarray (sub1)

sw $t3, 0($t4) #save length of the first sub array to the first part of sub1

#get the length of the second sub array

sub $t5, $t7, $t3 #obtain length of the second array (l2 = array_length-l1)

mul $a0, $t5, $t2 #get the size = index * data, load it into $a0

addi $a0, $a0, 4 #extra space added for length of array

#initialize the second sub array

li $v0, 9 #load 9 into $v0

syscall

move $t6, $v0 #obtain the second subarray (sub2)

sw $t5, 0($t6) #save length of the second subarray to first part of sub2

FillArray1:

## This will fill the first subarray with the top half of the array we are working with

bgt $t0, $t3, else #check if $t0 > $t3, loop if not

lw $a0, 4($sp) #load previous state of the original array

mul $t8, $t0, $t2 #obtain real index = index * size (4)

add $a0, $a0, $t8 #add this to original array to move to a new address

add $t4, $t4, $t8 #add this index also to sub1 array

lw $t7, 0($a0) #load element from original array[index]

sw $t7, 0($t4) #store element to sub1[index]

addi $t0, $t0, 1 #inc by 1

#Reset the subarray offset to 0

li $t7, -1

mul $t8, $t8, $t7

add $t4, $t4, $t8

j FillArray1

else:

li $t0, 1 #reset increment to 1

FillArray2:

## This will fill the second subarray with the bottom half of the array we are working with

bgt $t0, $t5, else2 #check if $t0 > $t5, loop if not

lw $a0, 4($sp) #load previous state of the original array

add $t9, $t0, $t3 #obtain new index = i+l1

mul $t9, $t9, $t2 #obtain real index = (i+l1)*4

mul $t8, $t0, $t2 #obtain real index = sub2[index * size] (4)

add $a0, $a0, $t9 #add this to original array to move to a new address a[i+l1]

add $t6, $t6, $t8 #add $t8 to obtain address or sub2[index]

lw $t7, 0($a0) #load element from original array[index+l1]

sw $t7, 0($t6) #store element to sub2[index]

addi $t0, $t0, 1 #inc by 1

#Reset the subarray offset to 0

li $t7, -1

mul $t8, $t8, $t7

add $t6, $t6, $t8

j FillArray2

else2:

li $t0, 1 #reset increment to 1

callOnMerge:

## This is where we will implement recursion through dividing the arrays and merging the arrays.

move $a0, $t4 #Put first subarray into $a0

move $a1, $t6 #Put second subarray into $a1

addi $sp, $sp, -4 #Put second subarray onto the stack!

sw $a1, 0($sp)

jal recursion #recursion on subarray 1

lw $a0, 0($sp) #Load the second subarray

sw $v0, 0($sp) #save sub array result from recurse into stack

jal recursion #recursion on subarray 2

move $a2, $v0 #sets up the second subarray

lw $a1, 0($sp) #sets up first subarray

addi $sp, $sp, 4

jal Merge #merge the two

lw $ra, 0($sp) #load return address

addi $sp, $sp, 8 #deallocate memory

jr $ra #return to main function that called it

# Params:

# $a1 = first subarray

# $a2 = second subarray

# $v0 = new array, merged

# Temp Registers:

# $t0 = counter for first array (static)

# St1 = counter for second array (static)

# $t2 = loop counter (static)

# $t3 = bytes per int (4), or the offset

# $t4 = subarray1 length (static)

# $t5 = subarray2 length (static)

# $t6 = subarray1 value

# $t7 = address we grab from based on offset

# $t8 = new array length (static)

# $t9 = subarray2 value

Merge:

## This function will merge two given subarrays from parameters $a1 and $a2

#Set counters to one.

li $t0, 1 #first

li $t1, 1 #second

#Set loop counter to start at one.

li $t2, 1

#Initialize return array, where length is in $a1

li $t3, 4 #Each int inside the array is 4 bytes

lw $t4, 0 ($a1) #Get first subarray length

lw $t5, 0 ($a2) #Get second subarray length

add $t8, $t4, $t5 #Length of new array we are creating

mul $a0, $t3, $t8 #How much space our solution will need allocated

addi $a0, $a0, 4 #Add extra spot for length value

#Allocates enough bytes specified in $a0, which $v0 will point to.

li $v0, 9

syscall

sw $t8, 0 ($v0) #Puts the length of the new array at first index.

Do_Loop:

## Check to see if loop is complete. Which means we performed enough iterations to fill up the new array

bgt $t2, $t8, Merge_Complete

First_Array_Empty:

## Check to see if the first array is empty.

## If so, take the element from array 2.

ble $t0, $t4, Second_Array_Empty #If the counter is less than the first array, continue on.

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t1 #Multiply 2nd array counter by 4 bytes per int to get offset

add $t7, $t3, $a2 #Puts the offset address into $t7

lw $t9, 0 ($t7) #Put the value at this address into $t9. In a moment, we will put this into our return array.

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t2 #Multiply loop counter by 4 bytes per int to get offset

add $t7, $t3, $v0 #Now apply the offset to our new array

sw $t9, 0 ($t7) #Store the value into our new array

addi $t2, $t2, 1 #loop counter

addi $t1, $t1, 1 #second array counter

j Do_Loop #loop again

Second_Array_Empty:

## Check to see if the second array is empty.

## If so, take the element from array 1.

ble $t1, $t5, Grab_First

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t0 #Multiply 1st array counter by 4 bytes per int to get offset

add $t7, $t3, $a1 #Puts the offset address into $t7

lw $t6, 0 ($t7) #Put the value at this address into $t6. In a moment, we will put this into our return array.

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t2 #Multiply loop counter by 4 bytes per int to get offset

add $t7, $t3, $v0 #Now apply the offset to our new array

sw $t6, 0 ($t7) #Store the value into our new arrays

addi $t2, $t2, 1 #loop counter

addi $t0, $t0, 1 #first array counter

j Do_Loop #loop again

Grab_First:

#Check to see if we should grab a value from the first array.

#We will do this if first_element < second_element

#First we want to get the value at the 1nd array counter index

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t0 #Multiply 1st array counter by 4 bytes per int to get offset

add $t7, $t3, $a1 #Puts the offset address into $t7

lw $t6, 0 ($t7) #Put the value at this address into $t6. In a moment, we will put this into our return array.

#Then we want to get the value at the 2nd array counter index

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t1 #Multiply 2nd array counter by 4 bytes per int to get offset

add $t7, $t3, $a2 #Puts the offset address into $t7

lw $t9, 0 ($t7) #Put the value at this address into $t9. In a moment, we will put this into our return array.

bge $t6, $t9, Grab_Second #If the second value is smaller, branch to that function.

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t2 #Multiply loop counter by 4 bytes per int to get offset

add $t7, $t3, $v0 #Puts the offset address into $t7

sw $t6, 0 ($t7) #Store the value in the new array

addi $t2, $t2, 1 #loop counter

addi $t0, $t0, 1 #first array counter

j Do_Loop #loop again

Grab_Second:

## We will take the element from the second array.

## We will reach here if first_element > second_element

#We want to get the value at the 2nd array counter index

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t1 #Multiply 2nd array counter by 4 bytes per int to get offset

add $t7, $t3, $a2 #Puts the offset address into $t7

lw $t9, 0 ($t7) #Put the value at this address into $t9. In a moment, we will put this into our return array.

li $t3, 4 #Each int inside the array is 4 bytes

mul $t3, $t3, $t2 #Multiply loop counter by 4 bytes per int to get offset

add $t7, $t3, $v0 #Get new array address offset

sw $t9, 0 ($t7) #Store it at that location

addi $t2, $t2, 1 #loop counter

addi $t1, $t1, 1 #second array counter

j Do_Loop #loop again

Merge_Complete:

## Reaches here when the merge is complete.

## Now all we have to do is return the array.

jr $ra #return array to the Merge_Sort function

0 个答案:

没有答案