Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [masm32] Сравнение вещественных чисел, не сравнивает 
V
    Опции темы
race1
Дата 27.11.2008, 15:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.6.2004

Репутация: нет
Всего: нет



Разобрался с одной проблемой, появилась вторая smile

Мне надо сравнивать не целые числа, для этого использую сопроцессор (и вообще его использую потому что много "не целых" вычислений). Пробовал двумя способами:
  • FpuComp. Подглядел в справке пример, делаю так:

    Код

    FpuTmp1 DOUBLE ?
    FpuTmp2 DOUBLE ?
    ...
          fld HALF
          fld DUDE_RADIUS
          fadd
          fst FpuTmp1

          fld FDude2X
          fld DUDE_STEP
          fsub
          fst FpuTmp2
          
          invoke FpuComp, addr FpuTmp1, addr FpuTmp2, SRC1_REAL or SRC2_REAL
          test eax, CMP_GREATER
          
          jnz _MAX2_GREATER
          jmp _MAX2_LOWER
        _MAX2_GREATER:
    ...
          jmp _MAX2_END

        _MAX2_LOWER:
    ...
          jmp _MAX2_END

        _MAX2_END:
    ...


    Этот вариант не работает как надо, eax никогда не содержит CMP_GREATER.

    Пробовал по-разному, записывал оба числа в стэк сопроцессора и указывал SRC1_FPU or SRC2_FPU - ничего не меняется. Полистал справку, посмотрел что сопроцессору нужны 80-ти битные переменные, сделал FpuTmp1/2 REAL10, даже не компилится и падает на fst FpuTmp1.
  • Пробовал как в старом турбо-ассемблере, использовать fstsw, так не компилируется даже именно на fstsw. Т.е. задумка такая - сравнить числа в сопроцессоре fcom, загрузить регистр флагов сопроцессора в регистр флагов процессора и уже исходя из этих данных делать jb/jae

Скажите пожалуйста, как сравнить два вещественных числа? smile
PM MAIL ICQ   Вверх
Mikl_
Дата 28.11.2008, 05:06 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 537
Регистрация: 9.11.2007

Репутация: 8
Всего: 14



race1Команды сравнения
Операция сравнения чисел FPU отличается от целочисленной операции сравнения. Это отличие в большем количестве ситуаций, и возможных результатов сравнения двух чисел. Числа могут быть:
1.Сравнимы. 
2.Несравнимы. 
3.Логически сравнимы. 
В первой группе сравниваемые числа могут быть больше, меньше, равны и т.д.
Во второй группе операнды не сравнимы. На пример, пытаются сравнить число и не число, число и денормализованное число и т.д.
В третью группу входят ситуации второй группы, но логически переосмысленные. Например, сравнивая число с денормализованным числом,  представляют его как сравнение с нулём, или как сравнение числа и бесконечности.
Как видите третья группа – условна и зависит от постановки задачи, от её особенностей, и того, что имеет смысл, а что нет.
Всё это вызывает достаточно значительные проблемы. Если вы устанавливайте исключения на все случаи, то есть исключаете ситуацию появления «ненормализованных» чисел – тогда ваш код можно будет реализовывать как обычно, не обращая внимания на ситуации с образованием ненормализованных результатов. Иначе, потребуется дополнительный анализ после сравнения. При этом заметьте, что в вашей задаче может иметь смысл денормализованный операнд, но не имеет смысла бесконечность, или наоборот.
Команды FCOM (FCOMP, FCOMPP, FICOM, FICOMP)
(сравнение вещественных чисел = ”COMPARE Floating point values”)
Синтаксис команды:    FCOM <SRC>
Семантика команды: Команда сравнения вещественных чисел 
Возможные варианты команды:
fcom    mem
fcom    st(i)
fcomp   mem
fcomp   st(i)
fcompp  mem
fcompp  st(i)
ficom   mem
ficom   st(i)
ficomp  mem
ficomp  st(i)
Псевдокод команды: 
CASE (relation of operands) OF
ST(0)>SRC:         C3,C2,C0←000
ST(0)<SRC:         C3,C2,C0←001
ST(0)=SRC:         C3,C2,C0←100
Unordered:        C3,C2,C0←111
В команде FCOM SRC всегда участвует вершина стека ST(0) и явно указанный регистр или операнд в памяти SRC. Команда FCOM SRC  выполняет сравнение ST(0) с операндом SRC, и устанавливает или сбрасывает биты состояния C3 и C0 (таблица 4). При этом указатель стека TOP не модифицируется, если это не команда FCOMP. Особой командой сравнения является FCOMPP,которая не имеет операндов. Она всегда сравнивает два верхних элемента стека ST(0) и ST(1), после сравнения они оба исчезают из стека. Команды FICOM/FICOMP сравнивают содержимое регистра ST(0) и 16- или 32-битная переменной SRC, считается что в SRC содержится целое число. В остальном команды FICOM/FICOMP эквивалентны командам FCOM/FCOMP.
Флаги состояния C3, C2 и C0 в FPU расположены на тех же местах что и флаги нуля (ZF), паритета (PF) и переноса (CF) регистра  EFLAGS.
регистр состояния SWR | B | C3 | TOP |C2| C1| C0
регистр  EFLAGS              |SF|ZF  |  - AF -|PF|   -- |CF
биты                                    | 7 |  6   |  5|4|3|  2 |  1  | 0
Для опроса флагов состояния, программа считывает содержимое SWR и записывает его в память командой FSTSW (FNSTSW), которая сохраняет содержимое регистра SWR в 16-битной переменной, или регистре AX. При помощи команды SAHF содержимое флагов C3 и C0 заносится в регистр флагов микропроцессора, правда при этом флаг C1  попадает на неиспользуемый в EFLAGS 1-бит и его значение теряется. Вместо SAHF можно также использовать команду POPF.  
C0/CF | C3/ZF | C2/PF |Значение
      0    |  0  |  0  |ST(0) > SRC
      1    |  0  |  0  |ST(0) < SRC
       0   |   1  |  0  |ST = SRC
       1    |   1  |  1  |ST(0) и SRC не могут быть сравнены
