MIPS汇编,矩阵乘法

时间:2017-03-07 01:17:17

标签: mips matrix-multiplication

我尝试使用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

1 个答案:

答案 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]