use of offset in MIPS - mips

Suppose $t0 stores the base address of word array, $s0 is associated with position, and $s1 is associated with offset.I have to convert the following program segment into Assembly and write down the resulting array content
array = [0,1,2,3,4,5,6,7,8,9,10,11]
position = 0
offset = 1
while position < 11:
array[position] = array [position + offset]
position = position + 1;
so far i have written this-
.data
array:
.word 0,1,2,3,4,5,6,7,8,9,10,11
counter: .word 11
lw $t1,counter
la $t0,array
li $s0,0
li $s1,1
loop:
beq $s0,$t1,end
lb $s0,0($t0)
add $s0,$s0,#s1
sll $s0,$s0,2
add $s0,$t0,s0
sw $s1,($s0)
addi $s0,$s0,1
addi $t0,$t0,4
j loop
end:
i dont know how to move forward from here , can anyone help

Try this code :
.data
array:
.word 0,1,2,3,4,5,6,7,8,9,10,11
counter: .word 44 # 11 *4 bytes
.text
.globl main
main:
lw $t1,counter
la $s0,array # array[i]
la $s1,array #
add $s1,$s1,4 # array[i+1]
la $s2,array
li $s3,0 # position
li $s4,4 # offset = 4 bytes
li $t4,0
loop:
beq $s3,$t1,end
add $t4,$s3,$s4 # $t4 = position + offset
lw $t3,($s1)
sw $t3,($s0)
add $s0,$s0,4
add $s1,$s1,4
add $s3,$s3,4
j loop
end:
li $a0, 0
li $v0, 17 #exit
syscall

Related

MIPS program to find the positive sum and negative sum of an array

Here is the code to find the sum of positive number and negative number. However, the code have arithmetic overflow when running (runtime exception at 0x00400034). The basic idea is to use the for loop but the error occured. Did I miss any element for doing the for loop?
.data
array: .word -13, 82, 56, 63, -54
length: .word 10
newLine: .ascii "\n"
posSumMsg: .ascii "Positive value = "
negSumMsg: .ascii "Negative value = "
posSum: .word 0
negSum: .word 0
.text
.globl main
main:
la $t0, array #the starting address of the array
li $t1, 0 # set the loop index, where i = 0
lw $t2, length # length
li $t3, 0 # initialize the sum to be 0 for pos_sum
li $t5, 0 # initialize for neg_sum
#start of loop
sumLoop:
lw $t4, ($t0) #get the array[i]
blt $t4, 0, getNegSum #jump to the negative sum calculation block for negative number
bgt $t4,0, getPosSum #jump to positive sum calculation block for positive number
#calcuates the sum for positive numbers
getPosSum:
add $t3, $t3, $t4 #sum = sum + array[i]
j loopback
getNegSum:
add $t5, $t5, $t4
#loopback of the array
loopback:
add $t1, $t1, 1 #i = i+1
add $t0, $t0, 4 # update the address of the array
bnez $t4, sumLoop # stop the for loop if the last elemnt is a 0, otherwise loop back
#store the sum
sw $t3, posSum
sw $t5, negSum
#print a message
li $v0, 4
la $a0, posSumMsg
syscall
#print value
li $v0, 1
move $a0, $t3
syscall
#print a message
li $v0, 4
la $a0, negSumMsg
syscall
#print a value
li $v0, 1
move $a0, $t5
syscall
#Terminate the program
li $v0, 10
syscall
.end main

how to find min and max in an array MIPS

