Двойное деление Mips возвращает Infinity

Я свел свою проблему к следующему коду:

.data

newline: .asciiz "\n"

.text
.globl main

main:

li $t0, 4
li $t1, 16          

mtc1 $t0, $f2       # Two integers get stored as floats
mtc1 $t1, $f30

div.d $f12, $f2, $f30

li $v0, 3
syscall         # First division works, returns 0.25

la $a0, newline
li $v0, 4
syscall         # prints new line

div.d $f12, $f12, $f30

li $v0, 3
syscall         # Second division doesn't work as expected, returns Infinity

Выход:

0.25

Infinity

Почему это? Я ожидаю, что 0.25/16 будет ~ 0.015625 вместо Infinity.

Первое значение $f12: 0x3fd0000000000000 Второе значение $f12:0x7ff0000000000000

Я относительно новичок в MIPS, так что это может быть что-то простое. Спасибо за любые ответы!


person Nicola    schedule 12.06.2014    source источник
comment
Похоже, у вас опечатка во втором делении: div.d $f12, $f12, $f30. Вы никогда не показываете инициализацию $f12, я подозреваю, что она содержит ноль.   -  person Durandal    schedule 12.06.2014
comment
Разве он не должен содержать что-то после 'div.d $f12, $f2, $f30'? Или он перезаписывается при вызове для печати?   -  person Nicola    schedule 12.06.2014
comment
Инструкция MTC1 не преобразует целое число в двойное. Вам нужно использовать CVT.D.W после перемещения.   -  person markgz    schedule 12.06.2014
comment
Большое спасибо! Это сработало! Но почему работает первое деление и почему второе деление возвращает бесконечность?   -  person Nicola    schedule 12.06.2014
comment
Я не слишком хорошо знаком с MIPS ABI, но, возможно, некоторые регистры затираются syscall и больше не содержат значений, которые, по вашему мнению, должны...   -  person twalberg    schedule 12.06.2014


Ответы (1)


Очевидный успех первого деления обусловлен артефактом представления небольших положительных целых чисел и положительных субнормальных двойников. Оба имеют начальные нули, а двоичная битовая комбинация соответствует значащим битам значения в младших значащих битах. Результатом обработки целых чисел как удвоения было деление каждого значения на 2 в степени 1074.

Хотя f2 и f30, рассматриваемые как числа с плавающей запятой двойной точности, содержали крошечные значения, около 2,0E-323 и 7,9E-323, их соотношение было таким же, как 4/16. Деление среднего числа, такого как 0,25, на крошечное число приводит к бесконечности.

Вот короткая программа на Java, иллюстрирующая это:

public class Test {
  public static void main(String[] args) {
    long t0 = 4;
    long t1 = 16;
    double f2 = Double.longBitsToDouble(t0);
    double f30 = Double.longBitsToDouble(t1);
    System.out.println("f2=" + f2);
    System.out.println("f30=" + f30);
    double f12 = f2 / f30;
    System.out.println("f12=" + f12);
    System.out.println("f12/f30=" + f12 / f30);
  }
}

выход:

f2=2.0E-323
f30=7.9E-323
f12=0.25
f12/f30=Infinity
person Patricia Shanahan    schedule 12.06.2014
comment
Это отличный ответ! И это отличный пример того, как несколько ошибок могут компенсировать друг друга. - person markgz; 13.06.2014
comment
Спасибо, отличный ответ. - person Nicola; 14.06.2014
comment
Спасибо! очень хороший ответ - person Ahmad; 19.06.2014