我尝试使用MIPS程序集实现矩阵乘法。该行" lw $ t4,0($ t4)"在第二个循环中通过k_loop。错误是:" 0x00400090处的运行时异常:提取地址未在字边界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
答案 0 :(得分:2)
有三个不同的问题,由对齐故障掩盖。
您正在计算数组索引 [对于int
数组]。在将这些添加到矩阵的基址之前,必须将它们转换为字节偏移。
否则,您将[因为 获得]对齐错误,因为mips要求字的地址(即lw/sw
)是四字节对齐的。
第二个问题是当你尝试从索引中减去一个时。即使评论显示为-4
,您也会使用-1
的值。因此,在某种程度上,您需要混合和匹配索引计算和偏移计算
考虑一个从地址int
开始的简单1D 0x10010000
数组/向量。地址映射的索引是:
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。
此外,在向地址添加地址或向地址添加偏移时,应使用 unsigned 版本的add
(即addu
)来防止溢出/换行< em>可以发生地址。
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]
您需要随时随地添加此额外步骤。
第三个问题是最终地址0x1000fffd
,而不是四个字节对齐,低于 .data
段中mars
段允许的最低地址(即0x10010000
),所以如果你没有得到对齐错误,你就会访问不存在的内存[会发出不同类型的错误]
因此,您可能需要仔细检查索引计算的正确性,以防止等同于访问int myarray[2]; myarray[-1] = 3;
[即UB]