Умножение в MIPS - PullRequest
       28

Умножение в MIPS

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

У меня есть следующий код, но я продолжаю получать сообщение об ошибке арифметического переполнения. Проблема, которую я пытаюсь решить, состоит в умножении двух 31-битных чисел и сохранении результатов в $ t2 $ t3 и распечатке правильного результата. Кажется, я кодировал два числа, которые нужно умножить, а конечный результат - 31-разрядное число.

Мне бы хотелось сузиться, где я чувствую, что я иду не так, но я, честно говоря, не вижу, где и что мне нужно изменить.

# program to multiply two 31 bit binary numbers (A & B),

# using the “shift and add” .

.data

# declare the variable lables of ASCII storage type.

prompt1: .asciiz "Enter number 1: "

prompt2: .asciiz "Enter number 2: "

result: .asciiz "The multiplication of two 31 bit binary numbers is: "

.text

главный:

            #prompt1.

            li $v0, 4   

            la $a0, prompt1

            syscall

           #read number 1 and store in the register $t0

            li $v0, 5        

            syscall  

            move $t0, $v0



            #prompt2.

            li $v0, 4   

            la $a0, prompt2

            syscall



            #read number 2 and store in the register $t1

            li $v0, 5        

            syscall  

            move $t1, $v0



            li $t2, 0 # The final result of the multiplication

                            #is saved into the register $t2

            li $t3, 1 # Mask for extracting bit!

            li $s1, 0 # set the Counter to 0 for loop.   

умножения:

            #if the Counter $s1 is equal to 31, then go the lable exit

            beq $s1, 31, exit

            and $s2, $t1, $t3

            sll $t3, $t3, 1

                    beq $s2, 0, increment

            add $t2, $t2, $t0

прибавка:

            sll $t0, $t0, 1

            addi $s1, $s1, 1

            j multiply

выход:

            #display the result string.

            li $v0, 4   

            la $a0, result

            syscall

                            #display the result value.

            li $v0, 1

            add $a0, $t2, $zero

            syscall



            li $v0, 10 # system call code for exit = 10

            syscall   # call operating sys

Пример ввода A: 1143330295 (десятичный) Пример ввода B: 999999223 (десятичное число)

1 Ответ

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

Вот возможная реализация.

Отличия от вашего кода:

  • умножение 32x32 дает 64-битный результат.На 32-битных мипах результат должен быть разделен на два регистра

  • вместо операнда смещения влево, который приводит к переполнению, результат смещается вправо.Выданные биты сохраняются и повторно вводятся в нижней части результата

  • используйте addu для сложения.Числа являются беззнаковыми и без переполнений операций без знака может произойти

  • измененный цикл в форме "do while".Счетчик циклов уменьшается

Отображаемый результат в настоящее время состоит из двух частей.Неправильное отображение может произойти, если установлен LSB (и рассматривается как отрицательный знак со значением display int syscall), но большинство симуляторов mips не имеют возможности отображать большие неподписанные значения.

# program to multiply two 31 bit binary numbers (A & B),
# using the “shift and add” .

.data
# declare the variable lables of ASCII storage type.
prompt1: .asciiz "Enter number 1: "
prompt2: .asciiz "Enter number 2: "
result: .asciiz "The multiplication of two 31 bit binary numbers is: "
result2: .asciiz "\nand the upper part of result is: "

.text
main:
        #prompt1.
        li $v0, 4   
        la $a0, prompt1
        syscall

        #read number 1 and store in the register $t0
        li $v0, 5        
        syscall  
        move $t0, $v0

        #prompt2.
        li $v0, 4   
        la $a0, prompt2
        syscall

        #read number 2 and store in the register $t1
        li $v0, 5        
        syscall  
        move $t1, $v0

        li $t2, 0 # The final result of the multiplication is 64 bits
                  # MSB part is in register $t2
        li $t4, 0 #  and LSB part of result is in $t4
        li $t3, 1 # Mask for extracting bit!
        li $s1, 32 # set the Counter to 32 for loop.   

multiply:
        and $s2, $t1, $t3
        beq $s2, 0, increment
        addu $t2, $t2, $t0

increment:
        sll $t3, $t3, 1 # update mask
        ##sll $t0, $t0, 1 # useless, we srl result instead
        andi $s4, $t2,1  # save lsb of result
        srl $t2,$t2,1    # t2>>=1
        srl $t4,$t4,1    # t4>>=1
        sll $s4,$s4,31
        or  $t4,$t4,$s4  # reinject saved lsb of result in msb of $t4
        addi $s1, $s1, -1 # decrement loop counter
        #if the Counter $s1 reaches 0 then go the label exit
        beq $s1, $zero, exit
        j multiply

exit:
        #display the result string.
        ## must be changed to take into account the 64 bits of the result
        ## but AFAIK, there is no syscall for that
        ## can be done in two steps t4 and t2
        ## and result is t4+2**32*t2
        #display the result value.
        li $v0, 4   
        la $a0, result
        syscall
        li $v0, 1  # if using mars replace 1 by 36 to print as an unsigned
        add $a0, $t4, $zero
        syscall
        li $v0, 4   
        la $a0, result2
        syscall
        li $v0, 1 # if using mars replace 1 by 36 to print as an unsigned
        add $a0, $t2, $zero
        syscall

        li $v0, 10 # system call code for exit = 10
        syscall   # call operating sys
...