Converting C to mips assembly, Unaligned address error - c

i'm doing an assignment now, it's almost done but i keep getting error saying
Unaligned address in inst/data fetch: 0x10010016
at line:
lw $t3,0($a1) # get the value of b[k] and save it into t3
I search online and i find an answer saying i have to use .align 2 to fix this, but that doesn't work for my problem.
can someone please give me a hint on this, I literally spend 6 hours on this..
thank you very much
Here is my code:
# a -> $a0
# b -> $a1
# n -> $a2
# j -> $a3
# k -> $s0
# i -> $t0
.data
.align 2
arra: .word 1,2,7,4,5
arrb: .word 3,4,7,2,9
.text
la $a0, arra # we have array a[] = { 1,2,7,4,5}
la $a1, arrb # we have array b[] = {3,4,7,2,9}
addi $a2,$zero,0 # n = 0
addi $a2,$zero,3 # n = 3
addi $a3,$zero,0 # j = 0
addi $a3,$zero,3 # j = 3
addi $s0,$zero,0 # k = 0
addi $s0,$zero,2 # k = 2
g:
addi $sp, $sp, -24
sw $ra, 20($sp) # save $ra on stack
sw $s0, 16($sp) # save $s0 (k) on stack
sw $a0, 12($sp) # save a0(a) on stack
sw $a1, 8($sp) # save a1(b) on stack
sw $a2, 4($sp) # save a2(n) on stack
sw $a3, 0($sp) # save a3(j) on stack
move $a3,$s0 # set j = k
jal f # f(a,b,n,k,k)
add $a1,$a1,$s0 # return the address of b[k]
lw $t3,0($a1) # get the value of b[k] and save it into t3
add $v0, $t3,$zero # return the value
lw $a3,0($sp)
lw $a2,4($sp)
lw $a1,8($sp)
lw $a0,12($sp)
lw $s0,16($sp)
lw $ra,20($sp)
addi $sp,$sp,24
jr $ra
f:
bne $a2, $zero, ELSE # if (n != 0) go to ELSE
addi $t0, $zero, 1 # set $t0 = 1
sw $t0, 0($a1) # then set b[0] = 1
addi $t0, $zero, 1 # set $t0 = 1
sw $t0, 0($a1) # then set b[0] = 1
addi $t0, $zero, 1 # set i = 1 for the loop
forLoop:
slt $t1,$s0, $t0 # if k < i, end the loop, use $t1 to store the boolean value
bne $t1, 1, forLoopDone
add $a1, $a1, $t0 # b[i] address
add $t2,$zero,$zero
sw $t2, 0($a1) # b[i] = 0
addi $t0, $t0, 1 # i = i + 1
j forLoop
ELSE:
bne $a3, $zero, updateJ # test if (j == 0), if not, j = j -1
j iteratef
updateJ:
addi $a3, $a3, -1 # j = j -1
j iteratef
iteratef:
addi $a2, $a2, -1 # iterate, n = n - 1
j f # f(b, a, n-1, j_update, k)
bne $a3, $zero, forLoop1Ini # if (j != 0), go to for_loop1_ini
lw $a0, 0($a0) # there might be sth wrong here
sw $a1, 0($a1) # set b[0] = a[0]
addi $a3, $a3, 1 # j++
forLoop1Ini:
addi $t0, $a3, 0 # set i = j
forLoop1Start:
slt $t1,$s0, $t0
bne $t1, 1, forLoop1Done
add $a0, $a0, $t0 # get a[i] address
lw $t1, 0($a0) # t1 = a[i]
lw $t2, -4($a0) # get b[i]
add $a1, $a1, $t0 # get b[i] address
add $t1, $t1, $t2 # t1 = a[i-1] + a[i]
sw $t1, 0($t1) # b[i] = a[i-1] + a[i]
addi $t0, $t0, 1 # i++
j forLoop1Start
forLoop1Done:
nop
forLoopDone:
nop
jr $ra

