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。

此外,在向地址添加地址或向地址偏移时,应使用 addunsigned 版本(即 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]