2015-01-09 6 views
2

У меня проблема с проектом MIPS. Задача состоит в том, чтобы умножить двоичное число (double) на целое число со знаком без использования блока с плавающей запятой. Он почти работает, но для некоторых чисел возникает ошибка (например, float-123456789123456, int - 1). По ошибке я имею в виду, что после 7-го числа мой результат кажется отличным от правильного. Я подозреваю, что может возникнуть проблема с переносом некоторого бита во время процедуры (возможно, при добавлении $ high of mantissa2 и $ low of mantissa2). Я попытался исправить это, но до сих пор я понятия не имею, как это сделать. Пожалуйста, проверьте мой код и исправьте его, если это возможно.MIPS - IEEE binary64 (double) и целочисленное умножение со знаком

  .data 
text1: .asciiz "Enter double: " 
text2: .asciiz "Enter integer: " 
text3: .asciiz "Result: " 
quest: .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: " 

num1a: .word  0   #multiplicand and result(sign exponent and first part of mantissa) 
num1b: .word  0   #second part of the multiplicand and result(remaining part of mantissa) 
num2: .word  0   #integer 

    .text 
    .globl input  
input: 
    #print "Enter double: " 
    la $a0, text1 
    li $v0, 4 
    syscall 
    # saving input double into num1 
    li $v0, 7 
    syscall     
    swc1 $f0, num1b 
    swc1 $f1, num1a 
    #print "Enter integer: " 
    la $a0, text2 
    li $v0, 4 
    syscall 
    # saving input int into num2 
    li $v0, 5 
    syscall 
    sw $v0, num2 
    # loading data to registers 
    lw $t0, num1a 
    lw $t1, num1b 
    lw $t2, num2 
#########################################################sign 
sign:  
    move $t3, $t0 
    andi $t3, $t3, 0x80000000 #preserve sign, zero the rest 
    bgez $t2, extract  #if less than zero we change the final sign and negate the value of integer 
    xori $t3, $t3, 0x80000000 #multiply signs (if integer is negative, then the sign is equal to $s0) 
    neg $t2, $t2  #absolute value of int 
extract:  
################################################checking for zero 
    or $t5, $t0, $t1  #if both part of double are equal to zero we skip all the calculation 
    beqz $t5, result_zero 
    beqz $t2, result_zero 
###############################sign, exponent and mantissa 
    move $t7, $t0  
    andi $t7, $t7, 0x7FF00000 #extracting exponent to $t7 
    move $t8, $t0 
    andi $t8, $t8, 0x000FFFFF #extracting first part of mantissa 
    ori  $t8, $t8, 0x00100000 #adding prefix one to mantissa 
    #remaining mantissa stays in register $t1 
######################################################### 
multiply: 
    ########################multiplying mantissa part 1 
    multu $t8, $t2  #multiply mantissa1 by integer 
    mflo $t8   #low part of multiplication to $t8 
    mfhi $s1   #high part of multiplication to $s1 
    ########################multiplying mantissa part 2 
    multu $t1, $t2  #mantissa part 2 multiplication 
    mflo $t1   #low part to $t1 
    mfhi $t0   #with overflow going to $t0 
    ########################partial accumulation 
    addu $t8, $t8, $t0  #adding the high part of mantissa2 to result of low part of mantissa1 
    bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high 
    addiu $s1, $s1, 1 
    ###### 
skip_add: 
    bnez $s1, shift 
    bltu $t8, 0x00200000, result  
shift: #else we shift 3 parts of mantissa and increment the the exponent 
    ###extracting least significant bit of high mantissa1 
    sll $s2, $s1, 31  #copying least significant beat of $s1 to most significant bit in $s2 
    sll $t9, $t8, 31  #copying least significant beat of $s8 to most significant bit in $t9 
    ###### 
    srl $s1, $s1, 1  #shifting right mantisa part1 high 
    srl $t8, $t8, 1  #shifting right mantisa part1 low 
    or $t8, $t8, $s2  #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low 
    srl $t1, $t1, 1  #shifting right mantisa part2 
    or $t1, $t1, $t9  #copying least significant bit from mantissa1 to most significant bit of mantissa2 
    ###### 
    addiu $t7, $t7, 0x00100000 #increment exponent by one 
    ###### 
    bnez $s1, shift  #if mantissa1 high is greater than zero we continue 
    bgeu $t8, 0x00200000, shift #if mantissa1 low exceeds final mantissa space 
