The following program
For the test case (lower bound: 2 upper bound: 4), I tried two different codes, with the difference marked below.
The following code does not return the expected output
findMin:
addi $t0, $a0, 0 # initialise $t0 (current pointer) to lower bound
addi $t1, $a0, 0 # initialise minimum pointer to upper bound
lw $t2, 0($t1) # initialise min (value) to the lower bound
Loop: slt $t4, $a1, $t0
bne $t4, $zero, End # branch to end if upper < lower
lw, $t3, 0($t0) # store the content of the current pointer
slt $t4, $t3, $t2 # if current ($t3) < min ($t2), store 1 in $t4
beq $t4, $zero, LoopEnd # if it is 0, go to LoopEnd
addi $t2, $t3, 0 # store content ($t3) as minimum ($t2)
addi $v0, $t0, 0 # store the address of min (DIFFERENCE)
LoopEnd: addi $t0, $t0, 4 # increments current pointer lower bound
j Loop # Jump to loop
End: jr $ra # return from this function
However, the following code does return the expected value:
findMin:
addi $t0, $a0, 0 # $t0 is the pointer to the current item
addi $t1, $a0, 0 # $t1 is the pointer to the minimum item
lw $t2, 0($t1) # $t2 stores the value of minimum item
loop:
slt $t4, $a1, $t0 # check if last pointer < current pointer
bne $t4, $zero, exit # if current pointer > last pointer, exit
lw $t3, 0($t0) # $t3 stores the value of current item
slt $t4, $t3, $t2 # if the current value is lesser than minimum value
beq $t4, $zero, skip # if current value is not lesser, then skip
addi $t1, $t0, 0 # minimum pointer = current pointer (DIFFERENCE)
lw $t2, 0($t1) # $t2 stores the value of minimum item
skip:
addi $t0, $t0, 4 # move to the next item
j loop
exit:
addi $v0, $t1, 0 # $v0 stores the address of the minimum item (DIFFERENCE)
jr $ra # return from this function
What is the rationale behind this?
The following is the code in its entirety (optional)
# arrayFunction.asm
.data
array: .word 8, 2, 1, 6, 9, 7, 3, 5, 0, 4
newl: .asciiz "\n"
.text
main:
# Print the original content of array
# setup the parameter(s)
# call the printArray function
la $a0, array # base address of array
la $a1, 10 # number of elements in array
jal printArray # call function
# Ask the user for two indices
li $v0, 5 # System call code for read_int
syscall
add $t0, $v0, $zero # store input in $t0
li $v0, 5 # System call code for read_int
syscall
add $t1, $v0, $zero # store input in $t1
# Call the findMin function
# setup the parameter(s)
la $a0, array # load address of array into $a0
la $a1, array # load address of array into $a1
sll $t0, $t0, 2 # calculate offset of lower bound
sll $t1, $t1, 2 # calculate offset of upper bound
add $a0, $a0, $t0 # set $a0 to the lower bound
add $a1, $a1, $t1 # set $a1 to the upper bound
# call the function
jal findMin # call function
# Print the min item
# place the min item in $t3 for printing
addi $t3, $t2, 0 # placing min item in $t3
addi $t4, $v0, 0 # saving the pointer to the min element
# Print an integer followed by a newline
li $v0, 1 # system call code for print_int
addi $a0, $t3, 0 # print $t3
syscall # make system call
li $v0, 4 # system call code for print_string
la $a0, newl
syscall # print newline
#Calculate and print the index of min item
la $a0, array
sub $t3, $t4, $a0
srl $t3, $t3, 2
# Place the min index in $t3 for printing
# Print the min index
# Print an integer followed by a newline
li $v0, 1 # system call code for print_int
addi $a0, $t3, 0 # print $t3
syscall # make system call
li $v0, 4 # system call code for print_string
la $a0, newl
syscall # print newline
# End of main, make a syscall to "exit"
li $v0, 10 # system call code for exit
syscall # terminate program
#######################################################################
### Function printArray ###
#Input: Array Address in $a0, Number of elements in $a1
#Output: None
#Purpose: Print array elements
#Registers used: $t0, $t1, $t2, $t3
#Assumption: Array element is word size (4-byte)
printArray:
addi $t1, $a0, 0 #$t1 is the pointer to the item
sll $t2, $a1, 2 #$t2 is the offset beyond the last item
add $t2, $a0, $t2 #$t2 is pointing beyond the last item
l1:
beq $t1, $t2, e1
lw $t3, 0($t1) # $t3 is the current item
li $v0, 1 # system call code for print_int
addi $a0, $t3, 0 # integer to print
syscall # print it
addi $t1, $t1, 4
j l1 # Another iteration
e1:
li $v0, 4 # system call code for print_string
la $a0, newl #
syscall # print newline
jr $ra # return from this function
#######################################################################
### Student Function findMin ###
#Input: Lower Array Pointer in $a0, Higher Array Pointer in $a1
#Output: $v0 contains the address of min item
#Purpose: Find and return the minimum item
# between $a0 and $a1 (inclusive)
#Registers used: $t0 (counter), $t1 (max add), $t2 (min), $v0 (min pos), $t3 (current item)
#Assumption: Array element is word size (4-byte), $a0 <= $a1
findMin:
addi $t0, $a0, 0 # initialise $t0 (current pointer) to lower bound
addi $t1, $a0, 0 # initialise minimum pointer to upper bound
lw $t2, 0($t1) # initialise min (value) to the lower bound
Loop: slt $t4, $a1, $t0
bne $t4, $zero, End # branch to end if upper < lower
lw, $t3, 0($t0) # store the content of the current pointer
slt $t4, $t3, $t2 # if current ($t3) < min ($t2), store 1 in $t4
beq $t4, $zero, LoopEnd # if it is 0, go to LoopEnd
addi $t2, $t3, 0 # store content ($t3) as minimum ($t2)
addi $t1, $t0, 0 # store the address of min
LoopEnd: addi $t0, $t0, 4 # increments current pointer lower bound
j Loop # Jump to loop
End: addi $v0, $t1, 0
jr $ra # return from this function
In the first case the problem is that you save the min pointer to the t1
register initially, but on return you expect it to be on v0
. Now on cases where the min value is not exactly on the lowerbound index this will not come up as an issue, because in the loop you save the new found min values pointer to v0
, so uppon return everything will be as expected. But in case like 2,4 the min value at the lowerbound here so in index 2, therefore in the loop since no new min points is found, thus nothing will be written in v0
, so on return it will have some garbage value.
Change the begining part to this and will work fine:
addi $v0, $a0, 0 # initialise minimum pointer to upper bound
lw $t2, 0($v0) # initialise min (value) to the lower bound