Related
[Solved]
We were tasked with writing a bubble sort in MIPS and printing both the unsorted and sorted arrays
I've written the following code to accomplish this.
But when I go to run it, the original array prints as I would expect
Original Array
[34, 23, -1, -2, 0]
But then it prints this for the sorted array.
Sorted Array
[173496791, 1818324585, 1920090400, 686433, 1919898378]
(the Unicode squares do print)
array: .word 34, 23, -1, -2, 0, 89
length: .word 6
original: .asciiz "Original Array\n"
sorted: .asciiz "\nSorted Array\n"
.text
# main()
main:
la $a2, length
lw $a2, 0($a2) # a2 <= n_element
add $t9, $0, $0 # t9 : counter
la $a1, array # a1 = &array[0]
addi $t0, $0, 0 # for t0=0 to
addi $a2, $a2, -1 # because we do [i+1]
#says prints original array
la $a0, original
li $v0, 4
syscall
#prints array
jal print
#printing the string saying sorted
la $a0, sorted
li $v0, 4
syscall
#after printing original we reset the values?
la $a2, length
lw $a2, 0($a2) # a2 <= n_element
add $t9, $0, $0 # t9 : counter
add $t8, $0, $0 # t10 : counter 2
la $a1, array # a1 = &array[0]
addi $t0, $0, 0 # for t0=0 to
addi $a2, $a2, -1 # because we do [i+1]
#see if that worked it did
li $s0, 1 #boolean swapped = false 0=false 1=true
outerLoop:
beqz $s0, exit #if flag is false exit
li $s0, 0
addi $a1, $a1, 4 # next array offset
addi $t9, $t9, 1 # counter++
move $t8 $0
sub $s2, $a2, $t9
innerLoop:
bge $t8, $s2, exitInner
lw $t7, 0($a1) # t7 = array[i]
lw $t8, 4($a1) # t8 = array[i+1]
ble $t7, $t8, skip #if array[i]<= arr[i+1] skip the swapping
sw $t8, 0($a1) #a[i+1] = a[1]
sw $t7, 4($a1) #a[i] = a[i+1]
li $s0, 1#flag update
skip:
addi $t8, $t8, 1 #count
addi $a1, $a1, 4
j innerLoop
exitInner:
j outerLoop
exit:
la $a2, length
lw $a2, 0($a2) # a2 <= n_element
add $t9, $0, $0 # t9 : counter
addi $a2, $a2, -1 # because we do [i+1]
jal print
j quit#end Program
#print array
print:
lw $t7,0($a1) # t7 = array[i]
lw $t8,4($a1) # t8 = array[i+1]
add $a0, $t7, 0
addi $v0, $0, 1 #print int using system call the value stored in a0
syscall
addi $a0, $0, 0x20 # ascii 0x20 = ' '
addi $v0, $0, 11
syscall
addi $a1, $a1, 4 # next array offset
addi $t9, $t9, 1 # counter++
beq $t9, $a2, return #return to the where we were we were at beforehand
j print
return:
jr $ra
quit:
addi $v0, $0, 10
syscall
I think these are memory locations? I'm not sure why it's printing that as it is because I reset my counter values before trying to print. So the question is. Why am I printing memory locations? if that is what is happening
I was sorting in place so I had to reset the array before the print function.
I'm trying to create a iterative binary search in mips, below is my code. It works when searching for the middle value, otherwise it doesnt but i'm not sure why. I'm new to MIPs and trying to get better so any critique is appreciated
.data
myArray: .word 1 4 5 7 9 12 15 17 18 20 21 30
last: #the address that comes after the array
arraySize: .word 11
.globl main
.text
main:
la $s0, myArray # array address
lw $s1, arraySize # arraysize
li $s2, 30 # address of last array entry
jal Binsearch # perform binary search
li $v0, 10
syscall
Binsearch:
li $t0,0 #first = 0
subu $t1, $s1, 1 #last = array size -1
Loop: bge $t0, $t1, DONE # if ! (first < last)
add $t2,$t0,$t1 #first + last
li $t3,2
div $t2, $t3 #$LO = middle index
mflo $t3 #$t3 = middle index
li $s3,4 #load the value 4 into s3
multu $s3, $t3 #multiply middle by 4 to get the offset
mflo $t4 #store the result in t4
add $t4, $s0, $t4 #t4 points to array[mid]
lw $t5, ($t4) #load the value at array[mid] into t5
beq $t5, $s2, return_mid # if t5 == s2 then return the index
blt $t5, $s2, move_right # if t5 < s2 then move right
subu $t1, $t3, 1 #if this line is reached that means that none of the above
j Loop #conditions are true, so t5 > s2, last = mid -1
return_mid:
li $v0, 1
add $a0, $t3, $zero # add the middle index to a0
syscall #print the index
move_right:
addi $t0, $t3, 1 # first = mid + 1
j Loop # jump to Loop
DONE:
li $v0, 1
li $a0, -1
syscall
j $ra #return to the caller
I figured it out, had to test for some corner cases and change the LOOP condition
.data
myArray: .word 1 4 5 7 9 12 15 17 18 20 21 30
last: #the address that comes after the array
arraySize: .word 11
.globl main
.text
main:
la $s0, myArray # array address
lw $s1, arraySize # arraysize
li $s2, 20 #value youre searching for
jal Binsearch # perform binary search
li $v0, 10
syscall
Binsearch:
li $t0,0 #first = 0
move $t1, $s1 #last = array size -1
li $t6,1
li $t7,4 #checks for the last element in the array being the correct value
multu $t7,$t1
mflo $t7
add $t7,$s0,$t7
lw $t5, ($t7)
beq $t5, $s2, last_num # if == then
subu $t1, $s1, 1
Loop: bge $t0, $t1, DONE # if ! (first < last)
add $t2,$t0,$t1 #first + last
li $t3,2
div $t2, $t3 #$LO = middle index
mflo $t3 #$t3 = middle index
beq $t2,$t6, special_case #if first+last = 1 you want totake HI not LO
li $t7,4 #load the value 4 into t7
multu $t7, $t3 #multiply middle by 4 to get the offset
mflo $t4 #store the result in t4
add $t4, $s0, $t4 #t4 points to array[mid]
lw $t5, ($t4) #load the value at array[mid] into t5
beq $t5, $s2, return_mid # if t5 == s2 then return the index
blt $t5, $s2, move_right # if t5 < s2 then move right
subu $t1, $t3, 1 #if this line is reached that means that none of the above
j Loop #conditions are true, so t5 > s2, last = mid -1
special_case:
mfhi $t3 #get the 1 value from hi
li $t7,4 #load the value 4 into t7
multu $t7, $t3 #multiply middle by 4 to get the offset
mflo $t4 #store the result in t4
add $t4, $s0, $t4 #t4 points to array[mid]
lw $t5, ($t4) #load the value at array[mid] into t5
beq $t5, $s2, return_mid # if t5 == s2 then return the index
return_mid:
li $v0, 1
add $a0, $t3, $zero # add the middle index to a0
syscall #print the index
j $ra
move_right:
addi $t0, $t3, 1 # first = mid + 1
j Loop # jump to Loop
last_num:
li $v0, 1
add $a0, $t1, $zero
syscall
j $ra
DONE:
li $v0, 1
li $a0, -1
syscall
j $ra #return to the caller
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
I'm writing a mips program to calculate exponent, but get an error:
Runtime exception at 0x00400158: fetch address not aligned on word boundary 0x400fffff
Any ideas?
The problem line is lw $v0, 0($t0) # $v0 = rev_binary[idx]
.data
prompt1: .asciiz "Enter a base: "
prompt2: .asciiz "Enter an exponential: "
b: .word 0
e: .word 0
rev_binary: .word 0
i: .word 0
result: .word 1
.text
main:
la $a0, prompt1 # print prompt1
addi $v0, $0, 4
syscall
addi $v0, $0, 5 # read b
syscall
move $t0, $v0 # $t0 = b
la $a0, prompt2 # print prompt2
addi $v0, $0, 4
syscall
addi $v0, $0, 5 # read e
syscall
move $t1, $v0 # $t1 = e
addi $sp, $sp, -8 # 2 * 4 = 8 bytes
sw $t1, 4($sp)
sw $t0, 0($sp)
jal power
move $a0, $v0
addi $v0, $0, 1
syscall # print the return value
j end
power:
# save $ra and $fp
addi $sp, $sp, -8
sw $ra, 4($sp)
sw $fp, 0($sp)
#copy $sp to $fp
addi $fp, $sp, 0
# allocate local variables
addi $sp, $sp, -20
# save $sp into $fp
move $fp, $sp
#rev_binary = [ 0 ] * e
lw $a0, 32($sp)
sll $a0, $a0, 2 # $a0 = 4 * e(e << 2)
addi $a0, $a0, 4 # $a0 = 4 * e + 4
addi $v0, $0, 9 # $v0 = 9
syscall # allocate memory
sw $v0, 0($sp)
lw $t0, 32($sp) # $t0 = e
sw $t0, 0($v0) #store the size of rev_binary
sw $0, 4($sp)
while0:
# while e != 0
lw $t0, e # $t0 = e
beq $t0, $0, while0_end # break if e == 0
# e_half = e >> 1
lw $t0, 32($sp) # allocate e_half
srl $t1, $t0, 1 # $t1 = $t0 >> 1
sw $t1, 8($sp) # e_half = $t1
# rev_binary[i] = e - 2 * e_half
lw $t0, 8($sp) # $t0 = e_half
sll $t0, $t0, 1 # $t0 = e_half * 2
lw $t1, e # $t1 = e
sub $t0, $t1, $t0 # $t0 = e - e_half * 2
lw $t1, 4($sp) # $t1 = i
sll $t1, $t1, 2
addi $t1, $t1, 4 # $t1 = i * 4 + 4
lw $t2, rev_binary # $t3 = the address of rev_binary
add $t1, $t1, $t2 # $t1 = the address of rev_binary[i]
sw $t0, 0($t1) # rev_binary[i] = $t0
# i += 1
lw $t0, 4($sp) # $t0 = i
addi $t0, $t0, 1 # $t0 += 1
sw $t0, 4($sp) # i = $t0
# e = e_half
lw $t0, 8($sp) # $t0 = e_half
sw $t0, 32($sp) # e = $t0
addi $sp, $sp, 4 # release local variable n_half
j while0
while0_end:
# rev_binary = rev_binary[:i]
lw $t0, 0($sp) # $t0: the address of rev_binary
lw $t1, 4($sp) # $t1 = i
sw $t1, 0($t0) # set the size of rev_binary to i
# result = 1
addi $t0, $0, 1 # $t0 = 1
sw $t0, 12($sp) # result = $t0
# for j in range(i - 1, -1, -1):
addi $sp, $sp, -4 # allocate j
lw $t0, i # $t0 = i
addi $t0, $t0, -1 # $t0 -= 1
sw $t0, 0($sp) # j = $t0 = i - 1
# idx = len(rev_binary) - 1
lw $t0, 4($sp) # $t0 = i = len(rev_binary)
addi $t0, $t0, -1 # $t0 -= 1
sw $t0, 16($sp) # idx = $t0
while1: # while idx >= 0
lw $t0, 16($sp) # idx = $t0
blt $t0, $0, while1_end # break if idx < 0
# result = result * result
lw $t0, 12($sp) # t0 = result
mul $t0, $t0, $t0
sw $t0, 12($sp) # $t0 = result
# if rev_binary[idx]
lw $t0, 16($sp) # $t0 = idx
sll $t0, $t0, 2 # $t0 = idx * 4
addi $t0, $t0, 4 # $t0 = idx * 4 + 4
lw $t1, 0($sp) # $t1 = the address of rev_binary
add $t0, $t1, $t0 # $t0 = the address of rev_binary[idx]
lw $v0, 0($t0) # $v0 = rev_binary[idx]
if:
beq $t0, $0, end_if # end if if (idx == 0)
# result = result * b
lw $t0, 12($sp) # $t0 = result
lw $t1, 28($sp) # $t1 = b
mul $t0, $t0, $t1 # $t0 = $t0 * $t1
sw $t0, 12($sp) # result = $t0
end_if:
# idx = idx - 1
lw $t0, 16($sp) # $t0 = idx
addi $t0, $t0, -1 # $t0 -= 1
sw $t0, 16($sp) # idx = $t0
j while1 # loop
while1_end:
lw $v0, 12($sp) # $v0 = result
lw $t0, 20($sp) # reset old $fp
move $fp, $t0
lw $t0, 24($sp) # reset old $ra
move $ra, $t0
addi $sp, $sp, 36 # release local variables
jr $ra # return
end:
# exit
You can only load words from aligned addresses. The address also looks strange since it has 0xffff in the end.
Looking at the code you have
lw $t1, 0($sp) # $t1 = the address of rev_binary
but before that you store j to (0)$sp, so that can't contain the address of rev_binary. Maybe you need
la $t1, rev_binary # $t1 = the address of rev_binary
instead?
Hello I'm trying to debug this code. It gives the wrong values for its registers. The code is to test some simple arithmetic and storing of values in different registers. Thank you for your help!
.ent main
main:
addi $a0, $0, 10 # r4 = 0 + 10
addi $a1, $0, 1 # r5 = 0 + 1
sltiu $s1, $a1, 2 # set if a1 < 2
add $t0, $t0, $0 # $t0 = 0
add $t1, $t1, $a1 # $t1 = $a1 (t1 = 1)
$count:
add $t0, $t0, $t1 # $t0 = $t0 + $t1 (t0 += 1)
slti $s1, $t0, 10 # if(a1 < 10) s1 = 1 else s1 = 0
beq $s1, $a1, $count # while to < 10
sub $s1, $s1, $a0 # s1 = s1 - a1
and $s1, $s1, $a0 # s1 = s1 $ a0
or $s2, $0, $s1 # s2 = 0 | a0
j $store # store result
$recount:
sub $s1, $s1, $a1 # t0 = 0
$store:
sw $s1,0($29) # store s1 on stack
slti $t3, $s1, 0 # if s1 < 0
beq $s1, $0, $recount # goto recount
lui $t3, 5 # load 5 into $t3
slt $s3, $t3, $t0 # if t3 < t0
beq $s1, $0, $end # goto end
add $t0, $t0, $0 # t0 = 0
sw $s1, 0($29) # store $s3 in $s1
lw $s4, 4($29) # pop stack
$end:
jr $31
.end main
I'm not sure where the errors are, but in these cases the comments and code do not correspond:
1
add $t0, $t0, $0 # $t0 = 0
should be
li $t0, 0 # $t0 = 0
2
add $t1, $t1, $a1 # $t1 = $a1 (t1 = 1)
should be
move $t1, $a1 # $t1 = $a1 (t1 = 1)
3
sub $s1, $s1, $a1 # t0 = 0
should be
li $t1, 0 # t0 = 0
4
Pushing on the stack is
addi $sp, $sp, -4
sw $t0, 0($sp)
Popping:
lw $t0, 0($sp)
addi $sp, $sp, 4
If you can provide more details on where exactly is goes wrong, we can help better.