MIPS: fetch address not aligned on word boundary 0x400fffff - mips

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?

Related

Practice to convert c to Mips

Does anyone know how to convert this into mips 32? Please show the code and explain for me. Thank you so much
int service (int n) {
if (n <= 10)
return n;
else
return n + service(n+1) + service (n+2);
}
Please pay attention on comments and try to understand what is happening instruction by instruction.
service:
lw $t0, $a0 # Load word from memory to $t0. $a0 is the argument of the function (int n).
addi $t1, 10 # $t1 = 10
bne $t0, $t1, cont # If n != 10 , continue
slti $t2, $t1, $t0 # If 10 < n $t2 = 1, else $t2 = 0
bne $t2, $t0, cont # If $t2 != 0 , then $t2 = 1 so 10 < n , so continue
addi $v0, $t0, $0 # Else return n;
jr $ra
cont:
addi $sp, $sp, -4 # Room on stack for 4 bytes
sw $ra, 0($sp) # Save $ra, recursion
addi $a0, $a0, 1 # n+1
jal service # Call service(n+1)
addi $a0, $a0, 1 # (n+1) + 1 = n+2
jal service # Call service(n+2)
lw $ra, 0($sp) # restore $sp
addi $sp, $sp, 4 # Restore room on stack
jr $ra
Here's my try with clarifications
# assuming $a0 is the parameter n
service:
bgt $a0, 10, else # if $a0 > 10 branch to else part
move $v0, $a0 # $v0 = $a0, to return the value
jr $ra # return n;
else:
addiu $sp, $sp, -8 # using stack to store $ra, $a0 each 4 bytes we need 8 bytes
sw $a0, 0($sp) # store the value of a0 in the stack
sw $ra, 4($sp) # store the caller addrs.
addiu $a0, $a0, 1 # parameter of the first function call (n+1)
jal service # service(n+1)
move $s0, $v0 # s0 = result of service(n+1)
lw $a0, 0($sp) # $a0 = n
addiu $a0, $a0, 2 # parameter of the second function call (n+2)
jal service # service(n+1)
move $s1, $v0 # s1 = result of service(n+1)
lw $a0, 0($sp) # $a0 = n
addu $v0, $a0, $s0 # $v0 = n + service(n+1)
addu $v0, $v0, $s1 # $v0 = n + service(n+1) + service(n+2)
lw $ra, 4($sp) # $ra = old caller return addrs.
addiu $sp, $sp, 8 # freeing the stack
jr $ra # return

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

mergesort recursion in mips

