This is boiling my brain, I've just started learn MIPS. The assignment asks us to use loops and maybe even a stack to do a simple multiplication by squaring a three digit number. For the assignment to be correct, the program needs to run for a minimum of 30 seconds doing the same calculation over and over.
Obviously I'm not asking for you to do my assignment (I want to learn), however I'm stumped on how to implement nested loops in MIPS, there isn't much online. I found something on Stack Overflow and tried to implement the same style but it doesn't work. A single loop works fine, it only runs for one second though so its nowhere near close enough. My problem is how to input a second loop really.
Here's my code:
.data
enterNumber: .asciiz "Enter three digit number \n"
.text
main:
addi $t3, $zero, 0
addi $t1, $zero, 0 #counter for second for loop
#asks for number
li $v0, 4
la $a0, enterNumber
syscall
#receives number
li $v0, 5
syscall
move $t0, $v0 #move number to t0
For1:
beq, $t3, $t0, exit #if counter= t0 then loop ends
For2:
beq, $t1, $t0, For1 #if counter= t0 then loop ends
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t1, $t1, 1 #add 1 to counter
j For2 #jump back to the top
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t3, $t3, 1 #add 1 to counter
j For1 #jump back to for loop
exit:
li $v0, 1
move $a0, $t2 #print out multiplication
syscall
#tell system to stop
li $v0, 10
syscall
The program runs through the inner loop (For2) fine, but its not incrementing the outer loop at all. Thanks in advance
The only problem with your code is that everything you've written in the outer loop(For1), after the inner loop (For2) will never be executed, because of the way you've written the conditions in For2. You only need to make a small change to your loops code: make For2 jump to the last part of your For1 loop in case counter = t0 instead of making it jump to For1.
For1:
beq, $t3, $t0, exit #if counter= t0 then loop ends
For2:
beq, $t1, $t0, exit2 #if counter= t0 then loop ends
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t1, $t1, 1 #add 1 to counter
j For2 #jump back to the top
exit2:
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t3, $t3, 1 #add 1 to counter
j For1 #jump back to for loop
You need to make a small change to your loops code.
Make For2 jump to the last part of your For1 loop in case counter = t0 instead of making it jump to For1.
write below code under For1 loop.
For2exit:
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t3, $t3, 1 #add 1 to counter
j For1 #jump back to for loop
and make change in the for2. make it jump to For2exit rather to For1.
Related
For example, I have a piece of C code that I am trying to convert to MIPS for practice, but for the variable count, I don't know whether to use addi $t0,0 or li $t0, 0. Could I use either either or? And what is the difference?
Void haarPredict (int vector[], int N)
{
int half = N >> 1;
int count = 0;
for(int i = 0; i < half; i++)
{
int predictVal = vector[i];
int j = i + half;
vector[j] = vector[j] - predictVal
}
}
This is what I have so far after converting the above code to MIPS. Assuming $a0 is vector[] and $a1 is N. Again, I am not sure if li or addi is the correct thing to use.
srl $t0, $a1, 1 #t0 holds half. half = N >> 1
addi $t1, $t1, 0 #t1 holds count. count = 0
addi $t2, $t2, 0 #t2 holds i. i = 0
loop: slt $t3, $t2, $t0 #t3 holds 1 if i < half
beg $t3, $zero, exit #exit if t3 == 0
lw $t4, 0($a0) #t4 holds predictValue
addi $a0, $a0, 4 #4 bytes for next word address
addi $t5, $t2, $t0 #t5 holds j. j = i + half
lw $t6, $t6, $t4 #vector[j]=vector[j]-predivtVal
addi $t2, $t2, 1 #i++
j loop
exit: jr $ra
The li (Load immediate) instruction loads a specific numeric value into a register.
The addi (Add inmediate) adds a register and a sign-extended immediate value and stores the result in a register.
So, unless you are 100% sure a register has a zero value, then you shouldn't use an addi instruction to set a register.
For example:
addi $t1, $t1, 0 #t1 holds count. count = 0
You don't know if $t1 is zero at that particular moment. If thats a subroutine, you might be using a garbage value of $t1 (a value from before the invocation of the subroutine, before the jump to the address of the subroutine).
So the safe way is to set the register with li (thus, count=0), not taking into consideration the previous value of the register.
I have to write a MIPS code to sum the series 1 + 5 + 9 + ... + N, under the constraint that I should use minimum number of registers to implement the MIPS code.
Here's my solution. It'd would be nice if you could point out any mistakes.
High-level code:
int count = 1;
int sum = 1;
while(count<N){
count = count + 4;
sum = sum + count;
}
Associate variable 'count' with register $t0 and
variable 'sum' with register $s0.
Equivalent MIPS code:
addi $t0, $zero, 1
addi $s0, $zero, 1
Loop: slti $t2, $t0, N
beq $t2, $zero, Exit
addi $t0, $t0, 4
addi $s0, $s0, $t0
j Loop
Exit:
You need a register to save the actual sum. If N is hard coded, I'd do something like this (untested code);
addi $t0, $zero, 0 ; Sum
addi $t1, $zero, 1 ; Counter
Loop:
slti $t2, $t1, N + 1 ; Exit if $t1 > N
beq $t2, $zero, Exit
add $t0, $t0, $t1 ; $t0 = $t0 + $t1
addi $t1, $t1, 4 ; $t1 += 4
j Loop
Exit: ; $t0 contains the sum here
I have this code that goes through an array of 5000 ASCII values of characters and then counts the number of each character and stores it into an array in alphabetical order.
.text
la $s7,results
array1 is the array of 5000 ASCII characters
la $s6,array1
main:
addi $s0,$zero, 5000
addi $s3, $zero,96
addi $s4, $zero,65
loop:lw $s2,0($s6)
addi,$t1,$zero,0
addi $s6,$s6,4
addi, $s5,$zero, 0
addi $s0,$s0, -1
bge $s2, $s3, convert
The substaction of of $s2, - $s4($s4 is # )is to get the positon of where the count needs to be stored
ex F - # = 6
sub $s5, $s2, $s4
I was wondering if this was right for it getting to the correct position and to increment the count?
addi $t1, $t1, 1
loop2: addi $s7, $s7, 4
lw $t0,($s7)
add $t0, $t0, $t1
sw $t0,($s7)
addi, $s5,$s5, -1
beq $s5, $zero, loop2
bne $s0,$zero, loop
This converts the character to an upper case ASCII value.
convert: subi $s2,$s2, 32
addi $s5, $s5, 0
sub $s5, $s2, $s4
j loop2
.data
results: .space 128 # Words to be used to store results
In this MIPS program
When this code fragment is run, how many instructions will be executed in total?
i1: ori $t0, $0, 1000
i2: ori $t1, $0, 2000
i3: addi $t2, $t0, 100
i4: lw $t3, 0($t1)
i5: lw $t4, 0($t0)
i6: add $t3, $t3, $t4
i7: sra $t3, $t3, 1
i8: sw $t3, 0($t0)
i9: sw $t3, 0($t1)
i10: addi $t0, $t0, 4
i11: addi $t1, $t1, 4
i12: slt $t3, $t0, $t2
i13: bne $0, $t3, i4
On every cycle, it adds 4 to $t0, which is initialized to 1000. At the end of the cycle, it checks if $t0 is greater than $t2, which is initialized to 1100. If it is, then the cycle breaks. So, it's the original 13 instructions, plus 10 for every cycle until it breaks. And it cycles an additional 25 times. And I may have added wrong, but if not, it's 263 instructions.
I know the program loads the address of .word 5 which is the initial value, I'm getting confused as to what the program is actually doing. Is it comparing stacks of the word or adding.
.data
arg: .word 5
.text
.globl main
main:
la $t3, arg
lw $t2, 0($t3)
lw $t3, 0($t3)
addi $t1, $zero, 0
beqz $t2, fin
fori:
add $t1, $t1, $t2
addi $t3, $t3, -1
bnez $t3, fori
fin:
li $v0, 10
syscall
Looks like it does addition based on the first item in the space as it doesn't access the array from inside the loop.
So for instance if you input a character representing the ascii value of 5 (not '5' itself iirc) you might see something like this:
int t2 = 5, t3 = 5, t1 = 0;
do {
t1 += t2;
t3 -= 1;
} while(t3 > 0);
Someone has already answered but I shall provide the translation I did:
.data
arg: .word 5
.text
.globl main
main:
la $t3, arg # load-address of arg into t3
lw $t2, 0($t3) # load-word from the address in t3 + 0 offset, like t3[0]
lw $t3, 0($t3) # same but to t3
addi $t1, $zero, 0 # initialize t1 to 0? weird they don't use li
beqz $t2, fin # if t2 is zero jump to fin:
fori:
add $t1, $t1, $t2 # t1 = t1 + t2
addi $t3, $t3, -1 # t3 -= 1
bnez $t3, fori # if(t3 != 0) goto fori
fin:
li $v0, 10 # load immediate 10 into v0, which is the syscall to terminate the program
syscall
Disclaimer: I don't have any direct MIPS experience, I just have been around a number of assembly languages.
That said, I think what the program does is calculating the square of 'arg' by repeated addition - in this case 5 * 5 = 25. However, the result in $t1 doesn't seem to be stored anywhere, instead the program just exits.