我必须在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
答案 0 :(得分:1)
当您在$t1
中计算结果的指数时,您有正确的想法,但尽管1.0 / 1.5f
和1.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(并且不减去)。
在这两种情况下,再次向左移动并计算下一个数字。 等等...