I am working with mergesort mips operating on Mars
i run it, the array is arranged but it has some troubles and it announces that error in : invalid program counter value: 0x00000000
Go: execution terminated with errors
please help me
thank you very much
.data # Data declaration section
text1: .asciiz "My array"
text2: .asciiz "Sorted Array"
newline: .asciiz "\n"
space: .asciiz " "
Myarray: .word 9 5 6 8 7 2
mangx: .word 0:20
mangy: .word 0:20
.text
main:
la $a0, Myarray # load dia chi myarray $a1
addi $t1, $zero,4 # size=20
and $a1, $zero, $zero # l=0 a1
addi $a3,$zero,3 #r=19
li $v0, 4
la $a0, text1 #in text1
syscall
li $v0, 4
la $a0, newline #in newline
syscall
and $t4, $zero, $zero # khoi tao i=0 $t4
j LoopPrintUn # nhay den ham in myarray
LoopPrintUn:
la $a0, Myarray # load dia chi myarray $a1
#While (i < length)
slt $t6, $t4, $t1 # neu i < size thi $t6=1, neu khong thi $t6=0
beq $t6, $zero, call # neu $t6=0 thi re qua ham in Sortedarray
# Load Array[i] and print it
sll $t0, $t4, 2 # i * 4
add $t6, $a0, $t0 # chuyen den dia chi phan tu thu i
li $v0, 1 # ham in integer
lw $a0, 0($t6) # load gia tri tai dia chi thu i
syscall # in
li $v0, 4
la $a0, space
syscall #in khoang trang
addi $t4, $t4, 1 # i ++
j LoopPrintUn # lap ham in myarray
MergeSort:
addi $sp, $sp, -20
sw $ra,0($sp)
sw $a3, 12($sp) # r
sw $a1, 8($sp) # l
sw $a0, 4($sp) # a[]
slt $t6, $a1, $a3 # neu l < r $t6=1 neu khong $t6=0
beq $t6, $zero, Exit2 # $t6=0 thi exit2
add $t1, $a1, $a3 # temp1 = l + r
div $t1, $t1, 2 # temp1 = temp1 / 2
add $a3,$t1,$zero
sw $t1,16($sp)
# add $a3, $a2, $zero # m=(l+r)/2 (m thay cho cho r trong mergesort(arr,l,r))
jal MergeSort # mergesort(arr,l,m)
lw $a1,16($sp) #load m
addi $a1,$a1,1
lw $a3,12($sp)#load r
#addi $sp, $sp, 24
jal MergeSort # mergesort(arr,m+1,r)
lw $a0, 4($sp)
lw $a1, 8($sp)
lw $a2, 16($sp)
lw $a3, 12($sp)
jal merge # merge(a,l,m,r)
Exit2:
lw $ra,0($sp)
lw $a0, 4($sp)
lw $a1, 8($sp)
lw $a2, 16($sp)
lw $a3, 12($sp)
addi $sp, $sp, 20
jr $ra
merge:
addi $sp,$sp,-32
sw $ra,0($sp)
sw $s0,4($sp) # bien i
sw $s1,8($sp) # bien j
sw $s2,12($sp) # bien k
sw $s3,16($sp) # bien n1
sw $s4,20($sp) # bien n2
sw $s5,24($sp) # mang X
sw $s6,28($sp) # mang y
la $s5,mangx
la $s6,mangy
sub $s3,$a2,$a1 # m-l
addi $s3,$s3,1 #m-l+1
sub $s4,$a3,$a2 # r-m
move $t0,$0 # bien dem o
move $t1,$0 # bien dem p
loop1:
slt $t3,$t0,$s3 # so sanh o<n1
beq $t3,$0,loop2 # go to toi loop 2 neu $t3=0
sll $t2,$t0,2 # o*4
add $t2,$s5,$t2 # X[0]
add $t5,$a1,$t0 # l+o
sll $t5,$t5,2 # (l+o)*4
add $t5,$a0,$t5 # arr[l+o]
lw $t5,0($t5)
sw $t5,0($t2) # x[o]=arr[l+o]
addi $t0,$t0,1 #o++
j loop1
loop2:
# xuly
slt $t4,$t1,$s4 # so sanh o<n1
beq $t4,$0,exit # go to toi exit neu $tt4=0
addi $t6,$a2,1 # m+1
add $t6,$t6,$t1 #m+1+p
sll $t6,$t6,2 #(m+1+p)*4
sll $t7,$t1,2 # p*4
add $t6,$a0,$t6 # arr[m+1+p]
lw $t6,0($t6)
add $t7,$s6,$t7 # y[p]
sw $t6,0($t7) # y[p]=arr[m+1+p]
addi $t1,$t1,1 #o++
j loop2
#-------------
exit:
move $s0,$0 #i=0
move $s1,$0 # j=0
add $s2,$a1,$0 #k=l
while:
slt $t0,$s0,$s3 #i<n1
beq $t0,$0,loop3
slt $t1,$s1,$s4 #j<n2
beq $t1,$0,loop3
sll $t2,$s0,2 #i*4
sll $t3,$s1,2 #j*4
add $t2,$s5,$t2 #x[i]
lw $t2,0($t2)
add $t3,$s6,$t3 #y[j]
lw $t3,0($t3)
slt $t6,$t2,$t3 # x[i]<y[j]
beq $t6,$0,else #x[i] >y[j] thì làm else còn x[i] <= y[j] lam if
sll $t7,$s2,2 #k*4
add $t7,$a0,$t7 #arr[k]
sw $t2,0($t7) #arr[k]=x[i]
addi $s0,$s0,1 #i++
addi $s2,$s2,1 #k++
else:
sll $t7,$s2,2 #k*4
add $t7,$a0,$t7 #arr[k]
sw $t3,0($t7) #arr[k]=y[j]
addi $s1,$s1,1 #j++
addi $s2,$s2,1 #k++
j while
loop3:
slt $t0,$s0,$s3 #i<n1
beq $t0,$0,loop4
sll $t1,$s2,2 #k*4
add $t1,$a0,$t1 #arr[k]
sll $t2,$s0,2 #i*4
add $t2,$s5,$t2 #x[i]
lw $t2,0($t2)
sw $t2,0($t1) #arr[k]=x[i]
addi $s0,$s0,1 #i++
addi $s2,$s2,1 #k++
j loop3
loop4:
slt $t0,$s1,$s4 #j<n2
beq $t0,$0,exit1
sll $t1,$s2,2 #k*4
add $t1,$a0,$t1 #arr[k]
sll $t2,$s1,2 #j*4
add $t2,$s6,$t2 #y[j]
lw $t2,0($t2)
sw $t2,0($t1) #arr[k]=y[j]
addi $s1,$s1,1 #j++
addi $s2,$s2,1 #k++
j loop4
exit1:
lw $ra,0($sp)
addi $sp,$sp,32
jr $ra
call:
jal MergeSort

