MIPS code for qtspim - mips

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.

Related

Trying to print ints in MIPS, coming out as ASCII?

Here is some relevant code. I extracted these ints from a .txt file into buffer, and then use extractInts to format them into an array (intArray). Then I use printArray to loop through it and print. The ints in intArray are stored in a .space of 80 bytes, each in their own word.
My current output:
The array: 14385 57 14130 53 14388 13873 50 13109 13366 14393
My expected output:
The array: 18 9 27 5 48 16 2 53 64 98
# put ints into array
extractInts:
la $s0, buffer # $s0 points to buffer
la $s1, intArray # $s1 points to intArray
li $t0, 0 # i = 0
li $t1, 3 # intLoop max = 3
li $t3, 4 # nextWord max = 4
# loop to place each int within its own word boundary in intArray
intLoop:
beq $t0, $t1, exitLoop # exit loop if i = end of word
lb $t2, ($s0) # $t2 = intArray[]
beq $t2, '\n', nextWord # if $t2 = \n, go to nextWord
beq $t2, '\0', exitLoop # if $t2 = \0, go to exitLoop
sb $t2, ($s1) # save byte in $t2 to intArray[]
addi $t0, $t0, 1 # i++
addi $s0, $s0, 1 # increment buffer
addi $s1, $s1, 1 # increment intArray
j intLoop
# skip to next word
nextWord:
sub $t4, $t3, $t0 # $t4 = 4 - i
add $s1, $s1, $t4 # increment intArray by $t4
li $t0, 0 # restore i to 0
addi $s0, $s0, 1 # increment buffer
j intLoop
printArray:
li $t0, 0 # i = 0
while:
beq $t0, 80, exit # exit if i = end of array
lw $t1, intArray($t0) # $t1 = intArray[$t0]
addi $t0, $t0, 4 # move to next word in intArray
# print current int
li $v0, 1
move $a0, $t1
syscall
# print space
li $v0, 11
li $a0, 32
syscall
j while

Retrieving Data from an Array (cannot seem to get it working)

I'm currently working on a palindrome function in MIPS that takes a char array and returns 0 if it is not a palindrome, else 1. I've got everything seemingly working except for the part where I find data at index i and array.length-i-1. If someone could lead me in the right direction I'd really appreciate it.
Here's the java code I'm going off of:
int Palindrome(char[] s) {
for(int i = 0; i < (s.length / 2); i++) {
if(s[i] != s[s.length - 1 - i])
return 0;
}
return 1;
}
Here's the Palindrome function:
palindrome:
# Get length of array and store it in $t1
addi $sp, $sp, -8
sw $ra, 0($sp)
sw $a0, 4($sp)
li $t1, 0
lengthWhile:
lw $t2, 0($a0)
beq $t2, $zero, startPalindrome
addi $t1, $t1, 1
addi $a0, $a0, 4
j lengthWhile
startPalindrome:
div $t2, $t1, 2 # Stores a.length / 2 into $t2
add $t3, $t3, $zero # i value (0 - (a.length/2 - 1))
add $t4, $t4, $t1
subi $t4, $t4, 1 # a.length-1
# $t1 = a.length
# $t2 = a.length / 2
# $t3 = i
# $t4 = a.length - 1
palLoop:
bge $t3, $t2, exitLoop
sub $t4, $t4, $t3 # Puts a.length-1-i into $t4
sll $t5, $t3, 2
add $t6, $a0, $t5
lw $s1, 0($t6)
sll $s3, $t4, 2
add $t7, $a0, $s3
lw $s2, 0($t7)
bne $s1, $s2, return0
# Increase i and start loop again
addi $t3, $t3, 1
j palLoop
return0:
li $v0, 0
jr $ra
exitLoop:
li $v0, 1
jr $ra
Here's the main:
.data
charArray: .word 'a', 'b', 'c', 'd', 'c', 'w', 'a'
.text
main:
# Palindrom Function
la $a0, charArray
jal palindrome
move $a0, $v0
li $v0, 1
syscall
# Exit Program
li $v0, 10
syscall
Thank you in advance for any help. (To specify, palLoop is where I'm having trouble).
Not directly part of your question, but charArray: .word 'a', 'b', 'c', 'd', 'c', 'w', 'a' is really a word array containing a chatarter value, not a character array.
It looks like that will wok as you are using word array everywhere, however wont wok if you use a proper character array.
add $t3, $t3, $zero is t3 = t3 + 0 - what is t3 prior to that?
add $t4, $t4, $t1 - same comment
sub $t4, $t4, $t3 # Puts a.length-1-i into $t4 - will overwrite a.length-1 (t4) so is going not be right on the 2nd time through the loop.

Iterative Binary Search in MIPS

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

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: fetch address not aligned on word boundary 0x400fffff

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?