result: 
    andi $t8, $t8, 0x000FFFFF #preserve mantissa, zero the rest(cut the prefix - one) 
    move $t0, $t3  #copy propoer sign 
    or $t0, $t0, $t7  #add exponent 
    or $t0, $t0, $t8  #add mantissa part1 
    b output 
result_zero: 
    li $t0, 0 
    li $t1, 0 
output: 
    sw $t0, num1a 
    sw $t1, num1b 
    #print "Result: " 
    la $a0, text3 
    li $v0, 4 
    syscall 
    lwc1 $f12, num1b 
    lwc1 $f13, num1a 
    #print double - the result 
    li $v0, 3 
    syscall 
question: 
    la $a0, quest   #Do you want to enter new numbers or finish? 
    li $v0, 4 
    syscall 
    li $v0, 5    #reads the answer (integer) 
    syscall 
    beq $v0, 1, input   #if input =1, continue, if 0 finish, otherwise ask again 
    beqz $v0, fin 
    b question 
fin: 
    li $v0, 10    #exit 
    syscall 

Я думаю, что проблема может быть в этом разделе (умножить):

addu $t8, $t8, $t0  #adding the high part of mantissa2 to result of low part of mantissa1 
bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high 
#addiu $s1, $s1, 1 
    ###### 
skip_add: 
    bnez $s1, shift 
    bltu $t8, 0x00200000, result 

Процесс добавления может вызвать выполнять. Я попытался обработать его с инструкцией, хранящейся в комментарии (addiu). Это означает, что если результат добавления двух беззнаковых чисел меньше одного из них, мы получим cary out и должны добавить 1 для регистрации $ s1, который содержит наиболее значимые часть мантиссы. Это не помогло.

+0

Этот процесс будет легче, если вы можете предоставить информацию о том, какие ошибки вы испытываете и, если возможно, вы можете детализировать вопрос в какой-то части вашего кода , Учитывая, что, вероятно, очень мало людей, которые знают MIPS-ассемблер и IEEE с плавающей запятой и находятся на SO, чем больше информации вы предоставляете в своем вопросе, тем лучше. – dho

+0

Я отредактировал сообщение. Надеюсь, мои мысли теперь легче понять. – Kornel

+0

К счастью, проблема решена. В размножении действительно была ошибка. Однако проблема заключалась в использовании функции mult. Теперь это правильно и работает. Надеюсь, это поможет кому-то в будущем. – Kornel

ответ

1

На мой взгляд, это правильный код:

.data 
text1: .asciiz "Enter double: " 
text2: .asciiz "Enter integer: " 
text3: .asciiz "Result: " 
quest: .asciiz "\nIf you want to multiply enter 1, otherwise enter 0: " 

num1a: .word  0   #multiplicand and result(sign exponent and first part of mantissa) 
num1b: .word  0   #second part of the multiplicand and result(remaining part of mantissa) 
num2: .word  0   #integer 

    .text 
    .globl input  
input: 
    #print "Enter double: " 
    la $a0, text1 
    li $v0, 4 
    syscall 
    # saving input double into num1 
    li $v0, 7 
    syscall     
    swc1 $f0, num1b 
    swc1 $f1, num1a 
    #print "Enter integer: " 
    la $a0, text2 
    li $v0, 4 
    syscall 
    # saving input int into num2 
    li $v0, 5 
    syscall 
    sw $v0, num2 
    # loading data to registers 
    lw $t0, num1a 
    lw $t1, num1b 
    lw $t2, num2 