Таблица 4:результат выполнения FCOM SRC 
Операция  опкод  Действие
FICOM m16int  DE/2  Сравнить ST(0) c m16int
FICOM m32int  DA/2  Сравнить ST(0) c m32int
FICOMP m16int DE/3 Сравнить ST(0) c m16int, вытолкнуть из стека
FICOMP m32int DA/3 Сравнить ST(0) c m32int, вытолкнуть из стека
Команда FUCOM (FUCOMP, FUCOMPP)
(сравнение вещественных чисел без учета порядка = ”Unordered COMPARE Floating point values”)
Синтаксис команды:        FUCOM<DEST>, <SRC>
Алгоритм работы: сравнения вещественных чисел без учета порядка 
Возможные варианты команды:
fucom   st(0),st(i)
fucomp  st(0),st(i)
fucompp st(0),st(i)
Псевдокод команды: 
CASE (relation of operands) OF
ST(0)>SRC:         C3,C2,C0←000
ST(0)<SRC:         C3,C2,C0←001
ST(0)=SRC:         C3,C2,C0←100
ENDCASE
IF ST(0) or SRC=QNaN, but not SnaN or unsupported format
THEN C3,C2,C0←111
ELSE;ST(0) or SRC=SnaN or unsupported format
    #IA
    IF FPUControlWord.IM=1
    THEN C3,C2,C0←111
    ENDIF
ENDIF
Команды FCOMI, FCOMIP, FUCOMI, FCOMIP появились в процессорах P6 и позволяют напрямую заносить результаты сравнения в регистр EFLAGS, не используя команды  FSTSW AX/SAHF
Операция   опкод  Действие
FCOMI ST(0),ST(i) DBF0+i  Сравнить ST(0) и ST(i), установить EFLAGS
FCOMIP ST(0),ST(i) DFF0+i Сравнить ST(0) и ST(i), установить EFLAGS, извлечь из стека
FUCOMI ST(0),ST(i) DBE8+i Сравнить без учета порядков значения в ST(0) и ST(i), установить EFLAGS
FUCOMIP ST(0),ST(i) DFE8+i Сравнить без учета порядков значения в ST(0) и ST(i), установить EFLAGS, извлечь из стека

CF |ZF| PF| Значение
  0  | 0 | 0  | ST(0) > SRC
 1  | 0 | 0 |ST(0) < SRC
 0  | 1 | 0 |ST = SRC
 1 | 1 | 1 |ST(0) и SRC не могут быть сравнены
Таблица 5: результат выполнения FUCOM SRC
Операция | опкод |Действие                                                              |Результат
FCOM st(i) | D8Di   |Сравнение вещественного значения,         |
         m32fp| D8/2   |находящегося в ST(0) с оператором,          |Флаги FPU
         m64fp  DC/2  |находящемся в памяти или ST(i)                 |
FCOMP st(i)|  D8D8+i |Сравнение вещественного значения,  |
          m32fp| D8/3       |находящегося в ST(0) с оператором, 
            m64fp DC/3    |находящемся в памяти или ST(i) с 
