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.
I'm very new into coding and we started with MIPS. We were kind of "thrown in to the cold water" and had to implement an algorithm that checks whether the elements of an array are sorted in ascending order. If it is sorted, a 1 is to be stored in $v0, otherwise a 0.
The solution that was given us:
.data
A: .word 1, 2, 3, 4, 5
l: .word 5
.text
main:
la $s0, A #address of A
lw $s1, l
add $t0, $0, $0 #counter for loop
addi $v0, $0, 1
sub $s1, $s1, $v0
for:
beq $t0, $s1, done
sll $t1, $t0, 2 #byte offset
add $t1, $t1, $s0
lw $t1, 0($t1) #$t1 = A[j]
addi $t2, $t0, 1
sll $t2, $t2, 2
add $t2, $t2, $s0
lw $t2, 0($t2) #$t2 = A[j + 1]
sub $t3, $t2, $t1 #$s3 = A[j+1] - A[j]?
slt $t4, $t3, $0
addi $t3, $0, 1
beq $t3, $t4 unsort #A isn’t sorted if A[j+1] - A[j] has a negative value
addi $t0, $t0, 1 #$t0 = $t0 + 1
j for
unsort:
add $v0, $0, $0 #set $v0 if array isn’t sorted
done:
I'm having trouble understanding this code/algorithm. First of all what is an Array and why do we need specifically 5 of them?
But much more important to me is understanding this code/algorithm. So I need someone who is kind enough and explains to me step by step and in simple word :D, how this code works.
Would be very helpful and thanks in advance.
Short answer
Basically, this program iterates over the array A in a loop with loop counter, say i. The index i is initialized with 0 and in every loop iteration incremented by 1 until it reaches l-1, where l is the size/length of the array A. In every iteration the algorithm checks if A[i] < A[i + 1] (i.e. if the i-th and the (i+1)-th element in A are in ascending order and thus are sorted). If so, it continues execution and $v0 remains 1. Otherwise it sets $v0 to 0 and terminates.
Long answer
Arrays and memory
An array is basically an ordered list of data – in this case it is an ordered list of words (a word in MIPS means: 32-bit value, and it consists of 4 bytes, each of which has 8 bits of information). So in this case, every word represents a 32-bit integer.
If we have an array A of length l, the elements are indexed from 0 to l-1. The first element in an array A (notation: A[0]) is saved at a certain address in memory, let's call it addr. The i-th element in A (A[i]) is then saved at the memory address addr + 4*i. This is because memory in MIPS is byte-addressable, i.e., every byte has his own address and because a word consists of 4 bytes, word addresses are offset by 4 (see below).
.data section
A: .word 1, 2, 3, 4, 5
l: .word 5
With that you will realize that you don't have 5 arrays but only one (called A) and it contains the values 1, 2, 3, 4 and 5. Thus, the length is 5 and it is specified in the word l. You could add more values to your array but then you would have to adjust the length because otherwise, strange things will happen (or at least the result will be random). Your data is specified in this .data section and is therefore somewhere stored in your program's memory space.
MIPS assembly
In order to understand the code in the .text section, you have to understand MIPS assembly. If I write about a register, just think about it as a placeholder for a 32-bit value. For example, $0 is the zero register and it always stores a 32-bit 0. Other registers are used to temporarily store values used in your program. The instructions you use are:
la rd, label ("load address")
(rd = address of label; stores the address of the word specified by "label" in the destination register rd)
lw rd, label ("load word")
or
lw rd, offset(rs)
(load data specified by label, or data at address rs+offset into destination register rd)
add rd, rs, rt
(rd = rs + rt; adds source registers rs and rt and stores result in destination register rd)
addi rd, rs, imm ("add immediate")
(rd = rs + imm; adds source register rs and immediate (16-bit constant) value and stores result in destination register rd)
sub rd, rs, rt ("subtract")
(rd = rs - rt; subtracts source register rt from source register rs and stores result in destination register rd)
beq rs, rt, label ("branch if equal")
(if value in rs is equal to value in rt, jump to label)
sll rd, rs, shamt ("shift logic left")
(rd = rs << 2; shift value in rs by two bits the left and store it in rd)
slt rd, rs, rt ("set less than")
(rd = (rs < rt) ? 1 : 0; if the value in rs is smaller than the value in rt, set rd to 32-bit 1, otherwise to 32-bit 0)
j label ("jump")
(jump to label)
.text section
main:
la $s0, A
lw $s1, l
add $t0, $0, $0
addi $v0, $0, 1
sub $s1, $s1, $v0
for:
beq $t0, $s1, done
sll $t1, $t0, 2 #byte offset
add $t1, $t1, $s0
lw $t1, 0($t1) #$t1 = A[j]
addi $t2, $t0, 1
sll $t2, $t2, 2
add $t2, $t2, $s0
lw $t2, 0($t2) #$t2 = A[j + 1]
sub $t3, $t2, $t1 #$s3 = A[j+1] - A[j]?
slt $t4, $t3, $0
addi $t3, $0, 1
beq $t3, $t4 unsort #A isn’t sorted if A[j+1] - A[j] has a negative value
addi $t0, $t0, 1 #$t0 = $t0 + 1
j for
unsort:
add $v0, $0, $0 #set $v0 if array isn’t sorted
done:
This assembly code is equivalent to the pseudocode (if you are not used to pseudocode or to while loops, please look it up in the internet):
s0 <- address of first element in A
s1 <- l
t0 <- 0
v0 <- 1
s1 <- s1-1
while (t0 != s1) do
t1 <- 4 * t0
t1 <- t1 + s0
t1 <- word at address t1
t2 <- t0 + 1
t2 <- 4 * t2
t2 <- t2 + s0
t2 <- word at address t2
t3 <- t2 - t1
if (t3 < 0) then t4 <- 1
else t4 <- 0
t3 <- 1
if (t3 == t4) then
v0 <- 0
return
else t0 <- t0 + 1
Hope, this helped. I think it is quite ambitious to start with assembly code if you haven't coded before. Good luck!