Как правильно умножить два массива 4x4 в сборке MIPS в порядке строк? - PullRequest
0 голосов
/ 20 марта 2019

для задания в моем курсе по программированию на ассемблере я должен умножить две матрицы 4x4 и сохранить результат в мажорном порядке строки, а затем в мажорном столбце.Я кодировал функции для основного порядка строк, но я не уверен, почему результат не сохраняется в $ t7.Я также считаю, что другой проблемой является то, что jr $ ra в rowMulInLoop2 возвращается к основному, а не к месту в rowMulInLoop1, но, опять же, я не уверен, как решить эту проблему.Я довольно новичок в MIPS, но как только я смогу это выяснить, я смогу справиться с основной колонкой самостоятельно.И да, я пробовал отладку, но все еще не уверен, как решить проблемы.(PS Я хотел бы, чтобы мой код был как можно ближе к этому, если только он не ПОЛНОСТЬЮ неверен. Кроме того, я исключил функции rowSum и colSum, поскольку они не имеют отношения к делу).Любая помощь будет принята с благодарностью.Спасибо!

.data

newline: .asciiz "\n"

array1:     .word 2,1,9,2
                .word 7,9,10,10  
                    .word 3,4,4,4
                        .word 2,5,4,4

array2:     .word 8,7,1,2
                .word 2,7,8,6
                    .word 7,5,6,8
                        .word 9,4,8,9

rowMulArray: .space 64
size: .word 4
.eqv DATA_SIZE 4

.text

main:
    lw $a1, size # size of array stored at $a2
    jal rowSum
    la $a0, newline
    li $v0, 4
    syscall
    jal rowMul
    la $a0, newline
    li $v0, 4
    syscall
    jal colSum
    li $v0, 10
    syscall

    rowMul:
        li $t7, 0 # product
        li $t0, 0 # row index for product array
        li $t1, 0 # column index for product array
        move $s0, $zero # row index for array1
        move $s1, $zero # column index for array1
        move $s2, $zero # row index for array2
        move $s3, $zero # column index for array2

        rowMulOutLoop:
            mul $t2, $t0, $a1
            add $t2, $t2, $t1
            mul $t2, $t2, DATA_SIZE

            rowMulInLoop1:
                mul $s4, $s0, $a1
                add $s4, $s4, $s1
                mul $s4, $s4, DATA_SIZE

                mul $s5, $s2, $a1
                add $s5, $s5, $s3
                mul $s5, $s5, DATA_SIZE

                sw $t4, array1($s4)
                sw $t5, array2($s5)

                mul $t6, $t4, $t5
                add $t7, $t7, $t6

                addi $t4, $t4, 4
                addi $s1, $s1, 1
                addi $s2, $s2, 1
                bne $s1, $a1, rowMulInLoop1
                jal rowMulInLoop2
                move $s1, $zero
                move $s2, $zero 
                addi $s0, $s0, 1
                addi $s3, $s3, 1
                bne $s0, $a1, rowMulInLoop1

        rowMulInLoop2:
            sw $t7, rowMulArray($t2)

            move $a0, $t7
            li $v0, 1
            syscall

            addi $t1, $t1, 1
            bne $t1, $a1, rowMulOutLoop
            li $t1, 0
            addi $t0, $t0, 1
            bne $t0, $a1, rowMulOutLoop
        jr $ra
    jr $ra  

1 Ответ

1 голос
/ 20 марта 2019

После расчета индексов для исходных данных вы сохраняете вместо загрузки.

              sw $t4, array1($s4)
              sw $t5, array2($s5)

Это перезаписывает ваш ввод мусором и не обновляет $t4 или $t5. Вы, вероятно, хотите lw.

Могут быть и другие ошибки, но это первая очевидная ошибка, которую я вижу, и полная демонстрация. Используйте ваш отладчик для пошагового выполнения кода и отслеживания изменений в регистрах. Должно было быть очевидно, что $t4 и $t5 не получили правильные значения из исходных данных на тот момент.


Кроме того, обычно следует избегать регистров $s, поскольку они сохраняются при вызове. Вызывающий main может аварийно завершить работу, если вы вернетесь с их изменениями. Если у вас закончились другие регистры, вы можете сохранить / восстановить некоторые регистры $s и / или $lr, чтобы использовать их в качестве нуля, в противном случае есть $t0..9, $v0..1 и $a0..3, которые все закрыты вызовом в обычное соглашение о вызовах MIPS .

Также $at (временный ассемблер), если вы избегаете любых псевдоинструкций, которые используют его как временные, когда они расширяются до реальных инструкций MIPS.

...