Store multiples off 11 in an array up to 1000 in MIPS - mips

(MIPS) I'm trying to store multiple's of 11 up to 1000 in an array and then trying to print them out in a sperate loop (I know i can do it a one loop all together)
.data
array11 : .space 360
.text
while :
beq $t0, 360,exit
addi $t0, $t0, 4
addi $s0, $s0, 7
sw $s0,array11 ($t0)
j while
addi $t0, $zero, 0
exit:
loop :
beq $t0, 360,exit
addi $t0, $t0, 4
lw $t6, array11($t0)
li $v0, 1
move $a0, $t6
syscall
j while

You've got the right idea for how to do two separate loops, but there are a few problems with what's in those loops. I'll go through the code, one step at a time and come to a possible solution:
.text
while :
beq $t0, 360,exit
To start with, your program begins with the first instruction after the .text declaration. Therefore the first thing you do in your program is compare $t0 to 360. The problem with that is, there's no way of knowing what value $t0 holds. Your operating system uses registers just like your program does, and so it could contain anything. Presumably you're trying to loop from 0 to 360, so you need to set $t0 to 0 before you start comparing it.
.text
move $t0,$zero
while:
beq $t0, 360,exit
addi $t0, $t0, 4
addi $s0, $s0, 7
sw $s0,array11 ($t0)
j while
Now let's move on to the loop itself. The syntax you're using here sw $s0, array11($t0) could work, but there's no guarantee, as offset values have a limited range. It depends on what the address of array11 happens to be - and you don't want to rely on that if you don't have to. It's better to write it like this. We'll use the register $t2 for the loop counter
.text
la $t0,array11
move $t2,$zero
while:
beq $t2,360,exit
addi $t0,$t0,4 #increment pointer
addi $t2,$t2,1 #increment loop counter
addi $s0,$s0,7 #???
sw $s0,0($t0) #store in array
j while
This, I'm not sure I understand. Why add 7 to $s0 if the goal is to output multiples of 11? Here's what I'd do to fix that.
.text
la $t0,array11
move $t2,$zero
move $s0,$zero
while:
beq $t2,360,exit
addi $t0,$t0,4 #increment pointer
addi $t2,$t2,1 #increment loop counter
addi $s0,$s0,11 #next multiple of 11.
sw $s0,0($t0) #store in array
j while
Now that this is working, you can reduce the number of instrutions by changing how your loop is structured.
.text
la $t0,array11
li $t1,360
move $t2,$zero
move $s0,$zero
while:
addi $t0,$t0,4 #increment pointer
addi $t2,$t2,1 #increment loop counter
addi $s0,$s0,11 #next multiple of 11.
sw $s0,0($t0) #store in array
bltu $t2,$t1,while #loop while $t2 < 360
This version effectively merges the j while and beq $t0,360,exit into one instruction which will make your loop faster.

Related

Why does the last line compare $t2 to $s0?

This is exercise 2.29 from the 5th edition of Computer Organisation and Design by David A. Patterson and John L. Hennessy:
...
addi $t1, $0, $0
LOOP :
lw $s1, 0($s0)
add $s2, $s2, $s1
addi $s0, $s0, 4
addi $t1, $t1, 1
slti $t2, $t1, 100
bne $t2, $s0, LOOP
...
i = $t1
$s2 = result
$s0 = base address of MemArray
I'm supposed to translate this into C code, and I get:
for(int i =0 ;i<100;i++)
{
result += MemArray[i];
}
This is the answer, but why does the last line of MIPS code compare $t2 with $s0? $s0 is the base address of MemArray. Shouldn't the comparison be to the zero register, in order for the loop to continue?
As far as I can tell, this is an error in the book; the correct comparison should be with $0, so $s0 may just be a typo. However, it is not mentioned in the errata for the book's fifth edition.

Why am I getting a duplicate main label error? Also why is there no output?

I am working on my first project in mips, trying to print the sum of all the positive numbers in an array. I am now testing my code with QtSpim and have been getting an error saying I am using the main label twice even though there is only one occurrence. There is also no output, regardless of whether or not I include the main label. Here's the code:
.data
A: .word -89, 19, 91, -23, -31, -96, 3, 67, 17, 13, -43, -74
.text
main:
addi $s0, $zero, 0 #set $s0 for sum of positive nums to 0
la $s1, A #set $s1 to array address
addi $t0, $s1, 48 #set $t0 to exit point
while:
beq $s1, $t0, end
lw $t1, A($s1)
slt $t2, $t1, $zero
bne $t2, $zero, else #skips addition step if A at $s1 is negative
add $s0, $s0, $t1
else:
addi $s1, $s1, 4
j while
end:
li $v0, 1
move $a0, $s0
syscall
li $v0, 10
syscall
Sorry if this is bad formatting for mips, I have only ever worked with Java and C++.
there's an error on this line
lw $t1, A($s1)
What I believe you want is
lw $t1, 0($s1)
A positive integer must be in the offset of the lw instruction.
The main label error seems like a rabbit hole as you see no label was used more than once.

