How to solve the error "Load address not aligned to word boundary" in RISC-V? - mips

I'm working on translating MIPS assembly programs written for the MARS simulator into RISCV assembly for RARS simulator.
This program is to divide the source image from a BMP file into 3 by 4 pieces and put them in new order after inputting it from console.
But after converting, when I ran the code, an error occurred.
Checking it step by step, I found this error occurred in the following line.
lw t0, 0(t2) # load word value from input file
in
copyLoop2:
blt s1, s3, copyLoop2after
lw t0, 0(t2) # load word value from input file
sw t0, 0(t3) # save word value to output file
addi t2, t2, 4 # jump t2 into next word
addi t3, t3, 4 # jump t3 into next word
addi s3, s3, 1
j copyLoop2
The error message is
Load address not aligned to word boundary 0x100100e2
But in MIPS, it worked correctly. Also, when I replaced lw with lb and sw with sb, an error didn't occur, but it didn't work properly. It didn't output any files.
Then, the following is the whole program of MIPS.
# Patch 1.1
# Changelog:
# - readBmp and writeBmp now slightly more universal
# - optimized multiplication by a power of 2 (now using sll)
.eqv bmpFileSize 230454
.eqv bytesPerRow 960
.eqv bytesPerColumnSegment 240
.eqv bytesPerRowSegment 76800
.eqv bytesJumpNextRow 720
.data
array: .space 96 # reserve space for array of numbers by which to order the segments in dest.bmp
checkArray: .word 1,1,1,2,1,3,1,4,2,1,2,2,2,3,2,4,3,1,3,2,3,3,3,4 # reserve space for array used in checking the input string
userInput: .space 25 # reserve space for initial user input
.align 4
res1: .space 2
inputImage: .space bmpFileSize # reserve space for input file data
.align 4
res2: .space 2
outputImage: .space bmpFileSize # reserve space for output file data
inputImageName: .asciiz "source.bmp"
outputImageName:.asciiz "dest.bmp"
inputMessage: .asciiz "Please input the desired order in the format 'number1number2number3...'. NO SPACES!!!\nFor instance 111213142122232431323334.\nAll numbers need to be used\n"
inputTab: .asciiz "\n"
inputFileErrorMessage: .asciiz "Encountered a problem while trying to open the input file. Exiting the program"
outputFileErrorMessage: .asciiz "Encountered a problem while trying to open the output file. Exiting the program"
checkErrorMessage: .asciiz "checkString error: Incorrect input string"
.text
######## Initial file handling ###############
# handle source.bmp and dest.bmp reading into memory
la $a0, inputImageName
la $a1, outputImageName
move $t8, $a1
jal readBmp
######## User input section ##################
# print 'give input' message
li $v0, 4
la $a0, inputMessage
syscall
# get user input
li $v0, 8
la $a0, userInput
li $a1, 25
syscall
# print newline
li $v0, 4
la $a0, inputTab
syscall
# loop over string and put data into array
li $s4, 24
li $s5, 0
addi $t0, $zero, 0 # array index
addi $t1, $zero, 0 # string index
arrayLoop:
lb $t2, userInput($t1) # load character bit
subi $t2, $t2, 48 # subtract 0
sb $t2, array($t0) # put into array
addi $t0, $t0, 4 # move array index
addi $t1, $t1, 1 # move string index
addi $s5, $s5, 1
blt $s5, $s4, arrayLoop
# check for errors in the array
jal checkString
######## Copying the segment data from inputImage into outputImage with accordance to the user input ########
# set up a nested loop (upper loop 3 (row), lower 4 (column))
li $s4, 2
li $s5, 4
li $s6, 0 # set first loop changing variable to 0
li $s7, 1 # set second loop changing variable to 1
segmentLoop1:
blt $s4, $s6, segmentLoopFin
addi $s6, $s6, 1
li $s7, 1
j segmentLoop2
segmentLoop2:
blt $s5, $s7, segmentLoop1
# load to $a0 and $a1 from array. row first, column second
addi $t0, $zero, 0
subi $t1, $s6, 1
sll $t1, $t1, 5 # calculate offset due to row number
add $t0, $t0, $t1 # offset $t0
subi $t1, $s7, 1
sll $t1, $t1, 3 # calculate offset due to column number
add $t0, $t0, $t1 # offset $t0
lw $t2, array($t0) # get row number
move $a0, $t2
addi $t0, $t0, 4
lw $t2, array($t0) # now column number
move $a1, $t2
# load to $a2 and $a3 from loop
move $a2, $s6
move $a3, $s7
jal copySegment
addi $s7, $s7, 1
j segmentLoop2
segmentLoopFin:
######## Output file handling ##############
# handle dest.bmp
move $a0, $t8
jal writeBmp
exit:
# exit
li $v0, 10
syscall
readBmp:
# $a0 - name of source file
# $a1 - name of destination file
move $t1, $a1 # save destintation file name for second half of function
sub $sp, $sp, 4
sw $s1, 0($sp)
# input file
# open file
li $v0, 13
# file name already in $a0
li $a1, 0 # flags: read file
li $a2, 0 # mode: ignored
syscall
# save file descriptor
move $s1, $v0
# check if the file was opened correctly
bltz $v0, inputFileError
# read file
li $v0, 14
move $a0, $s1
la $a1, inputImage
li $a2, bmpFileSize
syscall
# close file
li $v0, 16
move $a0, $s1
syscall
# output file
# open file
li $v0, 13
move $a0, $t1 # file name
li $a1, 0 # flags: read file
li $a2, 0 # mode: ignored
syscall
# save file descriptor
move $s1, $v0
# check if the file was opened correctly
bltz $v0, outputFileError
# read file
li $v0, 14
move $a0, $s1
la $a1, outputImage
li $a2, bmpFileSize
syscall
# close file
li $v0, 16
move $a0, $s1
syscall
lw $s1, 0($sp)
add $sp, $sp, 4
jr $ra
writeBmp:
# $a0 - name of destination file
sub $sp, $sp, 4 # push $s1
sw $s1, 0($sp)
# open file
li $v0, 13
# file name already in $a0
li $a1, 1 # flags: write file
li $a2, 0 # mode: ignored
syscall
# save file descriptor
move $s1, $v0
# check if the file was opened correctly
bltz $v0, outputFileError
# save file
li $v0, 15
move $a0, $s1
la $a1, outputImage
li $a2, bmpFileSize
syscall
# close file
li $v0, 16
move $a0, $s1
syscall
lw $s1, 0($sp)
add $sp, $sp, 4
jr $ra
inputFileError:
# print error message
li $v0, 4
la $a0, inputFileErrorMessage
syscall
j exit
outputFileError:
# print error message
li $v0, 4
la $a0, outputFileErrorMessage
syscall
j exit
checkString:
# This part (from here till if2True included) is a bit convoluted, but it works.
# Firstly there is a check if any data in the array derived from user input is zero. This doesn't do much
# by itself, but it compliments the next part.
# Then we iterate over checkArray in search of a pair of numbers that are the same as those in the array from user input.
# If we don't find it it means that the number pair was not a valid one (as checkArray contains all valid number pairs).
# If we find it we change that pair in checkArray into 00 and go to the next pair from user input. That way we won't count duplicates
# as once a number is used, it cannot be found again. That is also why at the beggining we check for the occurence of zeroes, because if we didn't
# an input string of 110000000000000000000000 would be accepted, which is of course wrong.
# set up nested loop
li $s4, 12
addi $s4, $s4, -1
li $s5, 12
addi $s5, $s5, -1
li $s6, 0
li $s7, 0
addi $t0, $zero, 0 # input array row index
addi $t1, $zero, 4 # input array column index
checkLoop1:
blt $s4, $s6, checkLoopFin
addi $s6, $s6, 1
li $s7, 0
# check if either row number or column number are equal to 0
lw $t4, array($t0)
beqz $t4, checkError
lw $t4, array($t1)
beqz $t4, checkError
addi $t2, $zero, 0 # check array row index
addi $t3, $zero, 4 # check array column index
checkLoop2:
blt $s5, $s7, checkError
lw $t4, array($t0)
lw $t5, array($t1)
lw $t6, checkArray($t2)
lw $t7, checkArray($t3)
beq $t4, $t6, if1True
checkCont:
addi $t2, $t2, 8
addi $t3, $t3, 8
addi $s7, $s7, 1
j checkLoop2
checkLoopFin:
jr $ra
if1True:
beq $t5, $t7, if2True
j checkCont
if2True:
li $t6, 0
li $t7, 0
sw $t6, checkArray($t2)
sw $t7, checkArray($t3)
addi $t0, $t0, 8
addi $t1, $t1, 8
j checkLoop1
checkError:
# print error message
li $v0, 4
la $a0, checkErrorMessage
syscall
j exit
copySegment:
# $a0 - row number input
# $a1 - column number input
# $a2 - row number output
# $a3 - column number output
# one register - get address of segment start point in input file
la $t1, inputImage + 10 # address of file offset to pixel array
lw $t2, ($t1) # file offset to pixel array in $t2
la $t1, inputImage # address of bitmab
add $t2, $t1, $t2 # address of pixel array in $t2
# pixel address calculation
# calculate 3 - $a0
li $t0, 3
sub $t1, $t0, $a0
# move $t2 by $t0*bytesPerRowSegment
mul $t0, $t1, bytesPerRowSegment
add $t2, $t2, $t0
# calculate $a1 - 1
li $t0, 1
sub $t1, $a1, $t0
# move $t2 by $t0*bytesPerColumnSegment
mul $t0, $t1, bytesPerColumnSegment
add $t2, $t2, $t0
# second register - get address of segment start point in output file
la $t1, outputImage + 10 # address of file offset to pixel array
lw $t3, ($t1) # file offset to pixel array in $t2
la $t1, outputImage # address of bitmab
add $t3, $t1, $t3 # address of pixel array in $t2
# pixel address calculation
# calculate 3 - $a2
li $t0, 3
sub $t1, $t0, $a2
# move $t3 by $t0*bytesPerRowSegment
mul $t0, $t1, bytesPerRowSegment
add $t3, $t3, $t0
# calculate $a3 - 1
li $t0, 1
sub $t1, $a3, $t0
# move $t3 by $t0*bytesPerColumnSegment
mul $t0, $t1, bytesPerColumnSegment
add $t3, $t3, $t0
# set up nested foor loop (upper one loops 80 times (rows per segment), lower one 60 (words per row in segment))
li $s0, 80
addi $s0, $s0, -1
li $s1, 60
addi $s1, $s1, -1
li $s2, 0 # set first loop changing variable to 0
li $s3, 0 # set second loop changing variable to 0
copyLoop1:
blt $s0, $s2, copyLoopFin
addi $s2, $s2, 1
li $s3, 0
j copyLoop2
copyLoop2:
blt $s1, $s3, copyLoop2after
lw $t0, 0($t2) # load word value from input file
sw $t0, 0($t3) # save word value to output file
addiu $t2, $t2, 4 # jump $t2 into next word
addiu $t3, $t3, 4 # jump $t3 into next word
addi $s3, $s3, 1
j copyLoop2
copyLoop2after:
add $t2, $t2, bytesJumpNextRow # jump $t2 into next row
add $t3, $t3, bytesJumpNextRow # jump $t3 into next row
j copyLoop1
copyLoopFin:
jr $ra
And the RISC-V program I converted the MIPS program to is .
.eqv bmpFileSize 230454
.eqv bytesPerRow 960
.eqv bytesPerColumnSegment 240
.eqv bytesPerRowSegment 76800
.eqv bytesJumpNextRow 720
li s10 230454
li s11 960
li a4 240
li a5 76800
li a6 720
# t7->s8
# t8->s9
# move->mv
# syscall -> ecall
# asciiz-> asciz
.data
array: .space 96 # reserve space for array of numbers by which to order the segments in dest.bmp
checkArray: .word 1,1,1,2,1,3,1,4,2,1,2,2,2,3,2,4,3,1,3,2,3,3,3,4 # reserve space for array used in checking the input string
userInput: .space 25 # reserve space for initial user input
.align 4
res1: .space 2
inputImage: .space bmpFileSize # reserve space for input file data
.align 4
res2: .space 2
outputImage: .space bmpFileSize # reserve space for output file data
inputImageName: .asciz "/private/var/folders/bf/t4py6npj0v38grsvrgvq1dx00000gn/T/hsperfdata_sotarosuzuki/source.bmp"
outputImageName:.asciz "/private/var/folders/bf/t4py6npj0v38grsvrgvq1dx00000gn/T/hsperfdata_sotarosuzuki/dest.bmp"
inputMessage: .asciz "Please input the desired order in the format 'number1number2number3...'. NO SPACES!!!\nFor instance 111213142122232431323334.\nAll numbers need to be used\n"
inputTab: .asciz "\n"
inputFileErrorMessage: .asciz "Encountered a problem while trying to open the input file. Exiting the program"
outputFileErrorMessage: .asciz "Encountered a problem while trying to open the output file. Exiting the program"
checkErrorMessage: .asciz "checkString error: Incorrect input string"
.text
######## Initial file handling ###############
# handle source.bmp and dest.bmp reading into memory
la a0, inputImageName
la a1, outputImageName
mv s9, a1
jal readBmp
######## User input section ##################
# print 'give input' message
li a7, 4
la a0, inputMessage
ecall
# get user input
li a7, 8
la a0, userInput
li a1, 25
ecall
# print newline
li a7, 4
la a0, inputTab
ecall
# loop over string and put data into array
li s4, 24
li s5, 0
addi t0, zero, 0 # array index
addi t1, zero, 0 # string index
arrayLoop:
lb t2, %lo(userInput)(t1) # load character bit
addi t2, t2, -48 # subtract 0
sb t2, array, t0 # put into array
addi t0, t0, 4 # mv array index
addi t1, t1, 1 # mv string index
addi s5, s5, 1
blt s5, s4, arrayLoop
# check for errors in the array
jal checkString
######## Copying the segment data from inputImage into outputImage with accordance to the user input ########
# set up a nested loop (upper loop 3 (row), lower 4 (column))
li s4, 2
li s5, 4
li s6, 0 # set first loop changing variable to 0
li s7, 1 # set second loop changing variable to 1
segmentLoop1:
blt s4, s6, segmentLoopFin
addi s6, s6, 1
li s7, 1
j segmentLoop2
segmentLoop2:
blt s5, s7, segmentLoop1
# load to a0 and a1 from array. row first, column second
addi t0, zero, 0
addi t1, s6, -1
slli t1, t1, 5 # calculate offset due to row number
add t0, t0, t1 # offset t0
addi t1, s7, -1
slli t1, t1, 3 # calculate offset due to column number
add t0, t0, t1 # offset t0
lw t2, %lo(array)(t0) # get row number
mv a0, t2
addi t0, t0, 4
lw t2, %lo(array)(t0) # now column number
mv a1, t2
# load to a2 and a3 from loop
mv a2, s6
mv a3, s7
jal copySegment
addi s7, s7, 1
j segmentLoop2
segmentLoopFin:
######## Output file handling ##############
# handle dest.bmp
mv a0, s9
jal writeBmp
exit:
# exit
li a7, 10
ecall
readBmp:
# a0 - name of source file
# a1 - name of destination file
mv t1, a1 # save destintation file name for second half of function
addi sp, sp, -4
sw s1, 0(sp)
# input file
# open file
li a7, 1024
# file name already in a0
li a1, 0 # flags: read file
li a2, 0 # mode: ignored
ecall
# save file descriptor
mv s1, a7
# check if the file was opened correctly
bltz a7, inputFileError
# read file
li a7, 63
mv a0, s1
la a1, inputImage
li a2, bmpFileSize
ecall
# close file
li a7, 57
mv a0, s1
ecall
# output file
# open file
li a7, 1024
mv a0, t1 # file name
li a1, 0 # flags: read file
li a2, 0 # mode: ignored
ecall
# save file descriptor
mv s1, a7
# check if the file was opened correctly
bltz a7, outputFileError
# read file
li a7, 63
mv a0, s1
la a1, outputImage
li a2, bmpFileSize
ecall
# close file
li a7, 57
mv a0, s1
ecall
lw s1, 0(sp)
addi sp, sp, 4
jr ra
writeBmp:
# a0 - name of destination file
addi sp, sp, -4 # push s1
sw s1, 0(sp)
# open file
li a7, 1024
# file name already in a0
li a1, 1 # flags: write file
li a2, 0 # mode: ignored
ecall
# save file descriptor
mv s1, a7
# check if the file was opened correctly
bltz a7, outputFileError
# save file
li a7, 64
mv a0, s1
la a1, outputImage
li a2, bmpFileSize
ecall
# close file
li a7, 57
mv a0, s1
ecall
lw s1, 0(sp)
addi sp, sp, 4
jr ra
inputFileError:
# print error message
li a7, 4
la a0, inputFileErrorMessage
ecall
j exit
outputFileError:
# print error message
li a7, 4
la a0, outputFileErrorMessage
ecall
j exit
checkString:
# This part (from here till if2True included) is a bit convoluted, but it works.
# Firstly there is a check if any data in the array derived from user input is zero. This doesn't do much
# by itself, but it compliments the next part.
# Then we iterate over checkArray in search of a pair of numbers that are the same as those in the array from user input.
# If we don't find it it means that the number pair was not a valid one (as checkArray contains all valid number pairs).
# If we find it we change that pair in checkArray into 00 and go to the next pair from user input. That way we won't count duplicates
# as once a number is used, it cannot be found again. That is also why at the beggining we check for the occurence of zeroes, because if we didn't
# an input string of 110000000000000000000000 would be accepted, which is of course wrong.
# set up nested loop
li s4, 12
addi s4, s4, -1
li s5, 12
addi s5, s5, -1
li s6, 0
li s7, 0
addi t0, zero, 0 # input array row index
addi t1, zero, 4 # input array column index
checkLoop1:
blt s4, s6, checkLoopFin
addi s6, s6, 1
li s7, 0
# check if either row number or column number are equal to 0
lw t4, %lo(array)(t0)
beqz t4, checkError
lw t4, %lo(array)(t1)
beqz t4, checkError
addi t2, zero, 0 # check array row index
addi t3, zero, 4 # check array column index
checkLoop2:
blt s5, s7, checkError
lw t4, %lo(array)(t0)
lw t5, %lo(array)(t1)
lw t6, %lo(checkArray)(t2)
lw s8, %lo(checkArray)(t3)
beq t4, t6, if1True
checkCont:
addi t2, t2, 8
addi t3, t3, 8
addi s7, s7, 1
j checkLoop2
checkLoopFin:
jr ra
if1True:
beq t5, s8, if2True
j checkCont
if2True:
li t6, 0
li s8, 0
sw t6, checkArray, t2
sw s8, checkArray, t3
addi t0, t0, 8
addi t1, t1, 8
j checkLoop1
checkError:
# print error message
li a7, 4
la a0, checkErrorMessage
ecall
j exit
copySegment:
# a0 - row number input
# a1 - column number input
# a2 - row number output
# a3 - column number output
# one register - get address of segment start point in input file
la t1, inputImage # address of file offset to pixel array
addi t1, t1, 10
lw t2, (t1) # file offset to pixel array in t2
la t1, inputImage # address of bitmab
add t2, t1, t2 # address of pixel array in t2
# pixel address calculation
# calculate 3 - a0
li t0, 3
sub t1, t0, a0
# mv t2 by t0*bytesPerRowSegment
mul t0, t1, a5
add t2, t2, t0
# calculate a1 - 1
li t0, 1
sub t1, a1, t0
# mv t2 by t0*bytesPerColumnSegment
mul t0, t1, a4
add t2, t2, t0
# second register - get address of segment start point in output file
la t1, outputImage # address of file offset to pixel array
addi t1, t1, 10
lw t3, (t1) # file offset to pixel array in t2
la t1, outputImage # address of bitmab
add t3, t1, t3 # address of pixel array in t2
# pixel address calculation
# calculate 3 - a2
li t0, 3
sub t1, t0, a2
# mv t3 by t0*bytesPerRowSegment
mul t0, t1, a5
add t3, t3, t0
# calculate a3 - 1
li t0, 1
sub t1, a3, t0
# mv t3 by t0*bytesPerColumnSegment
mul t0, t1, a4
add t3, t3, t0
# set up nested foor loop (upper one loops 80 times (rows per segment), lower one 60 (words per row in segment))
li s0, 80
addi s0, s0, -1
li s1, 60
addi s1, s1, -1
li s2, 0 # set first loop changing variable to 0
li s3, 0 # set second loop changing variable to 0
copyLoop1:
blt s0, s2, copyLoopFin
addi s2, s2, 1
li s3, 0
j copyLoop2
copyLoop2:
blt s1, s3, copyLoop2after
lw t0, 0(t2) # load word value from input file
sw t0, 0(t3) # save word value to output file
addi t2, t2, 4 # jump t2 into next word
addi t3, t3, 4 # jump t3 into next word
addi s3, s3, 1
j copyLoop2
copyLoop2after:
add t2, t2, a6 # jump t2 into next row
add t3, t3, a6 # jump t3 into next row
j copyLoop1
copyLoopFin:
jr ra
I couldn't find the solution to convert it correclty. So could anyone help me?
And is there any way to convert it automatically?