i can find the max perfectly fine but when it comes to finding the min, im having some trouble, my max finds the max number good but my min always prints out 0 no matter what, i cant seem to find out what is wrong with my code, does anyone see the flaw in my code?
For exmaple:
i enter in 5 integers
5 10 15 20 25
Array: 5,10,15,20,25
Min: 0
Max: 25
.text
.globl main
main:
la $a0, ask #ask user for integer thats going to be the size of the array
li $v0, 4
syscall
li $v0, 5 #store that int
syscall
move $t1,$v0 #size of my array stored in $t1
la $t0, array #load address of our array
li $t2, 0 #counter = 0
lw $t3,($t0) #initialize min = array[0]
lw $t4,($t0) #initialize max = array[0]
while:
la $a0, intask #ask user for integer
li $v0, 4
syscall
li $v0, 5 #store that int
syscall
sw $v0, ($t0) #store that int in the array
end: add $t0, $t0, 4 #increment the array to the next index
add $t2, $t2, 1 #increment the counter by 1
blt $t2, $t1,while #branch to while if counter < size of array
endw:
la $a0,display # Display "Array is: "
li $v0,4
syscall
li $t0, 0 # initilize array index value back to 0
li $t2, 0 # initial size counter back to zero
la $t0, array # load address of array back into $t0
sprint:
lw $t6,($t0) #load word into temp $t2
move $a0, $t6 #store it to a safer place
li $v0, 1 #print it out
syscall
la $a0,space # Display " "
li $v0,4
syscall
add $t0, $t0, 4 #increment the array to the next index
add $t2, $t2, 1 #increment the counter by 1
blt $t2, $t1,sprint #branch to while if counter < size of array
li $t2, 0 # initial size counter back to zero
la $t0, array # load address of array back into $t0
add $t0, $t0, 4 #increment the array to the next index
add $t2, $t2, 1 #increment the counter by 1
loop: lw $t8,($t0) # t8 = next element in array
bge $t8, $t3, notMin #if array element is >= min goto notMin
move $t3,$t8 #min = array[i]
j notMax
notMin: ble $t8,$t4, notMax #if array element is <= max goto notMax
move $t4,$t8 #max = array[i]
notMax: add $t2,$t2,1 #incr counter
add $t0,$t0, 4 #go up in index
blt $t2, $t1,loop #if counter < size, go to loop
eprint:
la $a0,nextline # Display "\n"
li $v0,4
syscall
la $a0,min # Display "min number is "
li $v0,4
syscall
move $a0, $t3 #displays min number in array
li $v0,1
syscall
la $a0,nextline # Display "\n"
li $v0,4
syscall
la $a0,max # Display "max number is "
li $v0,4
syscall
move $a0, $t4 #displays max number in array
li $v0,1
syscall
li $v0,10 # End Of Program
syscall
.data
array: .space 100
ask: .asciiz "How many numbers will be entered? no more than 15 numbers!: "
intask: .asciiz "Enter an Integer: "
min: .asciiz "The minimum number is: "
max: .asciiz "The maximum number is: "
display: .asciiz "Array: "
space: .asciiz " "
nextline: .asciiz "\n"
You are initializing $t3 (which is used for storing min) to array[0] before any values are stored in array, so $t3 ends up being initialized to 0.
It should be fine if you initialize $t3 to array[0] after values have been entered into array.

Finding min element of array in MIPS

I have seen that this question was already asked, but I'm trying to find why this logic is not working. I have tried this code, translating it to C++ and it is working fine. But here it is printing the last element of the array. Help?
.data
Array: .word 500 100 250 150
Len: .word 4
Sum: .word 0
Average: .word 0
NewLine: .asciiz "\n"
Min: .word 9999
Max: .word -9999
.text
la $t0, Array # Base address
li $t1, 0 # i = 0
lw $t2, Len # $t2 = Len
li $t3, 0 # Sum = 0
li $t5, 0 # Average = 0
la $t6, NewLine
lw $t7, Min # $t7 = min
lw $t8, Max # $t8 = max
while:
lw $t4, ($t0) # Array[i]
add $t3, $t3, $t4 # sum += Array[i]
blt $t4, $t7, else # If first element is < 9999, go to else
else: move $t7, $t4 # Min = Array[i]
add $t1, $t1, 1 # Increment index by 1
add $t0, $t0, 4 # Go to next array element
blt $t1, $t2, while # Do this cycle till i < $t2 (length)
sw $t3, Sum
div $t5, $t3, $t2 # Calculate avg.
sw $t5, Average
# Print sum
li $v0, 1
move $a0, $t3
syscall
# Print new line
li $v0, 4
move $a0, $t6
syscall
# Print average
li $v0, 1
move $a0, $t5
syscall
# Print new line
li $v0, 4
move $a0, $t6
syscall
# Print min element
li $v0, 1
move $a0, $t7
syscall
Compiler reads the code from up to down, let's look at calculating the minimum part of your code:
blt $t4, $t7, else # If first element is < 9999, go to else
else: move $t7, $t4 # Min = Array[i]
In the first line, it branches to else if $t4 < $t7. Looks fine for this situaton but if $t4 < $t7 it skips branching, then pass to the next line which is your else. So, that blz is uselles here because it will go the else line anyway so this code will always print the last element of your array.
But if you change your code like:
blt $t7, $t4, else # If first element is < 9999, go to else
move $t7, $t4 # Min = Array[i]
else:
...
It will skip "move $t7, $t4 line" if $t7 > $t4, so it will give you what you want.

