# Your name:
# Your student id:
# Your email address:
# output messages
PleaseMsgA1: .asciiz “Please enter the size of your matrix A:\n”
PleaseMsgA2: .asciiz “Please enter integers in array A[] one by one:\n”
PleaseMsgF1: .asciiz “Please enter the size of your matrix F:\n”
PleaseMsgF2: .asciiz “Please enter integers in array F[] one by one:\n”
MatrixMsgA1: .asciiz “A[”
MatrixMsgF1: .asciiz “F[”
MatrixMsgB1: .asciiz “B[”
MatrixMsg2: .asciiz “][”
MatrixMsg3: .asciiz “]: ”
OutMsg1: .asciiz “After convolution:\n”
space: .asciiz “\t”
newline: .asciiz “\n”
A: .word 0:100
F: .word 0:50
B: .word 0:100
A_size: .word 0
F_size: .word 0
B_size: .word 0
.globl main
# $s0 :base addr of A;
# $s1 :size of A[];
# $s2 :base addr of F;
# $s3 :size of F[];
# $s4 :base addr of B;
# $s5 :size of B[];
la $s0,A # $s0 :base addr of A;
la $s2,F # $s2 :base addr of F;
la $s4,B # $s4 :base addr of B;
#—- region : message befor input matrix A
# cout << "Please enter the size of your matrix A:" << endl;
la $a0, PleaseMsgA1
addi $v0, $zero, 4
# cin >> A_size; use $s1
add $s1,$v0,$zero
# cout << "Please enter integers in array A[] one by one:" << endl;
la $a0, PleaseMsgA2
addi $v0, $zero, 4
#---- endregion
#---- region : input A[i][j], for loop, use $t0,t1, save in $s0, size is $s1
A_outer_for_Loop:
beq $t0,$s1,A_exit_outer_for_Loop
add $t1,$zero,$zero
A_inner_for_Loop:
beq $t1,$s1,A_exit_inner_for_Loop
# cout << "A["
la $a0, MatrixMsgA1
addi $v0, $zero, 4
# print index
add $a0,$t0,$zero
addi $v0, $zero, 1
# cout << "]["
la $a0, MatrixMsg2
addi $v0, $zero, 4
# print index
add $a0,$t1,$zero
addi $v0, $zero, 1
# cout << "]: "
la $a0, MatrixMsg3
addi $v0, $zero, 4
# read user input in $v0
add $v1,$v0,$zero
#### need multiply
add $a0,$t0,$zero
add $a1,$s1,$zero
jal multiply #calculate A_size*i
add $t3,$v0,$zero #A_size*i in $t3
add $t3,$t3,$t1 #idx = A_size*i + j
sll $t3,$t3,2 # calculate the offset for the element A[idx] (i.e. idx*4)
add $t3,$t3,$s0 # calculate the addr of A[idx], $t3 = i*4 + base of A in $s0
sw $v1, 0($t3) # A[idx] = $v0 (user input from the previous syscall)
addi $t1,$t1,1
j A_inner_for_Loop
A_exit_inner_for_Loop:
addi $t0,$t0,1
j A_outer_for_Loop
A_exit_outer_for_Loop:
#---- endregion
#---- region : message befor input matrix F
# cout << "Please enter the size of your matrix F:" << endl;
la $a0, PleaseMsgF1
addi $v0, $zero, 4
# cin >> F_size; use $s3
add $s3,$v0,$zero
# cout << "Please enter integers in array F[] one by one:" << endl;
la $a0, PleaseMsgF2
addi $v0, $zero, 4
#---- endregion
#---- region : input F[i][j], for loop, use $t0,t1, save in $s2, size is $s3
F_outer_for_Loop:
beq $t0,$s3,F_exit_outer_for_Loop
add $t1,$zero,$zero
F_inner_for_Loop:
beq $t1,$s3,F_exit_inner_for_Loop
# cout << "F["
la $a0, MatrixMsgF1
addi $v0, $zero, 4
# print index
add $a0,$t0,$zero
addi $v0, $zero, 1
# cout << "]["
la $a0, MatrixMsg2
addi $v0, $zero, 4
# print index
add $a0,$t1,$zero
addi $v0, $zero, 1
# cout << "]: "
la $a0, MatrixMsg3
addi $v0, $zero, 4
# read user input in $v0
add $v1,$v0,$zero
#### need multiply
add $a0,$t0,$zero
add $a1,$s3,$zero
#addi $sp,$sp,-4 #back up $ra
#sw $ra,($sp)
jal multiply
#lw $ra,($sp) #restore $ra
#addi $sp,$sp,4
add $t3,$v0,$zero # idx=$t3= F_size*i
add $t3,$t3,$t1 # idx=$t3= F_size*i+j
sll $t3,$t3,2 # calculate the offset of F[idx] (i.e. idx*4)
add $t3,$t3,$s2 # calculate for the addr of F[idx], $t3 = i*4 + base of F in $s2,
sw $v1, 0($t3) # F[idx] = $v1 (the input from the previous syscall
addi $t1,$t1,1
j F_inner_for_Loop
F_exit_inner_for_Loop:
addi $t0,$t0,1
j F_outer_for_Loop
F_exit_outer_for_Loop:
#---- endregion
#---- region : prepare for and then call TwoDimensionConv() subroutine
sub $s5,$s1,$s3
addi $s5,$s5,1 #$s5=B_size=A_size-F_size-1
add $a0,$s1,$zero #Put A_size into $a0 for TwoDimensionConv()
add $a1,$s3,$zero #Put F_size into $a1 for TwoDimensionConv()
#There is no need to provide base addresses of A[], F[], and B[] to TwoDimensionConv
#as they are in $s0,$s2,$s4
jal TwoDimensionConv
#---- endregion
#---- region : message befor output matrix B
# cout << "After convolution:" << endl;
la $a0, OutMsg1
addi $v0, $zero, 4
#---- endregion
#---- region : ouput B[i][j], for loop, use $t0,t1, saveed in $s4, size is $s5
B_outer_for_Loop:
beq $t0,$s5,B_exit_outer_for_Loop
B_inner_for_Loop:
beq $t1,$s5,B_exit_inner_for_Loop
# cout << "B["
la $a0, MatrixMsgB1
addi $v0, $zero, 4
# print index
add $a0,$t0,$zero
addi $v0, $zero, 1
# cout << "]["
la $a0, MatrixMsg2
addi $v0, $zero, 4
# print index
add $a0,$t1,$zero
addi $v0, $zero, 1
# cout << "]: "
la $a0, MatrixMsg3
addi $v0, $zero, 4
#### need multiply
add $a0,$t0,$zero
add $a1,$s5,$zero
jal multiply
add $t3,$v0,$zero
add $t3,$t3,$t1
sll $t3,$t3,2
add $t3,$t3,$s4 # $t3 = i*4 + base of B in $s4, addr of B[idx]
lw $a0, 0($t3)
addi $v0, $zero, 1
la $a0, space
addi $v0, $zero, 4
syscall # cout << B[idx] << ", ";
addi $t1,$t1,1
j B_inner_for_Loop
B_exit_inner_for_Loop:
la $a0, newline
addi $v0, $zero, 4
syscall # cout << endl;
addi $t0,$t0,1
j B_outer_for_Loop
B_exit_outer_for_Loop:
#---- endregion
#---- region : end this program
addi $v0, $zero, 10
#---- endregion
#---- region : subroutine of multipy(), use $t4 but use stack to save%restore
#this multiply procedure will modify $t4 and $v0
enter_m_for:
beq $t4,$a1,exit_m_for
add $v0,$v0,$a0
addi $t4,$t4,1
j enter_m_for
exit_m_for:
#---- endregion
#The TwoDimensionConv() procedure
#Input argments:
#$a0 = A_size
#$a1 = F_size
#Different than the C++ function, the following arguments are in the saved registers (i.e. $s0 - $s5) and are not passed
#This function can directly read the values from the saved registers.
# assume base addr of A[] already in $s0, so do not need to pass
# assume base addr of B[] already in $s4, so do not need to pass
# assume base addr of F[] already in $s2, so do not need to pass
# assume B_size already in $s5, so do not need to pass
# If you decide to change the saved register values in this function, then remember to preserve registers according to the MIPS register convention on slide 76 of the ISA note set
# In general, preserve registers accoding to slide 76 of the ISA note set
#output: none
#effect: calculates and stores all the elements of the output matrix B
##
#this function needs to call the ConvForElement() for calculating B_ij, refer to the C++ program for the details
#the convForElement() procdure will change the following registers:
#$t2, $t3, $t6, $t7, $t8, $t9, $v0
#If you need to use these registers in the implementation of this procedure
#make sure you 1) backup them before calling convForElement , 2) restore them right after calling convForElement()
#make sure the $sp to be the same before and after doing 1) and 2) above (i.e. allocate n bytes, delocate n bytes)
##
#this function also calls the multiply() procedure, and multiply() changes the following register:
#If you need to use these registers in the implementation of this procedure
#make sure you 1) backup them before calling multiply() , 2) restore them right after calling multiply()
#make sure the $sp to be the same before and after doing 1) and 2) above (i.e. allocate n bytes, delocate n bytes)
##
#this function will make function calls, make sure you backup $ra at the beginning of the function and restore it before returning
TwoDimensionConv:
#TODO Below
#TODO Above
#The ConvForElement() procedure
#input arguments:
# $a0: B_i
# $a1: B_j
# $a2: A_size
# $a3: F_size
# assume base addr of A[] already in $s0, so do not need to pass
# assume base addr of F[] already in $s2, so do not need to pass
#return value:
# $v0: local_sum (calculated value for B_ij, refer to the C++ program)
# registers used in the procedure:
# $t2: F_i
# $t3: F_j
# $t6: local_sum
# $t7: for holding the addresses of A[A_idx], F[F_idx]
# $t8: F_idx; also content of F[F_idx]
# $t9: A_idx; also content of A[A_idx]
ConvForElement:
#backup $ra
addi $sp,$sp,-4
sw $ra,($sp)
# F_i loop starts
li $t2,0 #f_idx=0
F_i_for_Loop:
beq $t2,$a3,F_i_exit_for_Loop
# F_j loop starts
F_j_for_Loop:
beq $t3,$a3,F_j_exit_for_Loop
## below calculates F_idx in $t8, F_idx=F_size*F_i +F_j
# need multiply
addi $sp,$sp,-8 #allocate 2 words
sw $a0,($sp) #back up $a0
sw $a1,4($sp) #back up $a1
add $a0,$t2,$zero #$a0=F_i
add $a1,$a3,$zero #$a1=F_Size
jal multiply #calculate F_size*F_i
lw $a1,4($sp) #restore $a1
lw $a0,0($sp) #restore $a0
addi $sp,$sp,8 #delocate 2 words
add $t8,$v0,$zero #$t8=F_size*F_i
add $t8,$t8,$t3 #$t8=F_size*F_i + F_j
## above calculates F_idx in $t8, F_idx=F_size*F_i + F_j
## below calculates A_idx in $t9, A_idx=A_size*(B_i+F_i)+B_j+F_j
add $t9,$a0,$t2 #$t9=B_i+F_i
# need multiply
addi $sp,$sp,-8 #allocate 2 words
sw $a0,($sp) #back up $a0
sw $a1,4($sp) #back up $a1
add $a0,$t9,$zero
add $a1,$a2,$zero
jal multiply #calculate A_size*(B_i+F_i)
lw $a1,4($sp) #restore $a1
lw $a0,0($sp) #restore $a0
addi $sp,$sp,8 #delocate 2 words
add $t9,$v0,$zero#$t9=A_size*(B_i+F_i)
add $t9,$t9,$a1 #$t9=A_size*(B_i+F_i)+B_j
add $t9,$t9,$t3 #$t9=A_size*(B_i+F_i)+B_j+F_j
## the above calculates A_idx in $t9, A_idx=A_size*(B_i+F_i)+B_j+F_j
sll $t7,$t8,2 # calculate the offset $t7=F_idx*4
add $t7,$t7,$s2 # $t7 = F_idx*4 + base of F
lw $t8, 0($t7) # $t8 = F[F_idx]
sll $t7,$t9,2 # calculate the offset $t7=A_idx*4
add $t7,$t7,$s0 # $t7 = A_idx*4 + base of A
lw $t9, 0($t7) # $t9 = A[A_idx]
bltz $t8, do_sub # if F[F_idx]<0 then local_sum=local_sum-A[A_idx]
bgtz $t8, do_add # if F[F_idx]>0 then local_sum=local_sum+A[A_idx]
j ctn_with_F_i_Loop
sub $t6, $t6, $t9 # $t6 is local_sum, local_sum = local_sum – A[A_idx]
j ctn_with_F_i_Loop
add $t6, $t6, $t9 # $t6 is local_sum, local_sum = local_sum + A[A_idx]
j ctn_with_F_i_Loop
ctn_with_F_i_Loop:
addi $t3,$t3,1 #increment F_j
j F_j_for_Loop #start another iteration of F_j loop
F_j_exit_for_Loop:
addi $t2,$t2,1 #increment F_i
j F_i_for_Loop #start another iteration of F_i loop
F_i_exit_for_Loop:
add $v0,$t6,$zero #Copy local_sum to $v0 before returning
#restore $ra
lw $ra,($sp)
add $sp,$sp,4