Проблема с сопроцессором

Тема в разделе "WASM.ASSEMBLER", создана пользователем Max, 25 апр 2005.

  1. Max

    Max Member

    Публикаций:
    0
    Регистрация:
    22 май 2003
    Сообщения:
    192
    Есть прога на делфях, так эта зараза, при некоторых обстоятельствах, начинает стабильно вылетать внутри функции trunc (взятие целого).



    разбор полетов в дизассемблере привел к следующему:



    имеем прогу:
    Код (Text):
    1.  
    2.      cwChop dw 1F32h
    3.      temp   dd ?
    4.      fldcw word ptr [cwChop]
    5.      fldz
    6.      fistp dword ptr [temp]
    7.  


    Эта прога нормально отрабатывает, если на момент вызова fldz регистры фпу следующие:
    Код (Text):
    1.  
    2.      CTRL = 1F72h
    3.      STAT = 4020h
    4.      TAGS = FFFFh
    5.  


    ...и уходит в эксепшн, если регистры следующие:
    Код (Text):
    1.  
    2.      CTRL = 1F72h
    3.      STAT = 81A7h
    4.      TAGS = FFFFh
    5.  


    как можно видеть, эти два состояния отличаются только значением STAT.



    Вопрос, че такого волшебного во втором значении STAT, что вылетает эксепшн?

    Интеловский мануал на команду fldz говорит, что floating-point exception может вылетать только если stack overflow occured, но на момент вызова fldz стек фпу чист для обоих случаев, так что это вроде не тот случай.



    Штуку эту я поборол (переписал trunc :), но вот разобраться охота...

    если хто знает - подскажите.
     
  2. Max

    Max Member

    Публикаций:
    0
    Регистрация:
    22 май 2003
    Сообщения:
    192
    получается вообще какая-то 屁股 - загрузка control word через fldcw приводит к тому, что в status word выставляется флаг FPU Busy, то есть:
    Код (Text):
    1.  
    2.      // CTRL = 127Fh
    3.      // STAT = 0127h
    4.      fldcw word ptr [cwChop]
    5.      // CTRL = 1F72h
    6.      // STAT = 81A7
    7.  


    после чего, любое обращение к фпу (даже fwait) приводит к эксепшену 8-|
     
  3. gloom

    gloom New Member

    Публикаций:
    0
    Регистрация:
    23 июл 2004
    Сообщения:
    11
    Чтобы исключений не было, перед fldcw нужно выполнить fclex.
     
  4. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Max



    Ес-но при размаскировании исключений нужен fclex.

    Младшие 6 бит CW и SW соответствуют исключениям FPU.

    Даже если исключения замаскированы в CW, тем не менее они контролируются и выставляются в SW и сидят там до тех пор пока не будут сброшены явно fclex,finit,fsave\frstor.

    Вот и получается, что ты или не сделал finit или успел нахватать почти полный комплект замаскированных эксепшенов в SW = x7h, а после fldcw они размаскируются и "волшебным образом" проявляются на первой же инструкции после fldcw.



    А то, что "зараза" вылетает на trunc, то это для твоей же пользы :) Значит число слишком большое и не умещается в целое и "зараза" тебя об этом предупреждает - примите уважаемый соответствующие меры :)