What does this MIPS program do? - mips

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.

Related

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

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.

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

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

When writing in MIPS, I am unsure whether to use li or addi. I am still unclear what the difference is.

For example, I have a piece of C code that I am trying to convert to MIPS for practice, but for the variable count, I don't know whether to use addi $t0,0 or li $t0, 0. Could I use either either or? And what is the difference?
Void haarPredict (int vector[], int N)
{
int half = N >> 1;
int count = 0;
for(int i = 0; i < half; i++)
{
int predictVal = vector[i];
int j = i + half;
vector[j] = vector[j] - predictVal
}
}
This is what I have so far after converting the above code to MIPS. Assuming $a0 is vector[] and $a1 is N. Again, I am not sure if li or addi is the correct thing to use.
srl $t0, $a1, 1 #t0 holds half. half = N >> 1
addi $t1, $t1, 0 #t1 holds count. count = 0
addi $t2, $t2, 0 #t2 holds i. i = 0
loop: slt $t3, $t2, $t0 #t3 holds 1 if i < half
beg $t3, $zero, exit #exit if t3 == 0
lw $t4, 0($a0) #t4 holds predictValue
addi $a0, $a0, 4 #4 bytes for next word address
addi $t5, $t2, $t0 #t5 holds j. j = i + half
lw $t6, $t6, $t4 #vector[j]=vector[j]-predivtVal
addi $t2, $t2, 1 #i++
j loop
exit: jr $ra
The li (Load immediate) instruction loads a specific numeric value into a register.
The addi (Add inmediate) adds a register and a sign-extended immediate value and stores the result in a register.
So, unless you are 100% sure a register has a zero value, then you shouldn't use an addi instruction to set a register.
For example:
addi $t1, $t1, 0 #t1 holds count. count = 0
You don't know if $t1 is zero at that particular moment. If thats a subroutine, you might be using a garbage value of $t1 (a value from before the invocation of the subroutine, before the jump to the address of the subroutine).
So the safe way is to set the register with li (thus, count=0), not taking into consideration the previous value of the register.

Iterative Binary Search in MIPS

I'm trying to create a iterative binary search in mips, below is my code. It works when searching for the middle value, otherwise it doesnt but i'm not sure why. I'm new to MIPs and trying to get better so any critique is appreciated
.data
myArray: .word 1 4 5 7 9 12 15 17 18 20 21 30
last: #the address that comes after the array
arraySize: .word 11
.globl main
.text
main:
la $s0, myArray # array address
lw $s1, arraySize # arraysize
li $s2, 30 # address of last array entry
jal Binsearch # perform binary search
li $v0, 10
syscall
Binsearch:
li $t0,0 #first = 0
subu $t1, $s1, 1 #last = array size -1
Loop: bge $t0, $t1, DONE # if ! (first < last)
add $t2,$t0,$t1 #first + last
li $t3,2
div $t2, $t3 #$LO = middle index
mflo $t3 #$t3 = middle index
li $s3,4 #load the value 4 into s3
multu $s3, $t3 #multiply middle by 4 to get the offset
mflo $t4 #store the result in t4
add $t4, $s0, $t4 #t4 points to array[mid]
lw $t5, ($t4) #load the value at array[mid] into t5
beq $t5, $s2, return_mid # if t5 == s2 then return the index
blt $t5, $s2, move_right # if t5 < s2 then move right
subu $t1, $t3, 1 #if this line is reached that means that none of the above
j Loop #conditions are true, so t5 > s2, last = mid -1
return_mid:
li $v0, 1
add $a0, $t3, $zero # add the middle index to a0
syscall #print the index
move_right:
addi $t0, $t3, 1 # first = mid + 1
j Loop # jump to Loop
DONE:
li $v0, 1
li $a0, -1
syscall
j $ra #return to the caller
I figured it out, had to test for some corner cases and change the LOOP condition
.data
myArray: .word 1 4 5 7 9 12 15 17 18 20 21 30
last: #the address that comes after the array
arraySize: .word 11
.globl main
.text
main:
la $s0, myArray # array address
lw $s1, arraySize # arraysize
li $s2, 20 #value youre searching for
jal Binsearch # perform binary search
li $v0, 10
syscall
Binsearch:
li $t0,0 #first = 0
move $t1, $s1 #last = array size -1
li $t6,1
li $t7,4 #checks for the last element in the array being the correct value
multu $t7,$t1
mflo $t7
add $t7,$s0,$t7
lw $t5, ($t7)
beq $t5, $s2, last_num # if == then
subu $t1, $s1, 1
Loop: bge $t0, $t1, DONE # if ! (first < last)
add $t2,$t0,$t1 #first + last
li $t3,2
div $t2, $t3 #$LO = middle index
mflo $t3 #$t3 = middle index
beq $t2,$t6, special_case #if first+last = 1 you want totake HI not LO
li $t7,4 #load the value 4 into t7
multu $t7, $t3 #multiply middle by 4 to get the offset
mflo $t4 #store the result in t4
add $t4, $s0, $t4 #t4 points to array[mid]
lw $t5, ($t4) #load the value at array[mid] into t5
beq $t5, $s2, return_mid # if t5 == s2 then return the index
blt $t5, $s2, move_right # if t5 < s2 then move right
subu $t1, $t3, 1 #if this line is reached that means that none of the above
j Loop #conditions are true, so t5 > s2, last = mid -1
special_case:
mfhi $t3 #get the 1 value from hi
li $t7,4 #load the value 4 into t7
multu $t7, $t3 #multiply middle by 4 to get the offset
mflo $t4 #store the result in t4
add $t4, $s0, $t4 #t4 points to array[mid]
lw $t5, ($t4) #load the value at array[mid] into t5
beq $t5, $s2, return_mid # if t5 == s2 then return the index
return_mid:
li $v0, 1
add $a0, $t3, $zero # add the middle index to a0
syscall #print the index
j $ra
move_right:
addi $t0, $t3, 1 # first = mid + 1
j Loop # jump to Loop
last_num:
li $v0, 1
add $a0, $t1, $zero
syscall
j $ra
DONE:
li $v0, 1
li $a0, -1
syscall
j $ra #return to the caller

