Reputation: 31
I am trying to create a program where I can store up to 8 values in an array and then compare all these values to find the smallest number. For some reason my loop overwrites the first position in the array every time. Here's what I have. I then add 4 to $t1 on the loop so once it goes back around it should store the next integer in the space after that. I don't see what I'm doing wrong here?
.data
myArray: .space 32
Msg1: .asciiz "Enter an integer: "
.text
main:
# Print Message
li $v0, 4
la $a0, Msg1
syscall
# Prompt the user to enter an integer
li $v0, 5
syscall
# Store the first integer in $t0
move $t0, $v0
# Declare $t1 for the array position that the integer will be stored at
addi $t1, $zero, 0
# Store the integer in the array
sw $t0, myArray($t1)
#Add 4 to $t1 so store the next value in the next array position
addi $t1, $zero, 4
beq $t0, $zero, Exit
j main
Exit:
# Declare an exit to the program
li $v0, 10
syscall
Upvotes: 0
Views: 3030
Reputation: 26646
First, let's start with a working algorithm in C:
int a [] = { /* array elements */ };
int n = /* count of number of elements */;
...
int currMin = 0;
for ( int i = 0; i < n; i++ ) {
int next = a[i]; // next array element to check
if ( next < currMin ) // is it smaller than what we've seen so far?
currMin = next; // yes: capture new min value
}
// on exit from the loop currMin holds the min value
Ok, now we'll make some simple logical transformations on the way to taking this to assembly language. First, we remove the for loop in favor of the slightly simpler while loop construct.
int currMin = 0;
int i = 0;
while ( i < n ) {
int next = a[i]; // next array element to check
if ( next < currMin ) // is it smaller than what we've seen so far?
currMin = next; // yes: capture new min value
i++;
}
// on exit from the loop currMin holds the min value
Next, we'll transform the while loop into assembly's if-goto-label. (We could work the if-then first instead; the order we transform doesn't matter.)
int currMin = 0;
int i = 0;
loop1:
if ( i >= n ) goto endLoop1;
int next = a[i]; // next array element to check
if ( next < currMin ) // is it smaller than what we've seen so far?
currMin = next; // yes: capture new min value
i++;
goto loop1;
endLoop1:
// on exit from the loop currMin holds the min value
Next, we'll do the if-then statement. We could have done it first, that wouldn't change the analysis or results.
int currMin = 0;
int i = 0;
loop1:
if ( i >= n ) goto endLoop1;
int next = a[i]; // next array element to check
if ( next >= currMin ) goto endIf1;
currMin = next; // yes: capture new min value
endIf1:
i++;
goto loop1;
endLoop1:
Next we'll take this to assembly language.
First, assign variables to physical storage, here good choice is registers. Mental map:
$a0 array a
$a1 element count n
$v0 currMin, the result
$t0 loop control variable i, also used as index
$t1 temporary variable "next"
Second, translate code as per the last above:
li $v0, 0 # currMin = 0
li $t0, 0 # i = 0
loop1:
bge $t0, $a1, endLoop1
# array reference, variable index: a[i], capture in "next"/$t1
sll $t9, $t0, 2
add $t9, $a0, $t9
lw $t1, 0($t9)
# the if-then inside the loop body
bge $t1, $v0, endIf1
move $v0, $t1 # capture newly seen lowest value
endIf1:
# finish the rest of the while loop, having the for-loop i++ here
addi $t0, $t0, 1
j loop1
endLoop1:
All that's left is to put some starting and ending code around that, assuming the register numbers match up.
The starting code for this would put the address of the array into $a0
, and the count of elements into $a1
. Could use different registers of course, with appropriate modifications.
The ending code should expect the result in $v0
, to print or otherwise.
The starting code would be entirely before this code, and the ending code entirely after.
Yes, there are a few steps — but each one is a relatively simple and logical transformation. Logical transformations enable translating the C code, first staying in C but simplifying to make it easy to go right to assembly.
Upvotes: 1