Mips loop iteration - mips

I have the following code which is effectively supposed to increment from 1-6 while doing arithmetic on a variable.
An example in C would be
int res = 0;
for(i=1; i<6; i++) {
res += i*i+1;
}
Now for my mips code:
.data
res: .word 0
.text
li $t0, 1 #int j = 1
loop:
beq $t0, 6, end #for(int j = 1; j < 6; j++)
add $t0, $t0, 1
mul $t1, $t0, $t0 #res += j * j + 1
addi $t1, $t1, 1
sw $t1, res
b loop
end:
li $v0, 1 #checking the end result
la $a0, res
syscall
li $v0, 10 #graceful exit
syscall
For some reason the result I get towards the end is ~300 million and that is obviously wrong. Does anyone see what the issue is? Im fairly new to mips assembly.
Thanks

You've got a few problems here.
Firstly, the line you have marked #res += j * j + 1 is only multiplying, there is no addition involved.
You seem to be attempting to use res to store a running total but you are overwriting it in each iteration. In fact, there shouldn't be any need to store res in memory, a register is much more appropriate for this purpose.
.text
main:
move $t2 $zero
li $t0 1
loop:
mul $t1 $t0 $t0
addi $t1 $t1 1
add $t2 $t2 $t1 # res += i * i + 1
addi $t0 $t0 1
blt $t0 6 loop
# print res
li $v0 1
move $a0 $t2
syscall
# exit
li $v0 10
syscall
Prints 60.

You want to do something like this.
I am assuming you wanted something like this:
int res = 0;
for(i=1; i<6; i++) {
res += i*i+1;
}
.data
res: .word 0
.text
li $t0, 1 #int i = 1
loop:
bgt $t0, 6, exit
add $t0, $t0, 1
mul $t1, $t0, $t0
addi $t1, $t1, 1
sw $t1, res // I'm sure you can just move here
b loop
exit:

Related

MIPS - how to write a for loop while also accessing and saving arrays

I won't lie, I'm a total beginner at programming in general with my first time being last year when I started programming in Computer Programming I. A lot of this is still over my head so uh... go easy on me will ya?
The question poised is as follows:
"1. (5 pts) Translate the following C code to MIPS. Assume that the variables i and j are assigned to registers $s0 and $s1, respectively. Assume that the base address of the arrays A and B are in registers $s6 and $s7, respectively. Assume that the elements of the arrays A and B are 4-byte words:
for (i = 0; i< j; i++)
B[i] = A[i+1] - A[i];
For my program I wrote:
.data
arrayA: .word 5,8, 12, 13, 28
sizeA: .word 5
arrayB: .space 4
i: .word 0
_j: .word 5
.text
# for (i = 0; i< j; i++)
# B[i] = A[i+1] - A[i];
main:
la $s6, arrayA #loads the base address of arrayA into register s6
la $s7, arrayB #loads the base address of arrayB into register s7
lw $s0, i #Loads zero into register s0 for i
lw $s1, _j #loads the value of 4 into register s2 for j
Loop:
beq $s0, $s1, Exit #Does the operation i < j in the for-loop
addi $s0, $s0, 1 #Does the operation i++ in the for-loop
mul $t0, $s0, 4 #Get address of i
add $t1, $t0, $s6 #Finds and stores the base address of a[i]
add $t2, $t0, $s7 #Finds and stores the base address of b[i]
lw $t3, ($s6) #get the value of a[i]
lw $t4, 4($10) #get the value of a[i + 1]
sub $t5, $t4, $t3 #subtracts a[i + 1] and a[i]
sw $t5, ($t2) #Stores the above into b[i]
add $a0, $zero, $t5
li $v0, 1
syscall
J Loop #loops back to beginning
Exit:
li $v0 10
syscall #syscall to exit the program
When I run it, it spits out 33333, which means it isn't incrementing. How do I fix this?
arrayA: .word 5,8, 12, 13, 28
may be wrong. You didn't add a space between 5, and 8 while giving spaces between the other elements. My QtSpim Version 9.1.21 didn't accept that.
arrayB: .space 4
is wrong. You are allocating only 4 bytes while space for 4 words (16 bytes) is required.
_j: .word 5
is wrong. The stored value is 5 despite of the comment saying "loads the value of 4 into register s2 for j". Using value 5 is wrong also because the array a has only 5 elements.
addi $s0, $s0, 1 #Does the operation i++ in the for-loop
is in the wrong place. The increment should be after the loop body.
lw $t3, ($s6) #get the value of a[i]
lw $t4, 4($10) #get the value of a[i + 1]
is wrong. The address of a[i] is stored in $t1, so you should use that.
J Loop #loops back to beginning
may be wrong. You used an uppercase letter for instruction name only here. At least my QtSpim Version 9.1.21 didn't accept that.
li $v0 10
may be wrong. You didn't use a comma for separating the operands while you used that in previous use of li: li $v0, 1. I'm surprised by seeing my QtSpim Version 9.1.21 accepting this.
Fixed code:
.data
arrayA: .word 5, 8, 12, 13, 28
sizeA: .word 5
arrayB: .space 4 * 4
i: .word 0
_j: .word 4
.text
# for (i = 0; i< j; i++)
# B[i] = A[i+1] - A[i];
main:
la $s6, arrayA #loads the base address of arrayA into register s6
la $s7, arrayB #loads the base address of arrayB into register s7
lw $s0, i #Loads zero into register s0 for i
lw $s1, _j #loads the value of 4 into register s2 for j
Loop:
beq $s0, $s1, Exit #Does the operation i < j in the for-loop
mul $t0, $s0, 4 #Get address of i
add $t1, $t0, $s6 #Finds and stores the base address of a[i]
add $t2, $t0, $s7 #Finds and stores the base address of b[i]
lw $t3, ($t1) #get the value of a[i]
lw $t4, 4($t1) #get the value of a[i + 1]
sub $t5, $t4, $t3 #subtracts a[i + 1] and a[i]
sw $t5, ($t2) #Stores the above into b[i]
add $a0, $zero, $t5
li $v0, 1
syscall
addi $s0, $s0, 1 #Does the operation i++ in the for-loop
j Loop #loops back to beginning
Exit:
li $v0, 10
syscall #syscall to exit the program
Don't mix friendly register names with the raw register names — very confusing.
lw $t3, ($s6) #get the value of a[i]
lw $t4, 4($10) #get the value of a[i + 1]
Here you're mixing $t3, $t4, $s6, and $10, which is actually $t2.
Your assembly code is doing the following C code (modulo the above bug):
int *s6 = A;
int *s7 = B;
for ( int i = 0; i != j; ) {
i++;
int *t1 = s6 + i; // i is automatically scaled by C
int *t2 = s7 + i; // ditto
int t3 = *s6; // A[0]
int t4 = s6[1]; // A[1]
int t5 = t4 - t3;
*t2 = t5; // B[i]=...
}
Can you see why it keeps loading A[0] & A[1]?
You should have noticed these problems during single stepping debugging.  After each step, check that every effect you're expecting happens as you expect.  When it doesn't, look for typos or logic problems.

