I'm a newbie at MIPS and am attempting a program to find the value of the max number in a pseudo random array. However, I get an out of range error on a line I was fairly sure was allocated proper memory and such. Most of the skeleton code, comments, etc were given, I just am attempting to write the find_max function. I commented at the line giving me issues.
.data #data segment
nl: .asciiz "\n" #ASCII for a new line
separator: .asciiz ":" #string that seprates index from number
msg1: .asciiz "The function returned "
msg2: .asciiz "\nThe maximum value is "
li $v0, $t5
#.asciiz
msg3: .asciiz "\nThe address of the word is "
#.asciiz
li $v0, $t6
.align 2 # important for words
buffer: .space 4096 # allocate space for 1K words
.text # Code segment
.globl main # declare main to be global
main:
addi $sp, $sp, -4 # allocate space on the stack for $s0
sw $s0, ($sp) # save $s0
li $s0, 16 # specify the size of the array, must be less than 1024
la $a0,name # load the address of "name" into $a0
li $v0,4 # system call, type 4, print an string, *$a0
syscall # call the "OS"
# call
la $a0, buffer
move $a1, $s0
jal init_array # initialize the array with random values
la $a0, buffer
move $a1, $s0
jal print_array # call print. You can comment it out.
# call your find_max function
la $a0, buffer
move $a1, $s0
lw $t0, 0($a0)
la $t5, 0($a0)
jal find_max # call find_max
lw $v0, 0($t0)
lw $v1, 0($t5)
# add code to print the results
# print the returned value
la $a0, msg1 # print mssage 1
li $v0, 4
syscall
# print the maximum value
la $a0, msg2 # print mssage 2
li $v0, 4
syscall
# print the address of the value (in hex).
la $a0, msg3 # print mssage 3
li $v0, 4
syscall
la $a0, nl # print end of line
syscall
# restore $s0. You can check $sp here to make sure the stack is maintained correctly.
lw $s0, ($sp) # load $s0
addi $sp, $sp, 4 # restore $sp
Exit: lw $v0, 0($t5)
lw $v1, 0($t6)
#li $v0,10 # System call, type 10, standard exit
syscall # ...and call the OS
find_max: # your implementation of find_max
addi $sp, $sp, -16 # allocate space on the stack for four registers
sw $s0, ($sp) # save $s0
sw $s1, 4($sp) # save $s1
sw $s2, 8($sp) # save $s2
sw $s3, 12($sp) # save $s3
# put your code below.
# You can use temporary registers and $s0 to $s3
add $t1,$t1,1 # increment index i by 1
beq $t1,$s0,Exit # if all elements examined, quit
sll $t2,$t2,2 # compute 4i in $t2
add $t2,$t2,$s1 # form address of A[i] in $t2
# THIS IS THE LINE GIVING PROBLEMS
lw $t3,0($t2) # load value of A[i] into $t3
slt $t4,$t0,$t3 # maximum < A[i]?
beq $t4,$zero,find_max # if not, repeat with no change
addi $t0,$t3,0 # if so, A[i] is the new maximum
addi $t5, $t2, 0
# restore saved registers.
# make sure $sp is restored if you changed it.
lw $s0, ($sp)
lw $s1, 4($sp)
lw $s2, 8($sp)
lw $s3, 12($sp)
addi $sp, $sp, 16 # restore $sp
jr $ra # return to calling routine
Okay, the function you had to write was using the wrong register when calculating the array index:
Change:
Into:
But, your function also had a much more severe bug. You were looping back to the function beginning and creating multiple stack frames in the process. I think you may have realized this on some level which is why you tried to compensate and exit the function with a jump to
Exit:
[which is part ofmain
].Your calculation function would also terminate prematurely after finding the first maximum. It would not continue to loop through the remainder of the array to find better (i.e. larger) values.
There were a number of other bugs as well.
I've created two versions of your program. One with annotations regarding the bugs. And, a second version, cleaned up, and working.
Here is the annotated version [please pardon the gratuitous style cleanup]:
Here is the fixed and running version. I added the missing
init_array
andprint_array
functions as well as the results printing. The boilerplate code you were given also had some [minor] bugs that I fixed. I tried to remain faithful to yourfind_max
code, but, unfortunately, I needed to refactor it.Also, make note of the fact that under the mips ABI, the
$v*
,$a*
, and$t*
can be used by the called function for any purpose. So, modifying the$s*
registers was never an issue internally forfind_max
.