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.
Related
Write a MIPS program that defines a one-dimensional array of 10 integers in the static area of the data segment, asks the user to input all 10 array elements, computes, and displays their sum.
.data
arr: .word 1,2,3,4,5,6,7,8,9,10
msg: .asciiz "Result: "
.text
.globl main
main:
addi $t0, $zero, 0 # clear i
addi $t1, $zero, 0 # clear sum
ori $t2, $zero, 10 # Initializing t2 to its constant value 10
la $t3, arr # load address of array into t4
loop:
slt $t4, $t0, $t2 # compare, $t4 = i < sum ? 1 : 0
beq $t4, $zero, end # if i is not < 10, exit the loop
lw $t4, 0($t3) # load current array element into t4
add $t1, $t1, $t4 # add it to sum
add $t0, $t0, 1 # increment i
add $t3, $t3, 4 # increment current array element pointer
j loop
end:
addi $v0, $zero, 4 # Now we print out result: string
la $a0, msg
syscall
addi $v0, $zero, 1 # followed by the actual sum (which is in t1)
add $a0, $t1, $zero
syscall
jr $ra
.end main
Assume that the variables f and g are assigned to registers $s0, $s1. Assume that the base address of the arrays A and B are in registers $s6 and $s7 respectively. Below is the MIPS code I have written to translate A[2*(f+g)] = B[B[16 + f/2] ]:
# accessing the correct address for A[2*(f+g)]
line 1. add $t0, $s0, $s1 # $t0 = f + g
line 2. add $s6, $s6, $t0 # A[0] should update to A[(f+g)/4]
line 3. sll $s6, $s6, 3 # A[(f+g)/4] should update to A[(8*((f+g)/4)]
line 4. srl $s0, $s0, 1 # f = f/2
line 5. addi $s0, $s0, 16 # f = f/2 + 16
line 6. sll $s0, $s0, 2 # f = (f/2 + 16) * 4
line 7. add $s7, $s0, $s7 # B[0] should update to B[f/2 + 16]
line 8. sll $s7, $s7, 2 # B[f/2 + 16] should update to (B[f/2 + 16]) * 4
line 9. add $t0, $s7, $0 # $t0 = (B[f/2 + 16]) * 4
line 10. sw $s6, $t0($s7) # should be storing B[(B[f/2 + 16]) * 4] in A[2*(f+g)]
I think that I am messing up with access the memory location inside of array B when you need to access it twice. Can someone help?
I believe the correct solution is the following:
add $t0, $s0, $s1
sll $t0, $t0, 3
add $s6, $t0, $s6
srl $t1, $s0, 1
addi $t1, $t1, 16
sll $t1, $t1, 2
add $t2, $s7, $t1
lw $t3, 0($t2)
add t4, $s7, $t3
lw $t5, 0($t4)
sw $t5, 0($s6)
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!
So im attempting to put numbers 1-200 in an array. The array is at the bottom of the code. I keep getting errors when i try to print this, can anyone spot the error with me putting in the numbers? The numbers in the array are supposed to go from 1-200, so $t3 increments each time. Any advice would be greatly appreciated.
main:
.text
lw $t0, numbers_size # loads the size of the array into the loop
la $t1, numbers # $t1 gets the number array
li $t2, 0 # loop control variable
li $t3, 1 # value stored inside numbers
li $v0, 4
la $a0, test_2 # print before loop
syscall
number_for:
bge $t2, $t0, end_for
sw $t3, ($t1)
add $t1, $t1, 4
add $t2, $t2, 1
add $t3, $t3, 1
j number_for
end_for:
lw $t0, numbers_size # loads the size of the array into the loop
la $t1, numbers # $t1 gets the number array
li $t2, 0 # loop control variable
j print_numbers
.data
test: .asciiz "Printing numbers:"
test_2: .asciiz "Before loop:"
numbers:
.word 0:200
numbers_size:
.word 200
This may help you:
.text
main:
lw $t0, numbers_size # loads the size of the array into the loop
la $t1, numbers # $t1 gets the number array
li $t2, 0 # loop control variable
li $t3, 1 # value stored inside numbers
li $v0, 4
la $a0, test_2 # print before loop
syscall
j number_for
li $v0, 10
syscall
number_for:
bge $t2, $t0 end_for
sw $t3, ($t1)
addi $t1, $t1, 4
addi $t2, $t2, 1
addi $t3, $t3, 1
b number_for
end_for:
lw $t0, numbers_size # loads the size of the array into the loop
li $t1, 0
li $t2, 0 # loop control variable
buc:
bge $t2, $t0 end
lw $a0, numbers($t1) # Printing integer from array
li $v0,1
syscall
la $a0, space #load a space: " "
li $v0, 4 #print string
syscall
addi $t1, $t1, 4
addi $t2, $t2, 1
b buc
end:
jr $ra
.data
test: .asciiz "Printing numbers:"
test_2: .asciiz "Before loop:\n"
space: .asciiz " "
numbers_size:
.word 200
numbers:
.word 0:200
So I am working on an assignment to sort an array in MIPS. The data to sort is given in a separate .asm file as follows:
.data
.word 3
.word 40
.word 30
.word 70
.text
I decided to use bubble sort. I am fairly certain that my algorithm is sound, and it appears to sort the data correctly. The fun thing about this project is that the values we sort will be played as MIDI notes as a means of testing the program (so, naturally, the notes should play in ascending order). This is working pretty well when I test my code, however, I'm hearing a few strange beats at the end of the MIDI notes. I stepped through my code and discovered that, at the end, $t1 (the value I use to compare to my loop iterator for completeness) holds a value of 7, when I expected it to hold a value of three. I assign $t1 as 0($t2), $t2 is 0x10010000 which I assume is still the base address of my array. The base address of the array should hold 3, shouldn't it?
I'm a little confused about why $t1 is 7 at all... any advice? I have included all of my code below.
#ec2.asm
.include "ec2_data.asm" #must be in the same directory as ec2.asm
#ec2_data.asm: puts some values in the "data segment"
#the first value is the number of values to sort (n)
#the remaining n word values are the data to sort
#the values will be stored in memory as word values starting
# address 0x10010000
j main
#$t2 is hasChanged
#$t3 is itemCount
#$t4 is i, our iterator in the for loop
#$t5 is array[i] (temp)
#$t6 is array[i+1] (temp)
while_label:
beq $t2, $zero, done_sorting #checks to see if the previous iteration switched any values. If not, we are done.
addi $t2, $zero, 0 #initialize hasChanged to 0
addi $t3, $t3, -1 #decrement itemCount by -1
addi, $t0, $t0, 4 #add 4 to the array offset
addi, $t4, $zero, 0 #set our for loop iterator to 0
for_label:
lw $t5, 0($t0) #set a temp value equal to array[i]
lw $t6, 4($t0) #set a temp value equal to array[i+1]
beq $t4, $t3, while_label #for loop: if i = itemcount, we have incremented all the way through our for loop
bge $t6, $t5, skip_swap #if array[i+1] is greater than or equal to array[i], we don't need to swap these values
#swap
sw $t6, 0($t0) #set array[i] equal to array[i+1]
sw $t5, 4($t0) #set array[i+1] equal to the temp value
addi $t2, $t2, 1 #set hasChanged to 1 to indicate that a swap has been made
skip_swap:
addi, $t4, $t4, 1 #increment i by 1 (for loop iterator)
j for_label #keep the for loop going!
main:
#read values
addi $t0, $zero, 0x10010000 #sets $t0 to be the base address of the array
addi $t2, $zero, 1
lw $t3, 0($t0) #stores n in $t3
j while_label
done_sorting:
# adapted from MIDI example
#duration 25 ms
#instrument (whichever)
#volume 64
addi $v0, $zero, 33 # midi out synchronous
addi $t2, $zero, 0x10010000 # address of original array (which should by now be sorted)
addi $a1, $zero, 250 # duration (ms)
addi $a2, $zero, 1 # instrument
addi $a3, $zero, 64 # volume
addi $t0, $zero, 0 # counter
lw $t1, 0($t2) # end of the loop (should be n)
addi $t1, $t1, 4 # adds four to the array offset in $t1
lw $a0, 0($t2) # stores the first sorted value ( 4($t1) ) in $a0
midi_loop:
beq $t0, $t1, done
addi $t2, $t2, 4
lw $a0, 0($t2)
syscall
addi $t0, $t0, 1
j midi_loop
done:
#addi $v0, $zero, 10 # syscall for exit
#syscall # clean exit
Your sorting algorithm is quite broken. You haven't noticed that because it happens to get the right answer with your test data. It will produce the wrong answer with other test data (e.g. I believe your algorithm will sort 70, 40, 30 to 40, 30, 70).
But your question was about why $t1 ends up with value 7. The answer is simple. You wrote this:
addi $t2, $zero, 0x10010000 # address of original array (which should by now be sorted)
addi $a1, $zero, 250 # duration (ms)
addi $a2, $zero, 1 # instrument
addi $a3, $zero, 64 # volume
addi $t0, $zero, 0 # counter
lw $t1, 0($t2) # end of the loop (should be n)
addi $t1, $t1, 4 # adds four to the array offset in $t1
We can see that you set $t2 to 0 + 0x10010000 = 0x10010000. Then you load the word at 0($t2) (= 0x10010000) into $t1. The word at 0x10010000 is 3, so at that point $t1 is 3. Then you add 4 to $t1, storing the result in $t1. At that point $t1 is 7. You never modify $t1 after that.
SO I really shouldn't have asked this question without giving my code another once-over. The errors were extremely simple. This appears to work.
#ec2.asm
.include "ec2_data.asm" #must be in the same directory as ec2.asm
#ec2_data.asm: puts some values in the "data segment"
#the first value is the number of values to sort (n)
#the remaining n word values are the data to sort
#the values will be stored in memory as word values starting
# address 0x10010000
j main
#$t2 is hasChanged
#$t3 is itemCount
#$t4 is i, our iterator in the for loop
#$t5 is array[i] (temp)
#$t6 is array[i+1] (temp)
while_label:
beq $t2, $zero, done_sorting #checks to see if the previous iteration switched any values. If not, we are done.
addi $t2, $zero, 0 #initialize hasChanged to 0
addi $t3, $t3, -1 #decrement itemCount by -1 WHY
addi, $t0, $zero, 0x10010000 #add 4 to the array offset
addi, $t4, $zero, 0 #set our for loop iterator to 0
for_label:
addi, $t0, $t0, 4
lw $t5, 0($t0) #set a temp value equal to array[i]
lw $t6, 4($t0) #set a temp value equal to array[i+1]
beq $t4, $t3, while_label #for loop: if i = itemcount, we have incremented all the way through our for loop
bge $t6, $t5, skip_swap #if array[i+1] is greater than or equal to array[i], we don't need to swap these values
#swap
sw $t6, 0($t0) #set array[i] equal to array[i+1]
sw $t5, 4($t0) #set array[i+1] equal to the temp value
addi $t2, $t2, 1 #set hasChanged to 1 to indicate that a swap has been made
skip_swap:
addi, $t4, $t4, 1 #increment i by 1 (for loop iterator)
j for_label #keep the for loop going!
main:
#read values
addi $t0, $zero, 0x10010000 #sets $t0 to be the base address of the array
addi $t2, $zero, 1
lw $t3, 0($t0) #stores n in $t3
j while_label
done_sorting:
# adapted from MIDI example
#duration 25 ms
#instrument (whichever)
#volume 64
addi $v0, $zero, 33 # midi out synchronous
addi $t2, $zero, 0x10010000 # address of original array (which should by now be sorted)
addi $a1, $zero, 250 # duration (ms)
addi $a2, $zero, 1 # instrument
addi $a3, $zero, 64 # volume
addi $t0, $zero, 0 # counter
lw $t1, 0($t2) # end of the loop (should be n)
lw $a0, 0($t2) # stores the first sorted value ( 4($t1) ) in $a0
midi_loop:
beq $t0, $t1, done
addi $t2, $t2, 4
lw $a0, 0($t2)
syscall
addi $t0, $t0, 1
j midi_loop
done: