FCOM, FPREM - странное поведение

Тема в разделе "WASM.BEGINNERS", создана пользователем la_mer, 23 ноя 2008.

  1. la_mer

    la_mer New Member

    Публикаций:
    0
    Регистрация:
    21 ноя 2008
    Сообщения:
    2
    Код (Text):
    1. ...
    2.  
    3. @@oc_inc:
    4.     fadd    st(0), st(2)   
    5.     fcom           
    6.     fstsw   ax
    7.     sahf
    8.     jz  @@oc_loop  
    9.     jc  @@oc_loop
    10.     jmp @@oc_ret
    11.  
    12. ...
    вывожу на печать в цикле значения от 0.1 до 1.0 включительно с шагом 0.1
    на последней итерации к 0.9 прибавляется 0.1 и все это сравнивается с 1.0 - здесь проверка не срабатывает и цикл проваливается в @@oc_ret
    почему так?

    еще такой вопрос:
    иногда при загруженных в стек например 7.0 и 1.0 после fprem остается не ноль, а непонятное значение ~3.8e-19
    например такой глюк наблюдается с процедуркой outfloat взятой отсюда
    с чем это связано?

    PS: тестировал код под TASM 4.1 и MASM 6.1
     
  2. Y_Mur

    Y_Mur Active Member

    Публикаций:
    0
    Регистрация:
    6 сен 2006
    Сообщения:
    2.494
    0.1 в двоичной системе бесконечная дробь, из-за этого ошибка округления и результат твоего суммирования чуть больше чем 1.0 поэтому и флаги z и с не установлены. ~3.8e-19 это тоже ошибка округления. При работе с fpu следует избегать сравнений на точное равенство, заменяя его на сравнение с больше меньше или на попадание в диапазон ошибки. Еще в слове состояния fpu sw есть бит-флаг указывающий на то что при вычислениях произошла потеря точности, хотя как правило он бесполезен как раз из-за этих потерь точности на простейших числах.
    Кстати конструкция fcom + fstsw ax + sahf морально устаревшая и медленная, на современных камешках лучше использовать fcomi которая сразу действует на cpu флаги.
     
  3. la_mer

    la_mer New Member

    Публикаций:
    0
    Регистрация:
    21 ноя 2008
    Сообщения:
    2
    Y_Mur, спасибо
    добавил в код дополнительную проверку на ошибку округления