MIPS Mult two numbers and result it negative number

I am new for MIPS, there is my code:
.text
main:
add $s0, $zero, 1 # set $s0 to 0 for the initial value for the following loop
Loop: jal srand # Call function srand
addi $s0, $s0, 1 # $s0 = i++
slti $s1, $s0, 6 # $s1 < 6
bne $s1, $zero, Loop # go to loop in i < 6
beq $s1, 6, end_loop # go out the loop when i == 6
end_loop:
li $v0, 10
syscall
srand: # This function will set the numbers for future calculation
lw $t0, a # Load a value to $t0 1103515245
lw $t1, c # Load c value to $t1 12345
lw $t2, m # Load m value to $t2 2147483648
multu $t0,$s0 # result for multiplication (Xn*a) and store the result to $t3
add $t4, $t3, $t1 # result for add multiplication (Xn*a+c) and store the result to $t4
move $a0, $t4 # Debug function
li $v0, 1 # Debug function
syscall # Debug function
la $a0, msg
li $v0, 4
syscall
jr $ra
There is a problem, when the code goes to this "multu $t0,$s0" commend and result will be wrong.
1103515245 * 2 returned a negative number -2087936806
anyone know how to fix it ??
thanks
As chrylis said, it looks like integer overflow. If that's unclear to you, you should read up on two's complement integer representations.
Basically, the value of the highest-order bit is defined to be negative. Suppose you have 32-bit integers. Then 0x800000 will have the value of -2**32, and the other bits have their normal value, so you end up with an expression that looks like -2**32 + [the sum of the other bits], in particular 0xFFFFFFFF has the value of -1, 0xFFFFFE is -2, and so on.

Attempt to execute non-instruction in mips assembler?

.data
stack: .word 3, 2
.text
.globl main
main:
la $s1, stack #assign stack start memory to $s1
addi $t3, $t3, 0 #clear $t3
addi $t3, $t3, 4 #assign 4 to $t3
add $s1, $s1, $t3 #second member of stack
lw $t1, 0($s1) #d2
addi $t3, $t3, -4 #move $t3 forward
add $s1, $s1, $t3 #first member of stack
lw $t0, 0($s1) #d1
add $t0, $t0, $t1 #d1 = d1 +d2
sw $t0, 0($s1) #store new d1 at d1's location
I'm trying to create a mips program, which gets last-1 and last member of the stack, and add them, and store it. I don't care about addi $t3, $t3, 4 or stack: .word 3, 2 it's just for test.
However, when I run this at qtspim I got an error message "attempt to execute non-instruction at 0x0040004c" please enlighten me as to what the problem is.
You need to end your program with a jr $ra, otherwise the processor will just keep executing whatever random instructions that happen to come after the sw $t0, 0($s1).

MIPS debugging help

It seems that my understanding of MIPS fails me.
What I need to do is create a program that reverses a string input from terminal, using a stack, but without using $sp. Is there anyone here that knows MIPS?
Register usage
t0 - theString address start
t1 - stack address start
t2 - temp for retrieved character
t3 - counter for t0
t4 - counter for stack
t5 - newline
t6 - Length
.data
theString: .space 42
newLine: .asciiz "\n"
stack: .space 42
.globl main
.text
main:
li $v0, 8 # Set to read string
la $a0, theString
li $a1, 42 # Set size of string
syscall # Read string from terminal
la $t0, theString # Prepare t0 with theString
la $t1, stack # Prepare t1 with stack
la $t5, newLine
addi $t3, $t0, 0
addi $t4, $t1, 42
j push
push:
addi $t3, $t3, 1
addi $t4, $t4, -1
lb $t2, ($t3)
beq $t2, $t5, epush
sb $t2, ($t4)
j push
epush:
sub $t6, $t3, $t0
addi $t6, $t6, -1
addi $t3, $t0, 0
addi $t4, $t1, 0
j pop
pop:
addi $t3, $t3, 1
addi $t4, $t4, 1
lb $t2, ($t4)
beq $t2, $t5, epop
sb $t2, ($t3)
j pop
epop:
addi $t3, $t3, 1
sb $t5, ($t3)
li $v0, 4 # Set to print string
la $a0, theString # Set var to syscall output register
syscall # Print string
li $v0, 10 # Set to end program
syscall # End Program
For example, this just gives an infinite loop. (Sorry for lack of comments, I'm just tearing my hair out here)
Now, I think the problem is somewhere related to the newline character, but I don't know where?
Is there a reason you are using j and not jal? And it appears you are using SPIM, which has numerous issues.
In your pop loop, you are comparing (in beq) the address of newline (in $t5) and the address of the next character in the string. Even though they might contain the address of a location that contains "\n", the addresses might not be the same, because "\n" can be in more than one place. In fact, I can guarantee that they will never be the same, because one will refer to the address of the captured string, and the one in $t5 will be the address of the one at the beginning of the program.