выталкиванием вещественного значения с вершины стека
FCOMPP DED9 Сравнивает вещественное значение, 
находящееся в ST(0) и ST(1) с оператором, находящемся в памяти 
или в ST(i) с выталкиванием вещественного значения из ST(0) и ST(1)
______________________________________________________________________
FCOMI DBF0+i Сравнение вещественного значения, находящегося |
                            в ST(0) с оператором  ST(i)                                                 |Флаги CPU
FCOMIP DFF0+i Сравнение вещественного значения, находящегося 
                                в ST(0) с оператором ST(i) с выталкиванием 
                                 вещественного значения с вершины стека
FUCOMI DBE8+i Неупорядоченно сравнивает вещественное значение, 
                                 находящееся в ST(0) с оператором ST(i)
FUCOMIP DFE8+i Неупорядоченно сравнивает вещественное значение, 
                                    находящееся в ST(0) с оператором ST(i) с выталкиванием 
                                    вещественного значения с вершины стека

Кроме команд сравнения также доступны команды анализа FTST и FXAM.
 Команда FTST
(сравнение вещественных чисел без учета порядка = ”TEST Floating point values”)
Синтаксис команды:        FTST
Алгоритм работы: Команда FTST сравнивает содержимое  вершины стека ST(0) с нулём, и устанавливает коды условий 
C0/CF C3/ZF C2/PF Значение
   0           0             0   ST(0) > 0
   1           0             0   ST(0) < 0
   0           1             0   ST (0)= 0
   1           1             1   ST(0) и 0 не могут быть сравнены
Таблица 6: результат выполнения FTST
Команда FXAM
(проверка числа на вершине стека = ”Floating point EXAMINE”)
Синтаксис команды:        FXAM
Алгоритм работы:  проверка числа на вершине стека
Команда FXAM устанавливает флаги регистра состояния от C0 до C3, показывая какое число находится на вершине стека. 
C3/ZF     C2/PF       C1        C0/CF    Значение
    0            0               0           0            + ненормализованное
    0            0               0            1           + NAN (не число)
     0           0               1            0           - ненормализованное
      0          0               1            1           - NAN
       0         1               0            0             + нормализованное
       0         1               0            1           + ∞
       0         1               1           0            - нормализованное
        0        1               1           1           - ∞
        1        0               0           0            + 0
        1        0                0          1            Пусто
        1        0                1          0            - 0
        1         0              1           1            Пусто
         1        1              0           0            + денормализованное
         1        1             0             1            пусто 
         1        1             1             0            - денормализованное
         1        1             1             1             пусто 
Если очень внимательно рассмотреть таблицу результата выполнения команды FXAM, то можно заметить, что C1 отвечает за знак (C1=0 знак положительный, C1=1 знак отрицательный). Если число конечное (ноль, ненормализованное число, нормализованное число, денормализованное число) С0 = 0, если число неконечное (нечисло, бесконечность, пусто) С0 = 1
C1=0                                                 C1=1                     C3/ZF     C2/PF C0/CF
+ненормализованное  -ненормализованное           0             0            0
+нормализованное       -нормализованное               0              1           0
+0                                        -0                                                1             0           0
+денормализованное    -денормализованное         1             1           0
+NAN (нечисло)                -NAN (нечисло)                     0             0           1
+∞                               -∞                                0             1            1
Пусто                                    Пусто                                       1              0             1
Пусто                                    Пусто                                       1              1            1

Надеюсь, я ответил на твой вопрос? smile 
PM MAIL   Вверх
race1
Дата 28.11.2008, 07:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 68
Регистрация: 18.6.2004

Репутация: нет
Всего: нет



Цитата(Mikl_ @  28.11.2008,  10:06 Найти цитируемый пост)
Надеюсь, я ответил на твой вопрос?


Ммм... Да, спасибо! smile Разобрался, оказывается на моей стороне были ошибки... Ну и статья помогла smile

PM MAIL ICQ   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Asm для начинающих"
MAKCim
  • Проставьте несколько ключевых слов темы, чтобы её можно было легче найти.
  • Не забывайте пользоваться кнопкой КОД.
  • Телепатов на форуме нет! Задавайте чёткий, конкретный и полный вопрос. Указывайте полностью ошибки компилятора и компоновщика.
  • Новое сообщение должно иметь прямое отношение к разделу форума. Флуд, флейм, оффтопик запрещены.
  • Категорически запрещается обсуждение вареза, "кряков", взлома программ и т.д.

Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, MAKCim.

 
 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Asm для начинающих | Следующая тема »


 




[ Время генерации скрипта: 0.0739 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.