在没有FPU的MIPS组件中,将双精度除以单精度(均为IEEE 754)

时间:2015-04-25 13:32:45

标签: assembly mips ieee-754 fpu

我必须在MIPS程序集中创建一个程序,它将双精度浮点数除以单精度数(使用标准IEEE 754)而不使用浮点指针单元。我唯一能理解的是如何处理两个数字的尾数来计算除法。如何迭代各个位?

.data

res:    .asciiz "Result is: "
neg_res:.asciiz "Result is: - "
choice: .asciiz "\nMake your choice:\n1. Execute\n2. Exit\n"
wrong:  .asciiz "Inserted value is wrong! Please try one more time."
first:  .asciiz "Insert the first number: "
n:      .asciiz "\n"
second: .asciiz "Insert the second number: "
divz:   .asciiz "Can't divide for 0! Please try one more time." 

.text

main:
    la  $a0, choice
    li  $v0, 4
    syscall                  # Print menu

    li  $v0, 5
    syscall                  # Input choice

    move    $t7, $v0       
    beq     $t7, 2, end      # Control=2
    blt     $t7, 1, err      # Control<1
    bgt     $t7, 2, err      # Control>2

getdoub:
    la  $a0, first
    li  $v0, 4
    syscall             # Message for input numerator

    li  $v0, 7
    syscall
    mov.d   $f4, $f0        # Input double numerator

    c.eq.d  $f4, $f30
    bc1t    print_dou       # Print result if numerator is = 0

getfloat:
    la  $a0, second
    li  $v0, 4
    syscall             # Message for input denominator

    li  $v0, 6
    syscall
    mov.s   $f6, $f0        # Input float denominator

    c.eq.s  $f6, $f30
    bc1t    errz            # Print error if denominator is = 0

    sign_d:
    cvt.d.s $f6, $f6        # Convert from single to double to avoid errors in compare

    c.lt.d  $f4, $f6          # Control sign of double
    bc1t    minus_d         # If c1 is true (that means $f4<$f8) jump to minus_d
    b   plus_d              # Otherwise plus_d

minus_d:
    li  $t0, 1          # Negative sign

plus_d:
    li  $t0, 0          # Positive sign

extr_double:
    mfc1.d  $t2, $f4         # Iin $t2 I've sign, exponent and 20 bit of mantissa    in t3, 32 bit of mantissa
    li  $t6, 2146435072 # Mask for 11 bit of exponent
    and     $t1, $t2, $t6     # In $t1 Exponent
    li  $t6, 1048575    # Mask for 20 bit of mantissa
    and     $t2, $t2,$t6
    add     $t2, $t2, 2097152 # In t2 I've mantissa 1 and in t3 ho la mantissa 2 automatically


sign_s:
    cvt.s.d $f8, $f8        # Convert $f8 from double to single
    c.lt.s  $f6, $f8        # Same control made for numerator
    bc1t    minus_s
    b   plus_s

minus_s:
    li  $t4, 1
    b   extr_sing

plus_s:
    li $t4,0         # t4 sign

extr_sing:
    mfc1    $t6, $f6
    li  $t7, 2139095040 # 8 bit of exponent a 1 
    and     $t5, $t6, $t7       # In $t5 I've exponent

    li  $t7, 8388607    # Mask for 23 bit
    and     $t6, $t6, $t7
    add     $t6, $t6, 16777216  # In $t6 I've mantissa

sign:   # Sign of result
    xor     $t0, $t0, $t4     
    beqz    $t0, print_res
    b   p_neg_res

exp:
    sub     $t5, $t5, 1023   # Taking real exponent
    sub     $t1, $t1, 127    # Taking real exponent
    sub     $t1, $t1, $t5     # In $t1 I've the exponent of the final number
    add     $t1, $t1, 1023   # Adding bias (the final number will be a double)
    sll     $t1, $t1, 20      # Shifting so when I add $t2 (the first part of mantissa) I    have the number in the right position

divis:
    div     $t3, $t3, $t6     # First part of division (32 bit of mantissa) 
    div     $t2, $t2, $t6     # Second part of division (20 bit of mantissa)

        #HUGE QUESTION MARK
    add $t2, $t1, $t2       # Adding exponent and mantissa, in this way in $t2 I have all the information
    mtc1.d $t2, $f4         # $t2 & $t3 are moved in $f4 & $f5 so I have a double number   in $f4...I Hope
    b print_dou

print_res:  # Print positive result
    la  $a0, res
    li  $v0, 4
    syscall
    b   divis

p_neg_res:  # Print negative result
    la  $a0, neg_res
    li  $v0, 4
    syscall
    b   divis

err:    # Error in the choice
    la  $a0, wrong
    li  $v0, 4
    syscall
    b   main

end:    # End of program
   li   $v0, 10
   syscall

errz:   # Error dividing by 0
    la  $a0, divz
    li  $v0, 4
    syscall
    b   main

print_dou:  # Print the number!!
    mov.d   $f12, $f30 # bylo #f4
    li  $v0, 3
    syscall
    b   main

1 个答案:

答案 0 :(得分:1)

当您在$t1中计算结果的指数时,您有正确的想法,但尽管1.0 / 1.5f1.5 / 1.0f的相应操作数相同,但结果的指数不同一个人。在第一种情况下,你可以做的是在递减$t1的同时将分子的有效数除以1。

在提取了两个有效数之后,您需要设置相应的隐式有效位数(显然,在第一段中建议的调整之前设置先前隐式位,否则会很复杂)。

之后你将实施一个部门。以下说明实现53位除法:

div     $t3, $t3, $t6     # First part of division (32 bit of mantissa) 
div     $t2, $t2, $t6     # Second part of division (20 bit of mantissa)

首先,他们忘记了隐含的位,其次,这不是它的工作方式。

您从1xxxxxxxxx(52或53位)xxxxxxxxxxx和1yyyyy(23位)yyyyy开始。在第一段中,您确保分子的有效位数大于分母的值,因此第一个数字计算为1(它将隐式存储在最终结果中)。接下来你需要从前者中减去后者。如果您未在步骤1中移位,则减法如下所示:

 1xxxxxxxxxxx
-1yyyyyyy
_____________
 zzzzzzzzzzzz

如果你在第1步中转移,它看起来像这样:

 1xxxxxxxxxxx
- 1yyyyyyy
_____________
 zzzzzzzzzzzz

将结果左移一,并将新值与1yyyyyyyy进行比较。如果新值大于或等于1yyyyyyyy,则下一个数字为1,必须再次减去1yyyyyyy。如果它更低,则下一个数字为0(并且不减去)。

在这两种情况下,再次向左移动并计算下一个数字。 等等...