MIPS error "operand is of incorrect type"

I am trying to convert C code into MIPS assembly code, however I am getting an error:
"$t4": operand is of incorrect type
I could not find the error. Here is my C code and assembly code:
int A[4];
int i;
int diff;
for(i=0; i<3; i++){
diff = A[i+1] - A[i];
if (diff > 0)
A[i] = 5*A[i];
else
A[i+1] = -5*A[i];
}
MIPS code:
.data
intArr: .word 2, 4, 6, 8
.text
main:
la $s3, intArr # address of start of intArr $t1
li $s0, 0 # load loop iteration variable (i) to $s0
li $t2,3 # constant $t2 = 3
Loop:
bge $s0,$t2 end # end program when 3 iterations happened
# diff = intArr[i+1] - intArr[i]
lw $t1,intArr($s3) # $t1=intArr[i]
addi $t3, $s3,4 # intArr[i + 1]
lw $t4,intArr($t3) # $t4 = intArr[i + 1]
sub $t5, $t4,$t1 # diff = $t4 - $t1
bgt $t5,0,else #check if diff($t5) > 0
addi $t6,$zero,$t4
addi $t6,$t6,$t4
addi $t6,$t6,$t4
addi $t6,$t6,$t4
sw $t6,intArr($s3)
else:
subi $t6,$t4,$zero
subi $t6,$t4,$t4
subi $t6,$t4,$t4
subi $t6,$t4,$t4
subi $t6,$t4,$t4
subi $t6,$t4,$t4
subi $t6,$t4,$t4
sw $t6,intArr($s3)
addi $s3, $s3,4 #next element A[i+1]
addi $s0, $s0, 1 #Add immediate value 1 to i (i++)
j Loop #Jump back to the top to loop again
end:
li $v0,10
syscall

Converting C code to mips gives error