#########################################################sign 
sign:  
    move $t3, $t0 
    andi $t3, $t3, 0x80000000 #preserve sign, zero the rest 
    bgez $t2, extract  #if less than zero we change the final sign and negate the value of integer 
    xori $t3, $t3, 0x80000000 #multiply signs (if integer is negative, then the sign is equal to $s0) 
    neg $t2, $t2  #absolute value of int 
extract:  
################################################checking for zero 
    or $t5, $t0, $t1  #if both part of double are equal to zero we skip all the calculation 
    beqz $t5, result_zero 
    beqz $t2, result_zero 
###############################sign, exponent and mantissa 
    move $t7, $t0  
    andi $t7, $t7, 0x7FF00000 #extracting exponent to $t7 
    move $t8, $t0 
    andi $t8, $t8, 0x000FFFFF #extracting first part of mantissa 
    ori  $t8, $t8, 0x00100000 #adding prefix one to mantissa 
    #remaining mantissa stays in register $t1 
######################################################### 
multiply: 
    ########################multiplying mantissa part 1 
    multu $t8, $t2  #multiply mantissa1 by integer 
    mflo $t8   #low part of multiplication to $t8 
    mfhi $s1   #high part of multiplication to $s1 
    ########################multiplying mantissa part 2 
    multu $t1, $t2  #mantissa part 2 multiplication 
    mflo $t1   #low part to $t1 
    mfhi $t0   #with overflow going to $t0 
    ########################partial accumulation 
    addu $t8, $t8, $t0  #adding the high part of mantissa2 to result of low part of mantissa1 
    bgeu $t8, $t0, skip_add #if the result is less than any element we add 1 to mantissa1 high 
    addiu $s1, $s1, 1 
    ###### 
skip_add: 
    bnez $s1, shift 
    bltu $t8, 0x00200000, result  
shift: #else we shift 3 parts of mantissa and increment the the exponent 
    ###extracting least significant bit of high mantissa1 
    sll $s2, $s1, 31  #copying least significant beat of $s1 to most significant bit in $s2 
    sll $t9, $t8, 31  #copying least significant beat of $s8 to most significant bit in $t9 
    ###### 
    srl $s1, $s1, 1  #shifting right mantisa part1 high 
    srl $t8, $t8, 1  #shifting right mantisa part1 low 
    or $t8, $t8, $s2  #copying least significant bit from mantissa1- high to most significant bit of mantissa1 low 
    srl $t1, $t1, 1  #shifting right mantisa part2 
    or $t1, $t1, $t9  #copying least significant bit from mantissa1 to most significant bit of mantissa2 
    ###### 
    addiu $t7, $t7, 0x00100000 #increment exponent by one 
    ###### 
    bnez $s1, shift  #if mantissa1 high is greater than zero we continue 
    bgeu $t8, 0x00200000, shift #if mantissa1 low exceeds final mantissa space 
result: 
    andi $t8, $t8, 0x000FFFFF #preserve mantissa, zero the rest(cut the prefix - one) 
    move $t0, $t3  #copy propoer sign 
    or $t0, $t0, $t7  #add exponent 
    or $t0, $t0, $t8  #add mantissa part1 
    b output 
result_zero: 
    li $t0, 0 
    li $t1, 0 
output: 
    sw $t0, num1a 
    sw $t1, num1b 
    #print "Result: " 
    la $a0, text3 
    li $v0, 4 
    syscall 
    lwc1 $f12, num1b 
    lwc1 $f13, num1a 
    #print double - the result 
    li $v0, 3 
    syscall 
question: 
    la $a0, quest   #Do you want to enter new numbers or finish? 
    li $v0, 4 
    syscall 
    li $v0, 5    #reads the answer (integer) 
    syscall 
    beq $v0, 1, input   #if input =1, continue, if 0 finish, otherwise ask again 
    beqz $v0, fin 
    b question 
fin: 
    li $v0, 10    #exit 
    syscall