In riscv you have 3 possible accesses :
word
half word
byte
When you perform an access you need your address to be aligned to the type of access. So for example in the case of a lw your address need to be word-aligned.
In your case the address is 0x100100e2 which is not word-aligned.
Indeed in binary it gaves us :
0b10000000000010000000011100010
Or to be word aligned the 2 lsb need to be 0 so this is why you got an error.

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

Why is MIPS printing memory locations on the second time around

[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.

MIPS: Lucas Sequence Returns P every other number when P is 1

I am implementing a mips program for a lucas sequence. The user enters a number, n, P, and Q and choose 1 for the V sequence and 0 for the U sequence. I am having issues with choosing the V sequence returning P every other number only when P is 1. I know it is something little that I am missing, but I have been trying to find it for hours. Any help would be greatly appreciated.
addi $t1, $s0, 0 # load n into $t1
addi $t3, $zero, 0 # i = 0
jal lucasSequence # go to lucasSequence
end_loop:
la $a0, newline # print a newline \n
jal printString
j main # loop to main menu again
#############################################
# Procedure: lucasSequence #
#############################################
# - produces the Lucas sequence of the #
# first (U) or second (V) order for #
# given constants P and Q. #
# #
# The procedure produces all numbers #
# in the sequence U or V from n=0 #
# up to n=N. #
# #
# - inputs : $a0-integer N #
# $a1-constant P #
# $a2-constant Q #
# $a3-function U (0) or V (1) #
# - outputs: none #
# #
#############################################
lucasSequence:
loop:
move $a0, $t3 # n = i
beq $t3, $t1, end_loop # if i == n, quit.
jal lucasSequenceNumber # print the lucas sequence for N, P, and Q
addi $t3, $t3, 1 # i++
move $a0, $v0 # load int to print
li $v0, 1 # print int
syscall # print call
beq $t3, $t1, end_loop # don't print last comma
li $a0, ',' # load comma
li $v0, 11 # add to print
syscall # print comma
li $a0, ' ' # load space
li $v0, 11 # print space
syscall # print call
j loop # repeat until i = n
lucasSequenceNumber:
addi $sp, $sp, -8 # room for $ra and one temporary
sw $ra, 4($sp) # save $ra
move $v0, $a0 # pre-load return value as n
addi $t4, $zero, 1 # t4 =1
blt $a0, 2, rt # if(n < 2) return
sw $a0, 0($sp) # save a copy of n
addi $a0, $a0, -1 # n - 1
jal lucasSequenceNumber # lucas(n - 1)
lw $a0, 0($sp) # retrieve n
mul $v0, $v0, $a1 # P*lucas(n-1)
sw $v0, 0($sp) # save result of P*lucas(n - 1)
addi $a0, $a0, -2 # n - 2
jal lucasSequenceNumber # lucas(n - 2)
mul $v0, $v0, $a2 # Q*lucas(n-2)
lw $v1, 0($sp) # retrieve P*lucas(n - 1)
sub $v0, $v1, $v0 # P*lucas(n - 1) + Q*lucas(n - 2)
rt:
addi $t4, $zero, 1 # t4 = 1
beq $a3, $t4, return_V # user chose option 2
lucas_rt:
lw $ra, 4($sp) # restore $ra
addi $sp, $sp, 8 # restore $sp
jr $ra # back to caller
return_V:
bgt $a0, $t4, lucas_rt # if choice V and n > 1, got to return
beq $a0, $t4, one_v # if n = 1, go to one_v
li $a0, 2 # if n = 0, return 2
move $v0, $a0
j lucas_rt # back to caller
one_v:
addi $a0, $a1, 0 # return P
move $v0, $a0
j lucas_rt # go to return P call
The function one_v needs to be adjusted so it reads:
one_v:
move $a0, $a1
move $a0, $v0
j lucas_rt

Putting code into Subroutine

Can someone give me some advice on how to make my code into a subroutine that is called from main?
.data
inputOne: .word 2 # Value 1
inputTwo: .word 3 # Value 2
counter: .word 0 # Adds the amount of times that we go through the loop
sum: .word 0 # Where the result of the addition goes
.text
main:
lw $t2, inputOne # Load 2 into register t2
lw $t3, inputTwo # Load 3 into register t3
lw $t4, counter # Load 0 into register t4
lw $t5, sum # Load 0 into register t5
topOfLoop: # Start of the loop
beq $t4, $t2, bottomOfLoop # Until t4 is equal to t2, the loop will continue
addi $t5, $t5, 3 # Adds 3 to register t5 ( Sum)
addi $t4, $t4, 1 # Adds 1 to register t5 (Counter)
j topOfLoop # Jumps to the top of the loop
bottomOfLoop: # End of the loop
sw $t5, sum #Storing the value in $t5 into sum
Use jal and jr $ra:
.data
inputOne: .word 2 # Value 1
inputTwo: .word 3 # Value 2
counter: .word 0 # Adds the amount of times that we go through the loop
sum: .word 0 # Where the result of the addition goes
.text
main:
lw $t2, inputOne # Load 2 into register t2
lw $t3, inputTwo # Load 3 into register t3
lw $t4, counter # Load 0 into register t4
lw $t5, sum # Load 0 into register t5
jal sub # go to sub and store the address of the next position in $ra
li $vo, 10
syscall #end program
sub:
topOfLoop: # Start of the loop
beq $t4, $t2, bottomOfLoop # Until t4 is equal to t2, the loop will continue
addi $t5, $t5, 3 # Adds 3 to register t5 ( Sum)
addi $t4, $t4, 1 # Adds 1 to register t5 (Counter)
j topOfLoop # Jumps to the top of the loop
bottomOfLoop: # End of the loop
sw $t5, sum #Storing the value in $t5 into sum
jr $ra # jump to the address in $ra, as it is filled by jal
Remember: by convention, the $t registers may be changed by the subroutine, the $s registers must be restored by the subroutine before it ends, the $a registers are used for the arguments, and the $v registers for the return values.

What does this MIPS program do?

I know the program loads the address of .word 5 which is the initial value, I'm getting confused as to what the program is actually doing. Is it comparing stacks of the word or adding.
.data
arg: .word 5
.text
.globl main
main:
la $t3, arg
lw $t2, 0($t3)
lw $t3, 0($t3)
addi $t1, $zero, 0
beqz $t2, fin
fori:
add $t1, $t1, $t2
addi $t3, $t3, -1
bnez $t3, fori
fin:
li $v0, 10
syscall
Looks like it does addition based on the first item in the space as it doesn't access the array from inside the loop.
So for instance if you input a character representing the ascii value of 5 (not '5' itself iirc) you might see something like this:
int t2 = 5, t3 = 5, t1 = 0;
do {
t1 += t2;
t3 -= 1;
} while(t3 > 0);
Someone has already answered but I shall provide the translation I did:
.data
arg: .word 5
.text
.globl main
main:
la $t3, arg # load-address of arg into t3
lw $t2, 0($t3) # load-word from the address in t3 + 0 offset, like t3[0]
lw $t3, 0($t3) # same but to t3
addi $t1, $zero, 0 # initialize t1 to 0? weird they don't use li
beqz $t2, fin # if t2 is zero jump to fin:
fori:
add $t1, $t1, $t2 # t1 = t1 + t2
addi $t3, $t3, -1 # t3 -= 1
bnez $t3, fori # if(t3 != 0) goto fori
fin:
li $v0, 10 # load immediate 10 into v0, which is the syscall to terminate the program
syscall
Disclaimer: I don't have any direct MIPS experience, I just have been around a number of assembly languages.
That said, I think what the program does is calculating the square of 'arg' by repeated addition - in this case 5 * 5 = 25. However, the result in $t1 doesn't seem to be stored anywhere, instead the program just exits.