Mips Instruction Code

I am trying to solve a problem of addition of elements in an array in mips.
I have to insert nops or rearrange the code so it works but I am not able to. Can someone suggest some Ideas. Thanks
This is a way using a loop by which you can traverse through the array and calculate the sum of all its element:
.data
newline: .asciiz "\n"
array: .word 1, 3, 5, 7, 9, 12, 14, 15, 17, 19
length: .word 10
sum: .word 0
.text
.globl main
main:
#loop through the array to calculate sum
#array's starting address
la $t0 array
#loop index, i=0 ($t1=i)
li $t1 0
#loading the length of array in register t2
lw $t2 length
#initialise sum =0
li $t3 0
sumLoop:
#get array[i]
lw $t4 ($t0)
#sum = sum+array[i]
add $t3 $t3 $t4
#updating countervariable
addi $t1 $t1 1 #i = i+1
add $t0 $t0 4 #update array address
#while i<length , traverse the loop again
#blt (branch less than) (if $t1<$t2 then go through the loop)
blt $t1 $t2 sumLoop
sw $t3 sum #save sum
#printing the sum on syscall
move $a0 $t3
li $v0 1
syscall
li $v0 10
syscall
.end main

Trouble with division using shifting

I'm having some trouble implementing a division algorithm with MIPS, I'm assuming it has something to do with the way that I'm shifting and setting the least significant bit, but I'm not entirely sure.
The algorithm goes like this:
1) Subtract the divisor register from the remainder register and place the result in the remainder register.
2a) If the remainder >= 0, shift the quotient register to the left, setting the new rightmost bit to 1
2b) If the remainder <0, Add the divisor register to the remainder register and store the result in the remainder register (to restore the remainders previous value). Shifht the quotient register to the right, setting the rightmost bit to 0.
3) Shift the divisor register right one bit
4) Do this n+1 repititions. Since we are doing unsigned 8-bit division, i would assume this to mean 9 repitions
Edit: To make this simpler, I just set $t0 = 12 and $t1 = 5. However for the quotient i get 63 and the remainder I get 0
.data
quotient_a: .asciiz "Quotient (a/b): "
remainder_a: .asciiz "Remainder (a/b):"
quotient_b: .asciiz "Quotient (b/a): "
remainder_b: .asciiz "Remainder (b/a):"
error: .asciiz "Sorry, divide-by-zero not allowed"
new_line: .asciiz "\n"
.text
main:
li $s0, 8 #8 bit
li $t0, 12
li $t1, 5
## Quotient A message
la $a0, quotient_a # load the addr of display_sum into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
##Computer the Quotient and remainder
## $t0 = a $t1 = b
## $t0 = dividend $t1 = divisor
li $t2, 0 ##Quotient
li $t3, 0 ##Remainder
li $t9, 0 ##i
li $s0, 9 ##count
loop:
sub $t3, $t3, $t1
blt $t3, 0, less_than
## >= 0
sll $t2, $t2, 1
addi $t2, $t2, 1
j cont
less_than:
add $t3, $t3, $t1
sll $t2, $t2, 1
cont:
srl $t1, $t1, 1
addi $t9, $t9, 1
bne $t9, $s0, loop
## print the quotient
move $a0, $t2
li $v0, 1 # load syscall print_int into $v0.
syscall # make the syscall.
## new line
la $a0, new_line # load the addr of new_line into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall
## Remainder A message
la $a0, remainder_a # load the addr of display_sum into $a0.
li $v0, 4 # 4 is the print_string syscall.
syscall # do the syscall.
## print the remainder
move $a0, $t3
li $v0, 1 # load syscall print_int into $v0.
syscall # make the syscall.
#Exit Program
li $v0, 10 # syscall code 10 is for exit.
syscall # make the syscall.
The description of the algorithm looks a bit off to me. This is what a working 8-bit division algorithm in C looks like:
unsigned char Q,R;
unsigned char N=12,D=5;
int i;
Q = 0;
R = 0;
for (i = 0; i < 8; i++) {
R <<= 1;
R |= (N & 0x80) >> 7;
N <<= 1;
Q <<= 1;
if (R >= D) {
R -= D;
Q |= 1;
}
}
Transcribing that into MIPS assembly shouldn't be too difficult.