This is the C code that i have been converted so far. it gives me some error that i have been included in the following code. i don't understand which part is wrong in this c to mips conversion?
char ch[10];
int i;
for (i = 0; i != 10; i++)
ch[i] = ch[i] – 32
.data
.text
li $v0 4
syscall
#$s1 = i, $s0 base address of ch
addi $s1, $0, 0 #i =0
addi $t0, $0, 10 #t0 = 10
loop: beq $t0, $s1, end
add $t1, $s1, $s0
lw $t2, 0($t1)
addi $t2, $t2, -32
sw $t2, 0($t1)
addi $s1, $s1, 1
j loop
end:
My output:
Runtime exception at 0x00400018: address out of range 0x00000000
From the C code you are converting a char type array and in MIPS you should use lb instead of lw.
In order to print out you need a main: label and also you should declare an array like .byte or .space
You should usesyscall 11 to print a character or syscall 4 to print
string.
I have added some of these mentioned above to your code hope it helps.
.data
#ch: .byte 'a','b','c','d','e'
ch: .space 10
.text
main:
li $v0, 8 #read character
li $a1, 10 #load the space
la $a0, ch
syscall
li $v0,11 #print character
syscall
li $v0,10 # exit program
syscall
addi $s1, $0, 0 #i = 0
addi $t0, $0, 10 # $t0 = 10
loop: beq $t0, $s1, end
add $t1, $s1, $s0
lb $t2, ch($t1)
addi $t2, $t2, -32
sb $t2, ch($t1)
addi $s1, $s1, 1
j loop
end:

Binary Search using recursion in Mips assembly

I have a trouble. I tried to make a binary search algorithm using recursion in mips assembly, but I have some errors that I don't understand how to solve them.
I have an array of 10 integers and I assume that the array is sorted.
this is my code, I appreciate any help and thanks in advance..
.data
arr: .word 40
arrMsg: .asciiz "Enter the array : \n"
posMsg: .asciiz "This value exist in the array and its position is "
pos: .word 0
newline: .asciiz "\n"
valMsg: .asciiz "Enter the value you search for : \n"
val: .word 0
notfound:.asciiz "the value doesn't exist in the array !! \n"
.text
main:
# print the array message
li $v0, 4
la $a0, arrMsg
syscall
# read the array from the user
# put $s0 = i
add $s0, $zero, $zero # i = 0
for:
beq $s0, 40, end
li $v0, 5
syscall
sw $v0, arr($s0) # input arr[i]
addi $s0, $s0, 4 # i = i + 4
j for
end:
# print value message
li $v0, 4
la $a0, valMsg
syscall
# read the value from the user
li $v0, 5
syscall
# store the value in the val variable
sw $v0, val
################################################
## put $s0 = start , $s1 = middle , $s2 = end ##
################################################
li $s0, 0
li $s2, 9
jal BinarySearch
li $v0, 10
syscall
############################################################################################################
BinarySearch:
# middle = (start + end ) / 2
add $t0, $s0, $s2 # $t0 = start + end
sra $s1, $t0, 1 # $s1 = $t0 / 2
# save $ra in the stack
addi $sp, $sp, -4
sw $ra, 0($sp)
# base case
ble $s2, $s0, returnNegative1 # if (end <= start)
lw $t1, arr($s1) # $t1 = arr[middle]
lw $t2, val # $t2 = val
beq $t1, $t2, returnMiddle # if (arr[middle] == val)
blt $t2, $t1, returnFirstPart # if (val < arr[middle])
bgt $t2, $t1, returnLastPart # if (val > arr[middle])
returnNegative1:
li $v0, -1
j Exit
returnMiddle:
move $v0, $s1 # return middle
j Exit
returnFirstPart:
move $t3, $s1 # temp = middle
addi $t3, $t3, -1 # temp --
move $s2, $t3 # end = temp
jal BinarySearch
j Exit
returnLastPart:
move $t3, $s1 # temp = middle
addi $t3, $t3, 1 # temp++
move $s0, $t3 # start = temp
jal BinarySearch
j Exit
Exit:
lw $ra, 0($sp)
addi $sp, $sp, 4`
jr $ra
lw $t1, arr($s1) # $t1 = arr[middle]
this is the problem as it is not really the right index as integer takes 4 bytes
so the middle you get from
add $t0, $s0, $s2 # $t0 = start + end
sra $s1, $t0, 1 # $s1 = $t0 / 2
is just the logical address not the real one you will need to multiply it with 4
mul $s4, $s1,4
and then use $s4 as an address
lw $t1, arr($s4) # $t1 = arr[middle]
also there is a mistake with the stopping condition it should be
if (end < start) not (<=)
and sorry for my English

MIPS code to sum an artithmetic series

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