2015-04-25 54 views
-2

我必须在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

迭代位是迄今为止这个问题最容易的部分.. – harold

+0

我刚刚发布了一些代码。请给我一些提示如何开始...我很沮丧... – nytmrae55

回答

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进行比较。如果新值大于或等于1yyyyyyy,则下一个数字为1,必须再次减去1yyyyyyy。如果它较低,则下一个数字是0(并且不减)。

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

+0

更好的方式来做有效数除法算法是让他们在寄存器或内存? – nytmrae55