Your problem is that you are not taking into account the size of each element of the array. Each element occupies 4 bytes.
Therefore, instead of issuing
add $a1,$a1,$s0 # return the address of b[k]
you should multiply the index by 4 (which is the size of element) to get the effective offset:
sll $s1, $s0, 2 # Compute effective offset (i.e. multiply index by 4)
add $a1,$a1,$s1 # return the address of b[k]
lw $t3,0($a1) # get the value of b[k] and save it into t3

Related

Function to find the MAX and its position on an array

I have to find the max element and its position on an array(the position starts with 1)( if the array doesn't contain any elements I have to return position=0 and max=smallest negative number). I think that my code is ok (apart from setting the max to the lowest number possible, that I have doubt about) but I have no idea what I need to start my code with, like save the last thing stored in the registers. Also I can't compile it (probably because of the pseudo-instructions).
I have tried writing my program in c and then compiling to MIPS but it still wouldn't work.
MaxAndArg:
li $v0, -2,147,483,648 # $v0(MAX) is the smallest negative number
li $v1, 0 # $v1(POSITION) starts from zero
li $t3, 0 # $t3(i in a normal language) will be used to loop
li $t4, 0 # $t4 will be used to show the position in the array
L2:
beq $t3, $a1, EXIT # if (i = array size) goto EXIT
sll $t4, $t4, 2 # $t4 = $t4 * 4
add $a0, $t4, $a0 # $a0 = $a0 + $t4 (next element in the array)
blt $v0, a0, L1 # if (max < a[j]) goto L1
addi $t3, $t3, 1 # i++
addi $t4, $t4, 1 # array_position++
j L2
L1:
addi $v0, $a0, 0 # $v0 = $a0
addi $v1, $t3, 1 # $v1 = i + 1 (probably works)
addi $t3, $t3, 1 # i++
addi $t4, $t4, 1 # array_position++
j L2
EXIT:
jr $ra #return

MIPS Assembly - Matrix Multiplication Arithmetic Overflow Errors?

Down below is my code from a MIPS hw assignment where we have to multiply two matrixes. Our task was to implement the matrix_multiply function and matrix_print function
.data
matrix_a: .word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
matrix_b: .word 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16
result: .word 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
newline: .asciiz "\n"
tab: .asciiz "\t"
#############################################################################
#############################################################################
## Text segment
#############################################################################
#############################################################################
.text # this is program code
.align 2 # instructions must be on word boundaries
.globl main # main is a global label
.globl multiply
.globl matrix_multiply
.globl matrix_print
.globl matrix_ask
#############################################################################
matrix_ask:
#############################################################################
# Ask the user for the current matrix residing in the $a0 register
sub $sp, $sp, 4
sw $ra, 0($sp)
# init our counter
li $t0, 0
# t1 holds our the address of our matrix
move $t1, $a0
ma_head:
# if counter less than 16, go to ma_body
# else go to exit
li $t2, 16
blt $t0, $t2, ma_body
j ma_exit
ma_body:
# read int
li $v0, 5
syscall
li $t2, 4
# ints are 4 bytes
multu $t0, $t2
mflo $t2
add $t2, $t2, $t1
sw $v0, 0($t2)
j ma_latch
ma_latch:
addi $t0, $t0, 1
j ma_head
ma_exit:
lw $ra, 0($sp)
add $sp, $sp, 4
jr $ra
#############################################################################
main:
#############################################################################
# alloc stack and store $ra
sub $sp, $sp, 4
sw $ra, 0($sp)
# load A, B, and result into arg regs
la $a0, matrix_a
jal matrix_ask
la $a0, matrix_b
jal matrix_ask
la $a0, matrix_a
la $a1, matrix_b
la $a2, result
jal matrix_multiply
la $a0, result
jal matrix_print
# restore $ra, free stack and return
lw $ra, 0($sp)
add $sp, $sp, 4
jr $ra
##############################################################################
multiply:
##############################################################################
# mult subroutine $a0 times $a1 and returns in $v0
# start with $t0 = 0
add $t0,$zero,$zero
mult_loop:
# loop on a1
beq $a1,$zero,mult_eol
add $t0,$t0,$a0
sub $a1,$a1,1
j mult_loop
mult_eol:
# put the result in $v0
add $v0,$t0,$zero
jr $ra
##############################################################################
matrix_multiply:
##############################################################################
# mult matrices A and B together of square size N and store in result.
# alloc stack and store regs
sub $sp, $sp, 24
sw $ra, 0($sp)
sw $a0, 4($sp)
sw $a1, 8($sp)
sw $s0, 12($sp)
sw $s1, 16($sp)
sw $s2, 20($sp)
add $t5, $zero, $zero #Set t5 to zero. i = 0
add $t6, $zero, $zero #Set t6 to zero. j = 0
add $t7, $zero, $zero #Set t7 to zero. k = 0
#setup for i loop
iLoop:
beq $t5, 4, exit
j jLoop
#setup for j loop
jLoop:
beq $t6, 4, iEnd
#setup for k loop
kLoop:
beq $t7, 4, jEnd
# compute A[i][k] address and load into $t3
# A[i][k] = A+4*((4*i) + k)
sll $t3, $t5, 2 # Store 4*i in $t3
addu $t3, $t3, $t7 # Adds $t3 to k
sll $t8, $t3, 2 # Computes 4*($t3) = 4*(4*i+k) by temporarily storing the product in $t8
move $t3, $t8 # Stores 4*($t3) into $t3
addu $t3, $t3, $a0 # Adds A to $t3
lw $t3 0($t3)
# compute B[k][j] address and load into $t4
# B[k][j] = B+4*((4*k) + j)
sll $t4, $t7, 2 # Stores 4*k in $t3
addu $t4, $t4, $t6 # Adds $t4 to j
sll $t8, $t4, 2 # Computes 4*($t4) = 4*(4*k+j) by temporarily storing the product in $t8
move $t4, $t8 # Stores 4*($t4) into $t4
addu $t4, $t4, $a1 # Adds B to $t4
lw $t4 0($t4)
# call the multiply function
multu $t3, $t4
mflo $t9
# compute RESULT[i][j] address and load into $t1
# RESULT[i][j] = RESULT+4*((4*i) + j)
sll $t1, $t5, 2 # Store 4*i in $t1
addu $t1, $t1, $t6 # Adds $t1 to j
sll $t8, $t1, 2 # Computes 4*($t1) = 4*(4*i+k) by temporarily storing the product in $t8
move $t1, $t8 # Stores 4*($t1) into $t1
addu $t1, $t1, $a2 # Adds A to $t3
lw $t1 0($t1)
sw $a2 0($t9) # Store $t9 into its respective location in $a2
# increment k and jump back or exit
addi $t7, $t7, 1
j kLoop
jEnd:
#increment j and jump back or exit
addi $t6, $t6, 1
li $t7, 0
j jLoop
iEnd:
#increment i and jump back or exit
addi $t5, $t5, 1
li $t6, 0
j iLoop
exit:
# retore saved regs from stack
lw $s2, 20($sp)
lw $s1, 16($sp)
lw $s0, 12($sp)
lw $a1, 8($sp)
lw $a0, 4($sp)
lw $ra, 0($sp)
# free stack and return
add $sp, $sp, 24
jr $ra
##############################################################################
matrix_print:
##############################################################################
# alloc stack and store regs.
sub $sp, $sp, 16
sw $ra, 0($sp)
sw $s0, 4($sp)
sw $s1, 8($sp)
sw $a0, 12($sp)
li $t0, 4 # size of array
# do your two loops here
# setup to jump back and return
lw $ra, 0($sp)
lw $s0, 4($sp)
lw $s1, 8($sp)
lw $a0, 12($sp)
add $sp, $sp, 16
jr $ra
I keep getting one of the two following errors - Either I get an error saying Exception occurred at PC=0x004000cc, Arithmetic overflow or "The Following Symbols are Undefined" and it lists iEnd, matrix_print, exit, and jEnd. I don't know why those symbols would be "undefined since they're clearly written in my code, and they don't have to be "global" symbols, otherwise matrix_print wouldn't have been included in that list.
I realize I haven't yet implemented my matrix_print, but I'll get to that once I figure out what's causing the more pressing issue, which is my Arithmetic Overflow error. I use sll knowing I need to multiply by 4, and sll is the best way to approach it. I don't believe I'm going out of bounds anywhere either, so if someone can please help me debug this I would greatly appreciate it. Thanks!

MIPS implementation of selection sort outputting correct values

I am attempting to implement selection sort in MIPS. My output occasionally correct, but there are several instances where it is incorrect. Usually it is correct up until some point and after that point the numbers print out unsorted. It also appears to have difficulty with multiple negative numbers.
I believe the issue may be with the swap function but I am not sure.
Any help would be greatly appreciated.
Note: I am not allowed to use pseudo-instructions, such as bge or move.
Here is my code in the C implementation I'm emulating.
.data
msg1: .asciiz "The elements sorted in ascending order are:"
.align 2
space: .asciiz " "
.align 2
comma: .asciiz ","
.align 2
arr: .space 80
.text
MAIN:
# Ask for user input and put value in $s1
addi $v0, $zero, 5 # call service 5 for integer input
syscall # read integer
add $s1, $zero, $v0 # Save $t0 = len
# Load address for arr
la $s0, arr # Pointer to arr goes in $t1
add $a0, $zero, $s0 # Save arr pointer to $a0
add $a1, $zero, $s1 # Save len to $a1
# Ask for user input to fill arr
jal FILL
# Sort the list using selection sort
jal SORT
# Print list
jal PRINT
# Call to end program
addi $v0, $zero, 10 # system call for exit
syscall
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
FILL: # deal with stack and save
addi $t0, $zero, 0 # $t0 = counter = 0
FILL_LOOP:
slt $t1, $t0, $a1 # if(counter < len) continue
beq $t1, $zero, FILL_RETURN # if(counter >= len) branch out of loop
addi $v0, $zero 5 # call service 5 for integer input
syscall # read integer
addi $t2, $zero, 0 # clear $t2 and set to 0
add $t2, $zero, $v0 # $t2 holds input integer
add $t3, $zero, $t0 # $t3 = i
sll $t3, $t3, 2 # $t3 = counter * 4
add $t3, $t3, $a0 # addr of arr[counter]
sw $t2, 0($t3) # store values in arr
addi $t0, $t0, 1 # counter = counter + 1
j FILL_LOOP
FILL_RETURN:
jr $ra # Return
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
SORT:
addi $sp, $sp, -28 # make space for variables
sw $a0, 0($sp) # store $a0 (arr)
sw $a1, 4($sp) # store $a1 (len)
sw $ra, 8($sp) # store return address
sw $s0, 12($sp) # store $s0 ( i )
sw $s1, 16($sp) # store $s1 ( j )
sw $s2, 20($sp) # store $s2 (tmp)
sw $s3, 24($sp) # store $s3 (minIndex)
addi $s0, $zero, 0 # i = 0
add $t0, $zero, $a1 # $t0 = len
addi $t0, $t0, -1 # $t0 = len - 1
FOR_1:
slt $t1, $s0, $t0 # i < $t0 = len - 1 continue
beq $t1, $zero, SORT_RETURN # if !(i < len - 1) branch out of loop
add $s3, $zero, $s0 # minIndex = i
addi $t1, $s0, 1 # $t1 = i + 1
add $s1, $zero, $t1 # j = $t1 = i + 1
FOR_2:
slt $t1, $s1, $a1 # j < len continue
beq $t1, $zero, IF_1 # if !(j < len) branch out of loop
IF_2: # "FIND MIN"
# get value at arr[ j ] store in $t3
add $t2, $zero, $s1 # calculate index $t2 = j
sll $t2, $t2, 2 # offset = $t2 * 4
add $t2, $t2, $a0 # add offset to base address
lw $t3, 0($t2) # load value at arr[ j ] into $t3
# get value at arr[minIndex] store in$t5
add $t4, $zero, $s3 # calculate index $t4 = minIndex
sll $t4, $t4, 2 # offset = $t4 * 4
add $t4, $t4, $a0 # add offset to base address
lw $t5, 0($t4) # load value at arr[minIndex] into $t5
slt $t1, $t3, $t5 # if(arr[ j ] < arr[minIndex]) continue
beq $t1, $zero, LOOP_2 # if !(arr[ j ] < arr[minIndex]) branch out of if stmt
add $s3, $zero, $s1 # minIndex = j
LOOP_2:
addi $s1, $s1, 1 # j++
j FOR_2
IF_1: # "SWAP"
beq $s3, $s0, LOOP_1 # if(minIndex == i) branch out of if stmt (jump to LOOP_1)
# tmp = arr[minIndex]
add $t2, $zero, $s3 # calculate index $t2 = minIndex
sll $t2, $t2, 2 # offset = $t2 * 4
add $t2, $t2, $a0 # add offset to base address
lw $s2, 0($t2) # $s2 = tmp = arr[minIndex]
# arr[minIndex] = arr[ i ]
add $t3, $zero, $s0 # calculate index $t3 = i
sll $t3, $t3, 2 # offset = $t2 * 4
add $t3, $t3, $a0 # add offset to base address
lw $t0, 0($t3) # $t0 = arr [ i ]
sw $t0, 0($t2) # store value at arr[ i ] in arr[minIndex]
# arr[ i ] = tmp
sw $s2, 0($t3) # store tmp value in arr[ i ]
LOOP_1:
addi $s0, $s0, 1 # i++
j FOR_1
SORT_RETURN:
lw $a0, 0($sp) # Get $a0
lw $a1, 4($sp) # Get $a1
lw $ra, 8($sp) # Get return address
lw $s0, 12($sp) # Get $s0
lw $s1, 16($sp) # Get $s1
lw $s2, 20($sp) # Get $s2
lw $s3, 24($sp) # Get $s3
addi $sp, $sp 28 # Adjust stack pointer
jr $ra # Return
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
PRINT:
addi $t0, $zero, 0 # $t0 = counter = 0
add $t1, $zero, $a0 # $t1 = arr address pointer
# Print msg1
la $s3, msg1
add $a0, $zero, $s3 # put address of space in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
# Print a space
la $s3, space
add $a0, $zero, $s3 # put address of space in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
PRINT_LOOP:
slt $t2, $t0, $a1 # if(counter < len) continue
beq $t2, $zero, PRINT_RETURN # if(counter >= len) branch out of loop
add $t3, $zero, $t0 # $t3 = counter
sll $t3, $t3, 2 # $t3 = counter * 4
add $t3, $t3, $t1 # $t3 = addr of arr[counter]
lw $t4, 0($t3) # Load value to print
add $a0, $zero, $t4 # put address of $t4 in $a0 to print
addi $v0, $zero, 1 # call service 1 to print integer
syscall # print integer
# Check if last array element
# Skip printing comma and space
addi $t3, $a1, -1 # $t3 = len - 1
beq $t3, $t0, PRINT_RETURN # if(at least element)
# Print a comma
la $s3, comma
add $a0, $zero, $s3 # put address of space in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
# Print a space
la $s3, space
add $a0, $zero, $s3 # put address of space in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
addi $t0, $t0, 1 # counter - counter + 1
j PRINT_LOOP
PRINT_RETURN:
jr $ra # Return
C imp
for ( c = 0 ; c < ( n - 1 ) ; c++ )
{
position = c;
for ( d = c + 1 ; d < n ; d++ )
{
if ( array[position] > array[d] )
position = d;
}
if ( position != c )
{
swap = array[c];
array[c] = array[position];
array[position] = swap;
}
}
The issued did occur within the swap function. I was reusing $t0 to hold the value at arr[i] and then store that value at arr[minIndex] shown here,
lw $t0, 0($t3) # $t0 = arr [ i ]
sw $t0, 0($t2) # store value at arr[ i ] in arr[minIndex]
when further up in my code $t0 had been a variable used in my outer for loop FOR_1 check shown here,
slt $t1, $s0, $t0 # i < $t0 = len - 1 continue
beq $t1, $zero, SORT_RETURN # if !(i < len - 1) branch out of loop
In effect I was modifying $t0 when I shouldn't have which caused me to prematurely quit the sort method resulting in incorrect output.
Below is the corrected code along with additional commenting. There are also modifications to the FILL and PRINT functions to handle saving and restoring variables used by the functions to the stack.
.data
msg: .asciiz "The elements sorted in ascending order are:"
.align 2 # align string
space: .asciiz " "
.align 2 # align string
comma: .asciiz ","
.align 2 # align string
arr: .space 80 # max array length = 20 * 4 bytes
.text
MAIN:
# Ask for user input and put value in $s1
addi $v0, $zero, 5 # call service 5 for integer input
syscall # read integer
add $s1, $zero, $v0 # Save $s1 = len
# Load address for arr
la $s0, arr # pointer to arr goes in $s0
add $a0, $zero, $s0 # save arr pointer to $a0
add $a1, $zero, $s1 # save len to $a1
# Ask for user input to fill arr
jal FILL
# Sort the list using selection sort
jal SORT
# Print list
jal PRINT
# Call to end program
addi $v0, $zero, 10 # system call for exit
syscall # exit program
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
FILL:
addi $sp, $sp, -8 # make space on stack
sw $s0, 0($sp) # save $s0 (position) on stack
sw $s1, 4($sp) # save $s1 (input) on stack
addi $t0, $zero, 0 # $t0 = 0
add $s0, $zero, $t0 # initialize $s0 = $t0 = 0
FILL_LOOP:
slt $t1, $s0, $a1 # if(position < len) continue
beq $t1, $zero, FILL_RETURN # if(position >= len) branch out of loop
addi $v0, $zero 5 # call service 5 for integer input
syscall # read integer
addi $s1, $zero, 0 # clear $s1 and set to 0
add $s1, $zero, $v0 # $s1 holds input integer
add $t3, $zero, $s0 # $t3 = position
sll $t3, $t3, 2 # $t3 = position * 4
add $t3, $t3, $a0 # addr of arr[position]
sw $s1, 0($t3) # store value $s1 in arr[position]
addi $s0, $s0, 1 # position++
j FILL_LOOP
FILL_RETURN:
lw $s0, 0($sp) # restore $s0 from stack
lw $s1, 4($sp) # restore $s1 from stack
addi $sp, $sp 8 # adjust stack pointer
jr $ra # Return
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
SORT:
addi $sp, $sp, -28 # make space on stack
sw $a0, 0($sp) # save $a0 (arr) on stack
sw $a1, 4($sp) # save $a1 (len) on stack
sw $ra, 8($sp) # save return address on stack
sw $s0, 12($sp) # save $s0 ( i ) on stack
sw $s1, 16($sp) # save $s1 ( j ) on stack
sw $s2, 20($sp) # save $s2 (tmp) on stack
sw $s3, 24($sp) # save $s3 (minIndex) on stack
addi $s0, $zero, 0 # i = 0
add $t0, $zero, $a1 # $t0 = len
addi $t0, $t0, -1 # $t0 = len - 1
FOR_1:
slt $t1, $s0, $t0 # if(i < len - 1) continue
beq $t1, $zero, SORT_RETURN # if(i >= len - 1) branch out of loop
add $s3, $zero, $s0 # minIndex = i
addi $t1, $s0, 1 # $t1 = i + 1
add $s1, $zero, $t1 # j = $t1 = i + 1
FOR_2:
slt $t1, $s1, $a1 # if(j < len) continue
beq $t1, $zero, IF_1 # if(j >= len) branch out of loop
IF_2: # "FIND MIN"
# get value at arr[ j ] store in $t3
add $t2, $zero, $s1 # calculate index $t2 = j
sll $t2, $t2, 2 # offset = $t2 * 4
add $t2, $t2, $a0 # add offset to base address
lw $t3, 0($t2) # load value at arr[ j ] into $t3
# get value at arr[minIndex] store in$t5
add $t4, $zero, $s3 # calculate index $t4 = minIndex
sll $t4, $t4, 2 # offset = $t4 * 4
add $t4, $t4, $a0 # add offset to base address
lw $t5, 0($t4) # load value at arr[minIndex] into $t5
slt $t1, $t3, $t5 # if(arr[ j ] < arr[minIndex]) continue
beq $t1, $zero, LOOP_2 # if(arr[ j ] >= arr[minIndex]) branch out of if stmt
add $s3, $zero, $s1 # minIndex = j
LOOP_2:
addi $s1, $s1, 1 # j++
j FOR_2
IF_1: # "SWAP"
beq $s3, $s0, LOOP_1 # if(minIndex == i) branch out of if stmt (jump to LOOP_1)
# tmp = arr[minIndex]
add $t2, $zero, $s3 # calculate index $t2 = minIndex
sll $t2, $t2, 2 # offset = $t2 * 4
add $t2, $t2, $a0 # add offset to base address
lw $s2, 0($t2) # $s2 = tmp = arr[minIndex]
# arr[minIndex] = arr[ i ]
add $t3, $zero, $s0 # calculate index $t3 = i
sll $t3, $t3, 2 # offset = $t2 * 4
add $t3, $t3, $a0 # add offset to base address
lw $t6, 0($t3) # $t6 = arr [ i ]
sw $t6, 0($t2) # store value at arr[ i ] in arr[minIndex]
# arr[ i ] = tmp
sw $s2, 0($t3) # store tmp value in arr[ i ]
LOOP_1:
addi $s0, $s0, 1 # i++
j FOR_1
SORT_RETURN:
lw $a0, 0($sp) # restore $a0 from stack
lw $a1, 4($sp) # restore $a1 from stack
lw $ra, 8($sp) # restore return address from stack
lw $s0, 12($sp) # restore $s0 from stack
lw $s1, 16($sp) # restore $s1 from stack
lw $s2, 20($sp) # restore $s2 from stack
lw $s3, 24($sp) # restore $s3 from stack
addi $sp, $sp 28 # adjust stack pointer
jr $ra # Return
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
PRINT:
addi $sp, $sp, -4 # make space on stack
sw $s0, 0($sp) # save $s0 (position) on stack
addi $t0, $zero, 0 # $t0 = 0
add $s0, $zero, $t0 # initialize $s0 = $t0 = 0
# Print msg
la $s3, msg # load address of msg into $s3
add $a0, $zero, $s3 # put address of msg in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
# Print a space
la $s3, space # load address of space into $s3
add $a0, $zero, $s3 # put address of space in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
PRINT_LOOP:
slt $t2, $s0, $a1 # if(position < len) continue
beq $t2, $zero, PRINT_RETURN # if(position >= len) branch out of loop
la $a0, arr # reload arr pointer into $a0
add $t3, $zero, $s0 # $t3 = position
sll $t3, $t3, 2 # $t3 = position * 4
add $t3, $t3, $a0 # $t3 = address of arr[position]
lw $t4, 0($t3) # Load value to print
add $a0, $zero, $t4 # put address of $t4 in $a0 to print
addi $v0, $zero, 1 # call service 1 to print integer
syscall # print integer
# Check if last array element
# Skip printing comma and space
addi $t3, $a1, -1 # $t3 = len - 1
beq $t3, $s0, PRINT_RETURN # if(at last element)
# Print a comma
la $s3, comma # load address of comma into $s3
add $a0, $zero, $s3 # put address of comma in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
# Print a space
la $s3, space # load address of space into $s3
add $a0, $zero, $s3 # put address of space in $a0 to print
addi $v0, $zero, 4 # call service 4 to print a string
syscall # print string
addi $s0, $s0, 1 # position++
j PRINT_LOOP
PRINT_RETURN:
lw $s0, 0($sp) # restore $s0 from stack
addi $sp, $sp 4 # adjust stack pointer
jr $ra # Return

Traversing through a 2D array in MIPS

Hey guys I am required to do C[i][j] = A[i][j] + B[j][i] for all i and j, size is 16 x 16 in a 2D array.
This is the main part of my code (shown below).
When I run this code in SPIM, I received an exception at line "lw $t4, 0($t4) # value of B[j][i]", which says bad address at data/stack read
When I checked the value stored in each registers, I realized that i == 0x1, but j reaches 0xbf0! (That's 3056)
I have no idea why this happened since my j is supposed to only increase from 0 to 15. Help me out!
la $t0, A # $t0 represents start address of A[i][j]
la $t1, B # $t1 represents start address of B[i][j]
la $t2, C # $t2 represents start address of C[i][j] displacement of A will be the same as C
addi $t3, $zero, 16 # set maximum iteration to be 16
addi $t5, $zero, 0 # set i = 0
addi $t6, $zero, 0 # set j = 0
loopi:
jal loopj # starts inner loopj
addi $t5, $t5, 1 # i++
bne $t3, $t5, loopi # continue loopi if i < 16
j finish
loopj:
sll $t7, $t5, 4
add $t7, $t7, $t6
sll $t7, $t7, 2 # 4 * ((i * 16) + j)
add $t9, $t7, $t0 # address of A[i][j]
lw $t9, 0($t9) # value of A[i][j]
sll $t4, $t6, 4
add $t4, $t4, $t5
sll $t4, $t4, 2 # 4 * ((j * 16) + i)
add $t4, $t4, $t1 # address of B[j][i]
lw $t4, 0($t4) # value of B[j][i]
add $t4, $t4, $t9 # A[i][j] + B[j][i]
add $t7, $t7, $t2 # address of C[i][j]
sw $t4, 0($t7) # store answer into C[i][j]
addi $t6, $t6, 1 # j++
bne $t3, $t6, loopj # continue loopj if j < 16
jr $ra
finish:
You forgot to reset j to zero every time you enter loopi, otherwise after the first loopj won't start at zero in loopj...
To fix it, you can move the addi which sets $t6 (which holds j) after the label loopi:
loopi:
addi $t6, $zero, 0 # set j = 0
jal loopj # starts inner loopj
...

C to MIPS translation

Trying to convert this c code into MIPS and run it in SPIM.
int A[100], B[100];
for(i=1; i<100; 1++){
A[i] = A[i-1] + B[i];
}
So far this is what I have.
# comments are delimted by has marks
.data
A: .word 0:100 # array of 12 integers
B: .word 0:100 # array of 12 integers
.text
main:
li $v0, 1 # load the value "1" into register $v0
li $t0, 1 # load the value "1" into register $t0
li $t1, 100 # load the value "100" into register $t1
blt $t0, $t1, loop # branches to Loop if $t0 < 100
la $t9, B
la $t8, A
loop:
sll $t0, $t0, 2
add $t2, $t9, $t0
lw $s4, 0($t9)
add $t3, $t0, -1
add $t4, $t8, $t3
lw $s5, 0($t4)
add $t5, $t2, $s5
add $t6, $s0, $t0
sw $t7, 0($t5)
addi $t0, $t0, 1
li $v0, 1 # system call for print_int
move $a0, $t0 # the sum to print
syscall # print the sum
When running in SPIM I get the following errors:
Exception occurred at PC=0x00400040
Bad address in data/stack read: 0x00000004
Exception occurred at PC=0x0040004c
Unaligned address in inst/data fetch: 0x00000003
Exception occurred at PC=0x00400058
Bad address in data/stack read: 0x00000000
Attempt to execute non-instruction at 0x0040006c
Some direction would be nice. Thanks
You are branching to loop (blt $t0, $t1, loop) before you initialize the pointers to A and B. You need to move the blt $t0, $t1, loop to the end of your code, not have it at the beginning.
I hate to do this, but there are too many things wrong to list them all. Try this:
.data
A: .word 0:100 # array of 100 integers
B: .word 0:100 # array of 100 integers
.text
main:
li $t0, 4 # load the value "1" into register $t0
li $t1, 400 # load the value "100" into register $t1
la $t9, B
la $t8, A
loop:
add $t2, $t9, $t0 # $t2 = B + i
lw $s4, 0($t9) # $s4 = B[i]
add $t3, $t0, -4 # $t3 = i - 1
add $t4, $t8, $t3 # $t4 = A + i - 1
lw $s5, 0($t4) # $s5 = A[i - 1]
add $t5, $t8, $t0 # $t5 = A + i
add $t6, $s4, $s5 # $t6 = B[i] + A[i - 1]
sw $t6, 0($t5) # A[i] = $t6
addi $t0, $t0, 4 # i++
li $v0, 1 # system call for print_int
move $a0, $t6 # the sum to print
syscall # print the sum
blt $t0, $t1, loop # branches to Loop if $t0 < 100
Right off the bat, s1 and s2 should be initialized to the stack-based (I assume) address of your arrays.

Resources