MIPS 汇编,矩阵乘法
MIPS Assembly, matrix multiplication
我正在尝试使用 MIPS 汇编实现矩阵乘法。通过 k_loop 的第二个循环中的 "lw $t4, 0($t4)" 行有错误。错误是:"Runtime exception at 0x00400090: fetch address not aligned on word boundary 0x1000fffd"。有人可以解释错误的含义以及我可以做些什么来解决它吗?谢谢。
.data
matrixA: .word 1,2,3,4,5,6 #Content of matrixA in array form
matrixB: .word 5,6,7,8,9,10 #Content of matrixB in array form
sizeA: .word 3,2 #Defines matrixA as being a 3x2 matrix
sizeB: .word 2,3 #Defines matrixB as being a 2x3 matrix
result: .word 0:9 #Initialize result as being an array of length 9 populated with 0
tab: .asciiz "\t"
newLine: .asciiz "\n"
.globl _main
.text
_main: la $s0, matrixA #s0 set to base address of matrixA
la $s1, matrixB #s1 set to base address of matrixB
la $s2, sizeA #s2 set to base address of sizeA
nop
lw $s3, 4($s2) #s3 set to second val in sizeA (col #)
nop
lw $s2, 0($s2) #s2 set to first val in sizeA (row #)
la $s4, sizeB #s4 set to base address of sizeB
nop
lw $s5, 4($s4) #s5 set to second val in sizeB (col #)
nop
lw $s4, 0($s4) #s4 set to first val in sizeB (row #)
la $s6, result #s6 set to base adress of result
add $s7, $s5, $zero #s7 set to col # in result matrix
add $t0, $zero, $zero #Set t0 to zero. i = 0
add $t1, $zero, $zero #Set t1 to zero. j = 0
add $t2, $zero, $zero #Set t2 to zero. k = 0
li $t3, 0 #Result position set to zero
i_loop: beq $t0, $s2, i_end #End i_loop if i = rowsA
nop
j_loop: beq $t1, $s5, j_end #End j_loop if j = colsB
nop
k_loop: beq $t2, $s4, k_end #End k_loop if k = rowsB
nop
#loop body
li $t4, 0
li $t5, 0
li $t6, 0
#i * M + k - 1
mul $t4, $t0, $s3 #i * #col in matrixA
add $t4, $t4, $t2 #t4 + k
addi $t4, $t4, -4 #t4 -1
add $t4, $t4, $s0 #Now points to value at matrixA[i][k]
lw $t4, 0($t4) #Loads value at matrixA[i][k]
#k * M + j - 1
mul $t5, $t2, $s5 #k * #col in matrixB
add $t5, $t5, $t1 #t5 + j
addi $t5, $t5, -4 #t5 -1
add $t5, $t5, $s1 #t5 now points to value at matrixB[k][j]
lw $t5, 0($t5) #t5 loads value at matrixB[k][j]
#i * M + j - 1
mul $t6, $t0, $s7 #i * #col in result
add $t6, $t6, $t1 #t6 + j
addi $t6, $t6, -4 #t6 -1
add $t6, $t6, $s6 #t6 now points to value at result[i][j]
lw $t8, 0($t6) #t6 loads value at result[i][j]
mul $t7, $t4, $t5 #t7 = matrixA[i][k]*matrixB[k][j]
add $t9, $t8, $t7 #t8 = result[i][j] + matrixA[i][k]*matrixB[k][j]
sw $t9, 0($t6)
#end loop body
addi $t2, $t2, 1 #k++
j k_loop #Return to start of k_loop
k_end:
addi $t1, $t1, 1 #j++
li $t2, 0 #Resets k counter to 0
j j_loop #Return to start of j_loop
j_end:
addi $t0, $t0, 1 #i++
li $t1, 0 #Resets j counter to 0
j i_loop #Return to start of i_loop
i_end: #print
对齐错误掩盖了三个明显的问题。
您正在计算数组 indexes [对于 int
数组]。在将这些添加到矩阵的基地址之前,必须将它们转换为 byte offsets.
否则,你会[像你所做的那样得到一个对齐错误,因为 mips 要求字的地址(即 lw/sw
)是四字节对齐的。
第二个问题是当您尝试从索引中减一时。您使用的是 -4
的值,即使注释显示 -1
。因此,在某种程度上,您正在混合和匹配索引计算和偏移量计算
考虑一个从地址 0x10010000
开始的简单一维 int
array/vector。地址映射的索引为:
index offset address
----- ------ --------
0 0 10010000
1 4 10010004
2 8 10010008
在您的代码中,您有:
addi $t4,$t4,-4 # t4 - 1
add $t4,$t4,$s0 # Now points to value at matrixA[i][k]
lw $t4,0($t4) # Loads value at matrixA[i][k]
最终索引(例如$t4
)需要乘以sizeof(int)
[即4]然后加入矩阵基地址。执行此操作的惯用方法是左移 2。
此外,在向地址添加地址或向地址偏移时,应使用 add
的 unsigned 版本(即 addu
)以防止overflow/wrap 地址可以 。
addi $t4,$t4,-1 # t4 - 1
sll $t4,$t4,2 # convert index to byte offset
addu $t4,$t4,$s0 # Now points to value at matrixA[i][k]
lw $t4,0($t4) # Loads value at matrixA[i][k]
你需要添加这个额外的步骤whenever/wherever你做这些索引计算。
第三个问题是最终地址 0x1000fffd
虽然不是四字节对齐,但也是 低于 中 .data
段允许的最低地址 mars
(即 0x10010000
),所以如果你没有对齐错误,你将访问不存在的内存[这将发出不同类型的错误]
因此,您可能需要仔细检查索引计算的正确性,以防止等同于访问 int myarray[2]; myarray[-1] = 3;
[这是 UB]
我正在尝试使用 MIPS 汇编实现矩阵乘法。通过 k_loop 的第二个循环中的 "lw $t4, 0($t4)" 行有错误。错误是:"Runtime exception at 0x00400090: fetch address not aligned on word boundary 0x1000fffd"。有人可以解释错误的含义以及我可以做些什么来解决它吗?谢谢。
.data
matrixA: .word 1,2,3,4,5,6 #Content of matrixA in array form
matrixB: .word 5,6,7,8,9,10 #Content of matrixB in array form
sizeA: .word 3,2 #Defines matrixA as being a 3x2 matrix
sizeB: .word 2,3 #Defines matrixB as being a 2x3 matrix
result: .word 0:9 #Initialize result as being an array of length 9 populated with 0
tab: .asciiz "\t"
newLine: .asciiz "\n"
.globl _main
.text
_main: la $s0, matrixA #s0 set to base address of matrixA
la $s1, matrixB #s1 set to base address of matrixB
la $s2, sizeA #s2 set to base address of sizeA
nop
lw $s3, 4($s2) #s3 set to second val in sizeA (col #)
nop
lw $s2, 0($s2) #s2 set to first val in sizeA (row #)
la $s4, sizeB #s4 set to base address of sizeB
nop
lw $s5, 4($s4) #s5 set to second val in sizeB (col #)
nop
lw $s4, 0($s4) #s4 set to first val in sizeB (row #)
la $s6, result #s6 set to base adress of result
add $s7, $s5, $zero #s7 set to col # in result matrix
add $t0, $zero, $zero #Set t0 to zero. i = 0
add $t1, $zero, $zero #Set t1 to zero. j = 0
add $t2, $zero, $zero #Set t2 to zero. k = 0
li $t3, 0 #Result position set to zero
i_loop: beq $t0, $s2, i_end #End i_loop if i = rowsA
nop
j_loop: beq $t1, $s5, j_end #End j_loop if j = colsB
nop
k_loop: beq $t2, $s4, k_end #End k_loop if k = rowsB
nop
#loop body
li $t4, 0
li $t5, 0
li $t6, 0
#i * M + k - 1
mul $t4, $t0, $s3 #i * #col in matrixA
add $t4, $t4, $t2 #t4 + k
addi $t4, $t4, -4 #t4 -1
add $t4, $t4, $s0 #Now points to value at matrixA[i][k]
lw $t4, 0($t4) #Loads value at matrixA[i][k]
#k * M + j - 1
mul $t5, $t2, $s5 #k * #col in matrixB
add $t5, $t5, $t1 #t5 + j
addi $t5, $t5, -4 #t5 -1
add $t5, $t5, $s1 #t5 now points to value at matrixB[k][j]
lw $t5, 0($t5) #t5 loads value at matrixB[k][j]
#i * M + j - 1
mul $t6, $t0, $s7 #i * #col in result
add $t6, $t6, $t1 #t6 + j
addi $t6, $t6, -4 #t6 -1
add $t6, $t6, $s6 #t6 now points to value at result[i][j]
lw $t8, 0($t6) #t6 loads value at result[i][j]
mul $t7, $t4, $t5 #t7 = matrixA[i][k]*matrixB[k][j]
add $t9, $t8, $t7 #t8 = result[i][j] + matrixA[i][k]*matrixB[k][j]
sw $t9, 0($t6)
#end loop body
addi $t2, $t2, 1 #k++
j k_loop #Return to start of k_loop
k_end:
addi $t1, $t1, 1 #j++
li $t2, 0 #Resets k counter to 0
j j_loop #Return to start of j_loop
j_end:
addi $t0, $t0, 1 #i++
li $t1, 0 #Resets j counter to 0
j i_loop #Return to start of i_loop
i_end: #print
对齐错误掩盖了三个明显的问题。
您正在计算数组 indexes [对于 int
数组]。在将这些添加到矩阵的基地址之前,必须将它们转换为 byte offsets.
否则,你会[像你所做的那样得到一个对齐错误,因为 mips 要求字的地址(即 lw/sw
)是四字节对齐的。
第二个问题是当您尝试从索引中减一时。您使用的是 -4
的值,即使注释显示 -1
。因此,在某种程度上,您正在混合和匹配索引计算和偏移量计算
考虑一个从地址 0x10010000
开始的简单一维 int
array/vector。地址映射的索引为:
index offset address
----- ------ --------
0 0 10010000
1 4 10010004
2 8 10010008
在您的代码中,您有:
addi $t4,$t4,-4 # t4 - 1
add $t4,$t4,$s0 # Now points to value at matrixA[i][k]
lw $t4,0($t4) # Loads value at matrixA[i][k]
最终索引(例如$t4
)需要乘以sizeof(int)
[即4]然后加入矩阵基地址。执行此操作的惯用方法是左移 2。
此外,在向地址添加地址或向地址偏移时,应使用 add
的 unsigned 版本(即 addu
)以防止overflow/wrap 地址可以 。
addi $t4,$t4,-1 # t4 - 1
sll $t4,$t4,2 # convert index to byte offset
addu $t4,$t4,$s0 # Now points to value at matrixA[i][k]
lw $t4,0($t4) # Loads value at matrixA[i][k]
你需要添加这个额外的步骤whenever/wherever你做这些索引计算。
第三个问题是最终地址 0x1000fffd
虽然不是四字节对齐,但也是 低于 中 .data
段允许的最低地址 mars
(即 0x10010000
),所以如果你没有对齐错误,你将访问不存在的内存[这将发出不同类型的错误]
因此,您可能需要仔细检查索引计算的正确性,以防止等同于访问 int myarray[2]; myarray[-1] = 3;
[这是 UB]