MIPS Programs with more than 4 arguments

The following is my code and the final test case. main and printStats are both given, I had to qrite average (which is at the bottom), so look there for problems. This case changes the value of all registers in $f, $t, $a, and $s and adds 2 items to the top of its stack in order to ensure that the average method is preserving properly the values it will need to run its calculations following the $jr from printStats.
The problem I am having is recurring in a few test cases where there are 3 batters. Batter 3 uses arbitrarily large integers.
# printStats puts two values at the top two spots in its stack. This is where
# the number of homeruns and outs were placed when printStats
# is called. A function is allowed to change its own stack.
# Changes the $s registers used by main. The average function should be
# getting arguments from the $a registers and the stack, and not relying
# on what is in the $s registers.
# From test12:
# Tests if $t registers are preserved (if needed) by average.
# printStats puts values into every $t register.
# From test13:
# Tests if $a registers used correctly when average calls printStats.
# printStats changes the contents of $a1, $a2, and $a3 before returning
# test with three batters, both average and slugging percentage
# First batter has no hits, but does have outs
# Second batter has hits and outs, with realistic values
# Third hitter has large values for some of the hits and for the
# outs. This means the hits and outs *have* to be converted from int's
# to float's in order to get the right answer.
.data
mainNumBatters:
.word 3
mainBatter1:
.word 27 # walks
.word 0 # singles
.word 0 # doubles
.word 0 # triples
.word 0 # home runs
.word 423 # outs
mainBatter2:
.word 27 # walks
.word 101 # singles
.word 22 # doubles
.word 4 # triples
.word 10 # home runs
.word 423 # outs
mainBatter3:
.word 102322 # walks
.word 8000000 # singles
.word 22 # doubles
.word 500000 # triples
.word 10 # home runs
.word 23000000 # outs
.data
mainNewline:
.asciiz "\n"
mainBatterNumber:
.asciiz "Batter number: "
mainBattingAverage:
.asciiz "Batting average: "
mainSluggingPercentage:
.asciiz "Slugging percentage: "
mainOnbasePercentage:
.asciiz "On-base percentage: "
.text
main:
# Function prologue -- even main has one
addiu $sp, $sp, -24 # allocate stack space -- default of 24 here
sw $fp, 0($sp) # save frame pointer of caller
sw $ra, 4($sp) # save return address
addiu $fp, $sp, 20 # setup frame pointer of main
# for (i = 0; i < mainNumBatters; i++)
# compute batting average
# compute slugging average
la $s1, mainNumBatters
lw $s6, 0($s1) # $s6 = number of batters
addi $s0, $zero, 0 # $s0 = i = 0
la $s1, mainBatter1 # $s1 = addr of current batter's stats
mainLoopBegin:
slt $t0, $s0, $s6 # $t0 = i < number of batters
beq $t0, $zero, mainDone
la $a0, mainBatterNumber
addi $v0, $zero, 4
syscall
addi $a0, $s0, 1
addi $v0, $zero, 1
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
# Compute the batting average
addi $a0, $zero, 1 # $a0 = 1 = compute batting average
lw $a1, 0($s1) # $a1 = walks
lw $a2, 4($s1) # $a2 = singles
lw $a3, 8($s1) # $a3 = doubles
lw $s2, 12($s1) # $s2 = triples
lw $s3, 16($s1) # $s3 = home runs
lw $s4, 20($s1) # $s4 = outs
sw $s4, -4($sp) # put outs at top of average's stack
sw $s3, -8($sp) # put homeruns 2nd fm top of average's stack
sw $s2, -12($sp) # put triples 3rd fm top of average's stack
jal average
# Print the batting average
mtc1 $v0, $f12 # get result fm $v0 before we print string
la $a0, mainBattingAverage
addi $v0, $zero, 4
syscall
addi $v0, $zero, 2 # print the average
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
syscall
# do it for the slugging percentage
addi $a0, $zero, 2 # $a0 = 2 = compute slugging average
lw $a1, 0($s1) # $a1 = walks
lw $a2, 4($s1) # $a2 = singles
lw $a3, 8($s1) # $a3 = doubles
lw $s2, 12($s1) # $s2 = triples
lw $s3, 16($s1) # $s3 = home runs
lw $s4, 20($s1) # $s4 = outs
sw $s4, -4($sp) # put outs at top of average's stack
sw $s3, -8($sp) # put homeruns 2nd fm top of average's stack
sw $s2, -12($sp) # put triples 3rd fm top of average's stack
jal average
# Print the slugging percentage
mtc1 $v0, $f12 # get result fm $v0 before we print string
la $a0, mainSluggingPercentage
addi $v0, $zero, 4
syscall
addi $v0, $zero, 2 # print the percentage
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
syscall
# do it again for the on-base percentage
addi $a0, $zero, 3 # $a0 = 3 = compute slugging average
lw $a1, 0($s1) # $a1 = walks
lw $a2, 4($s1) # $a2 = singles
lw $a3, 8($s1) # $a3 = doubles
lw $s2, 12($s1) # $s2 = triples
lw $s3, 16($s1) # $s3 = home runs
lw $s4, 20($s1) # $s4 = outs
sw $s4, -4($sp) # put outs at top of average's stack
sw $s3, -8($sp) # put homeruns 2nd fm top of average's stack
sw $s2, -12($sp) # put triples 3rd fm top of average's stack
jal average
# Print the slugging percentage
mtc1 $v0, $f12 # get result fm $v0 before we print string
la $a0, mainOnbasePercentage
addi $v0, $zero, 4
syscall
addi $v0, $zero, 2 # print the percentage
syscall
la $a0, mainNewline
addi $v0, $zero, 4
syscall
syscall
addi $s0, $s0, 1 # i++
addi $s1, $s1, 24 # $s1 = addr of next batter's stats
j mainLoopBegin
mainDone:
# Epilogue for main -- restore stack & frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore frame pointer for caller
addiu $sp, $sp, 24 # restore frame pointer for caller
jr $ra # return to caller
.data
printStatsOuts:
.asciiz "Outs: "
printStatsWalks:
.asciiz "Walks: "
printStatsSingles:
.asciiz "Singles: "
printStatsDoubles:
.asciiz "Doubles: "
printStatsTriples:
.asciiz "Triples: "
printStatsHomeruns:
.asciiz "Home runs: "
printStatsNewline:
.asciiz "\n"
.text
printStats:
# Function prologue
addiu $sp, $sp, -32 # allocate stack space
sw $a3, 20($sp) # save $a0 thru $a3
sw $a2, 16($sp)
sw $a1, 12($sp)
sw $a0, 8($sp)
sw $ra, 4($sp) # save return address
sw $fp, 0($sp) # save frame pointer of caller
addiu $fp, $sp, 28 # setup frame pointer of average
# printStats expects to find the following:
# $a0 = walks
# $a1 = singles
# $a2 = doubles
# $a3 = triples
# 5th argument = homeruns
# 6th argument = outs
# print the outs
la $a0, printStatsOuts
syscall
lw $a0, 0($fp) # the outs are at the top of our stack
addi $v0, $zero, 1
syscall
la $a0, printStatsNewline
addi $v0, $zero, 4
syscall
# print the walks
la $a0, printStatsWalks
addi $v0, $zero, 4
syscall
lw $a0, 8($sp) # the walks were passed in $a0
addi $v0, $zero, 1
syscall
la $a0, printStatsNewline
addi $v0, $zero, 4
syscall
# print the singles
la $a0, printStatsSingles
addi $v0, $zero, 4
syscall
addi $a0, $a1, 0 # the singles were passed in $a1
addi $v0, $zero, 1
syscall
la $a0, printStatsNewline
addi $v0, $zero, 4
syscall
# print the doubles
la $a0, printStatsDoubles
addi $v0, $zero, 4
syscall
addi $a0, $a2, 0 # the doubles were passed in $a2
addi $v0, $zero, 1
syscall
la $a0, printStatsNewline
addi $v0, $zero, 4
syscall
# print the triples
la $a0, printStatsTriples
addi $v0, $zero, 4
syscall
addi $a0, $a3, 0 # the doubles were passed in $a3
addi $v0, $zero, 1
syscall
la $a0, printStatsNewline
addi $v0, $zero, 4
syscall
# print the homeruns
la $a0, printStatsHomeruns
addi $v0, $zero, 4
syscall
lw $a0, -4($fp) # the homeruns are 4 bytes below the top of our stack
addi $v0, $zero, 1
syscall
la $a0, printStatsNewline
addi $v0, $zero, 4
syscall
# Put -1 in $t0, then copy that value to each of the $f registers
addi $t0, $zero, -1
mtc1 $t0, $f0
mtc1 $t0, $f1
mtc1 $t0, $f2
mtc1 $t0, $f3
mtc1 $t0, $f4
mtc1 $t0, $f5
mtc1 $t0, $f6
mtc1 $t0, $f7
mtc1 $t0, $f8
mtc1 $t0, $f9
mtc1 $t0, $f10
mtc1 $t0, $f11
mtc1 $t0, $f12
mtc1 $t0, $f13
mtc1 $t0, $f14
mtc1 $t0, $f15
mtc1 $t0, $f16
mtc1 $t0, $f17
mtc1 $t0, $f18
mtc1 $t0, $f19
mtc1 $t0, $f20
mtc1 $t0, $f21
mtc1 $t0, $f22
mtc1 $t0, $f23
mtc1 $t0, $f24
mtc1 $t0, $f25
mtc1 $t0, $f26
mtc1 $t0, $f27
mtc1 $t0, $f28
mtc1 $t0, $f29
mtc1 $t0, $f30
mtc1 $t0, $f31
# Put various values in the $t registers
addi $t0, $zero, -1111
addi $t1, $zero, -2222
addi $t2, $zero, -3333
addi $t3, $zero, -4444
addi $t4, $zero, -5555
addi $t5, $zero, -6666
addi $t6, $zero, -7777
addi $t7, $zero, -8888
addi $t8, $zero, -9999
addi $t9, $zero, -1111
# Put various values in the $a registers.
addi $a0, $zero, -1111
addi $a1, $zero, -1111
addi $a2, $zero, -2222
addi $a3, $zero, -3333
# Put two values at the top two spots in our stack. This is where
# the number of homeruns and outs were placed when printStats
# is called. A function is allowed to change its own stack.
addi $t7, $zero, -1234
sw $t7, 0($fp)
sw $t7, -4($fp)
printStatsDone:
# Epilogue for printStats -- restore stack & frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore frame pointer for caller
addiu $sp, $sp, 32 # restore frame pointer for caller
jr $ra # return to caller
# Your code goes below this line
average:
#takes 7 arguments
#Arguments $a0-$a3 are put on the Caller's stack
#arguments 5-7 are put on the Callee's stack and called
# Prologue: set up stack and frame pointers for average
addiu $sp, $sp, -36 # allocate stack space -- 36 needed here
sw $fp, 0($sp) # save caller's frame pointer
sw $ra, 4($sp) # save return address
# save parameter values $a0-$a3 on the stack
sw $a0, 8($sp) # designates which calculation to do
sw $a1, 12($sp) # walks
sw $a2, 16($sp) # singles
sw $a3, 20($sp) # doubles
addiu $fp, $sp, 32 # setup average frame pointer
#Allocate proper locations of arguments for printStats
#arguments 5 and 6 (home runs and outs will be placed on stack)
addi $t5, $a0, 0 #$t5 designates which calculation to run
addi $a0, $a1, 0 #walks of printStats
addi $a1, $a2, 0 #singles of printStats
addi $a2, $a3, 0 #doubles of printStats
lw $a3, 24($sp) #triples of printStats
lw $t1, 28($sp) #home runs of printStat
sw $t1, -8($sp) #home runs now 2nd from top of stack
lw $t2, 32($sp) #outs of printStats
sw $t2, -4($sp) #out now top of stack
jal printStats
#restore registers used in average
lw $t2, 32($sp) #outs
lw $t1, 28($sp) #homeruns
lw $a3, 24($sp) #triples
lw $a2, 20($sp) #doubles
lw $a1, 16($sp) #singles
lw $a0, 12($sp) #walks
lw $t5, 8($sp) #compare which calculation to run
#convert outs to float
mtc1 $t2, $f4 #outs = $f4
#hits
#hits = singles + doubles + triples + home runs
add $t3, $a1, $a2 # hits = singles + doubles
add $t3, $t3, $a3 # hits = $t3 + triples
add $t3, $t3, $t1 # hits = $t3 + home runs
mtc1 $t3, $f1 #convert hits to float $f1
#atBats
#atBats = hits + outs
add.s $f2, $f1, $f4 # atBats = hits + outs
mfc1 $t4, $f2 #convert atBats to int for compare
#Compare $t5
#if $t5 == 1, computer batting average
#if $t5 == 2, compute slugging percentage
#if $t5 == 3, compute on-base percentage
addi $t0, $zero, 1 #$t0 = 1
beq $t5, $t0, averageBattingAverage
addi $t0, $zero, 2 #$t0 = 2
beq $t5, $t0, averageSluggingPercentage
addi $t0, $zero, 3 #$t0 = 3
beq $t5, $t0, averageOnBasePercentage
averageBattingAverage:
#batting average
#batting average = hits/atBats
#if atBats == 0, average = 0
#compare atBats
beq $t4, $zero, averageBattingSluggingZero
#batting
div.s $f3, $f1, $f2 #batting average = hits/atBats
#Set to print
mfc1 $v0, $f3 #return $v0 the batting average
j averageDone #done
averageSluggingPercentage:
#Slugging percentage
#slugging percentage = (singles + doubles*2 + triples*3
# + home runs*4)/atBats
#if atBats == 0, percentage = 0
#compare atBats
beq $t4, $zero, averageBattingSluggingZero
#slugging
add $t5, $a2, $a2 #doubles*2
add $t6, $a3, $a3 #$t6 = triples * 2
add $t6, $t6, $a3 #$t6 = triples * 3
add $t7, $t1, $t1 #$t7 = home runs * 2
add $t7, $t7, $t7 #$t7 = home runs * 4
add $t8, $a1, $t5 #$t8 = singles + doubles*2
add $t8, $t8, $t6 #$t8 = $t8 + triples*3
add $t8, $t8, $t7 #$t8 = $t8 + home runs*4
mtc1 $t8, $f1 #convert $t8 to float $f1
div.s $f3, $f1, $f2 #slugging percentage = $f1/atBats
#set to print
mfc1 $v0, $f3 #return $v0 the slugging percentage
j averageDone #done
averageOnBasePercentage:
#On-base percentages
#on-base percentages = (hits + walks)/(atBats + walks)
#if atBats + walks is zero, percentage is zero
add $t6, $t3, $a0 #$t6 = hits + walks
add $t7, $t4, $a0 #$t7 = atBats + walks
#compare atBats + walks
beq $t7, $zero, averageOnBaseZero
#on-base
mtc1 $t6, $f1 #convert $t6 to float $f6
mtc1 $t7, $f2 #convert $t7 to float $f7
div.s $f3, $f1, $f2 #on-base percentage = $f6/$f7
#set to print
mfc1 $v0, $f3 #return $v0 the on-base percentage
j averageDone #done
averageBattingSluggingZero:
#if atBats is zero, batting average and slugging
#percentage are both zero
addi $t0, $zero, 0 #$t0 = 0
mtc1 $t0, $f0 #convert 0 to float $f0
#set to print
mfc1 $v0, $f0 #return $v0 = 0
j averageDone #done
averageOnBaseZero:
#if atBats + walks is zero, on-base percentage
# is also zero
addi $t0, $zero, 0 #$t0 = 0
mtc1 $t0, $f0 #convert 0 to float $f0
#set to print
mfc1 $v0, $f0 #return $v0 = 0
j averageDone #done
averageDone: # Epilogue: restore stack and frame pointers and return
lw $ra, 4($sp) # get return address from stack
lw $fp, 0($sp) # restore the caller's frame pointer
addiu $sp, $sp, 36 # restore the caller's stack pointer
jr $ra # return to caller's code
My outputs are not lining up and I don't get why.
The following is the correct output for batter 3.
Batter number: 3
Outs: 23000000
Walks: 102322
Singles: 8000000
Doubles: 22
Triples: 500000
Home runs: 10
Batting average: 0.26984200
Outs: 23000000
Walks: 102322
Singles: 8000000
Doubles: 22
Triples: 500000
Home runs: 10
Slugging percentage: 0.30158967
Outs: 23000000
Walks: 102322
Singles: 8000000
Doubles: 22
Triples: 500000
Home runs: 10
On-base percentage: 0.27220613
And here's my output, with a ! to mark the inconsistencies
Batter number: 3
Outs: 23000000
Walks: 102322
Singles: 8000000
Doubles: 22
Triples: 500000
Home runs: 10
!Batting average: 0.22532867
Outs: 23000000
Walks: 102322
Singles: 8000000
Doubles: 22
Triples: 500000
Home runs: 10
!Slugging percentage: 0.25183919
Outs: 23000000
Walks: 102322
Singles: 8000000
Doubles: 22
Triples: 500000
Home runs: 10
!On-base percentage: 0.22559348
How are my calculations off for this one batter, and what can I do to fix it?
There are multiple calling conventions, you should figure out which one you are supposed to follow. If you have no documentation, you could look at compiler-generated assembly code, or use a debugger.
That said, judging from the fact that only 4 arguments are passed on the stack, you seem to be using the O32 calling convention. This means, the stack upon entry to your function contains 4 argument slots for saving the first 4 arguments which are passed in the registers $a0-$a3. Following them are all the remaining arguments. So, upon entry to your function, the 5th argument (the first one that is not passed via register) will be at address 16($sp) with the 6th at 20($sp) and the 7th at 24($sp). (This is assuming your arguments are 1 word each.) You subtract 36 from $sp to make space for your locals, thus after that all the offsets increase by that amount, i.e. 5th argument at 52($sp) and so on. You can access them using these addresses.
You then set $fp to $sp + 32. I don't think calling convention mandates any particular value for $fp, so that should be fine. If you subsequently wish to access your arguments relative to $fp, you need to adjust the offsets again to compensate, this time by -32. Thus, 5th argument should be at 20($fp), followed by the rest.

MIPS code for qtspim

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.