Nested Loops in MIPS

This is boiling my brain, I've just started learn MIPS. The assignment asks us to use loops and maybe even a stack to do a simple multiplication by squaring a three digit number. For the assignment to be correct, the program needs to run for a minimum of 30 seconds doing the same calculation over and over.
Obviously I'm not asking for you to do my assignment (I want to learn), however I'm stumped on how to implement nested loops in MIPS, there isn't much online. I found something on Stack Overflow and tried to implement the same style but it doesn't work. A single loop works fine, it only runs for one second though so its nowhere near close enough. My problem is how to input a second loop really.
Here's my code:
.data
enterNumber: .asciiz "Enter three digit number \n"
.text
main:
addi $t3, $zero, 0
addi $t1, $zero, 0 #counter for second for loop
#asks for number
li $v0, 4
la $a0, enterNumber
syscall
#receives number
li $v0, 5
syscall
move $t0, $v0 #move number to t0
For1:
beq, $t3, $t0, exit #if counter= t0 then loop ends
For2:
beq, $t1, $t0, For1 #if counter= t0 then loop ends
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t1, $t1, 1 #add 1 to counter
j For2 #jump back to the top
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t3, $t3, 1 #add 1 to counter
j For1 #jump back to for loop
exit:
li $v0, 1
move $a0, $t2 #print out multiplication
syscall
#tell system to stop
li $v0, 10
syscall
The program runs through the inner loop (For2) fine, but its not incrementing the outer loop at all. Thanks in advance
The only problem with your code is that everything you've written in the outer loop(For1), after the inner loop (For2) will never be executed, because of the way you've written the conditions in For2. You only need to make a small change to your loops code: make For2 jump to the last part of your For1 loop in case counter = t0 instead of making it jump to For1.
For1:
beq, $t3, $t0, exit #if counter= t0 then loop ends
For2:
beq, $t1, $t0, exit2 #if counter= t0 then loop ends
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t1, $t1, 1 #add 1 to counter
j For2 #jump back to the top
exit2:
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t3, $t3, 1 #add 1 to counter
j For1 #jump back to for loop
You need to make a small change to your loops code.
Make For2 jump to the last part of your For1 loop in case counter = t0 instead of making it jump to For1.
write below code under For1 loop.
For2exit:
addi $t2, $zero, 0 #resets t2 to 0
mul $t2, $t0, $t0 #multiply number multiplied by number
addi $t3, $t3, 1 #add 1 to counter
j For1 #jump back to for loop
and make change in the for2. make it jump to For2exit rather to For1.