Команды сопроцессора

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 18 авг 2018.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    С помощью какой команды (или набором команд) сопроцессора
    можно представить обычное число как число с плавающей точкой
    например просто число - 436 (436)
    программно представить как число с плавающей точкой - 436.0 (1138360320)
    например это можно сделать вот так
    Код (ASM):
    1.  
    2. .data
    3. Real qword 0
    4. .data?
    5. Temp dword ?
    6. .code
    7. mov edx,436
    8. cvtsi2sd xmm0,edx
    9. addsd xmm0,Real[edx*8]
    10. cvtsd2ss xmm0,xmm0
    11. movss Temp,xmm0
    12.  
    в переменной (Temp) будет число - 1138360320 (436.0)
    А можно например тоже самое сделать как нибудь попроще
    Кто в теме подскажите пожалуйста
     
  2. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.954
    fild [nInteger]
    fstp [nFloat]
     
    assch нравится это.
  3. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Большое спасибо f13nd
     
  4. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Ради интереса f13nd что можно сказать по поводу скорости
    Верхний многоходовый алгоритм я обнаружил когда смотрел один дизасемблированный код программы на C++
    Интересно почему компилятор C++ сделал эту многоходовку вместо fild и fstp
     
  5. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    assch,

    IA, V1(basic architecture), C.8: PROGRAMMING WITH THE X87 FPU
     
  6. f13nd

    f13nd Well-Known Member

    Публикаций:
    0
    Регистрация:
    22 июн 2009
    Сообщения:
    1.954
    Это подсистема fpu, у тебя mmx. Почему компилятор что-то там выбрал - понятия не имею. По поводу скорости - если тебе не надо это делать пару миллионов раз в секунду, не забивай голову вообще.
     
    Indy_ нравится это.
  7. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Всем спасибо за участие
     
  8. Mikl___

    Mikl___ Супермодератор Команда форума

    Публикаций:
    14
    Регистрация:
    25 июн 2008
    Сообщения:
    3.708
    assch,
    то же целочисленными командами, на скорую руку, с проверкой знака и нуля :)
    Код (ASM):
    1.    mov eax,-436
    2.    or eax,eax
    3.    jz @f
    4.    cdq ; if eax < 0 then edx := -1 else edx := 0
    5.    xor eax,edx
    6.    sub eax,edx ; eax := |eax|
    7.    and edx,256 ; create sign bit
    8.    bsr ecx,eax
    9.    ror eax,cl
    10.    add eax,edx
    11.    lea eax,[eax+ecx+126]
    12.    rol eax,23;eax=0C3DA0000h=-436.0
    13. @@: . . .
     
    assch нравится это.
  9. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    192
    Спасибо всем за участие
    Если кому интересно то меня интересовал один алгоритм на C++
    Код (C):
    1.  
    2. UINT iTime = timeGetTime() % 1000;
    3. FLOAT fAngle = iTime * ( 2.0f * D3DX_PI ) / 1000.0f;
    4.  
    в этом алгоритме меня заинтересовало как перевести
    получившиеся число (timeGetTime() % 1000) в число с плавающей точкой
    с вашей помощью оказалось что это можно сделать например так:
    Код (ASM):
    1.  
    2. call timeGetTime
    3. xor edx,edx
    4. mov ecx,1000
    5. div ecx
    6. cvtsi2ss xmm0,edx
    7. movd fAngle,xmm0
    8. movss xmm0,r1         ; 2.0
    9. mulss xmm0,r2         ; 3.141592653   -   D3DX_PI
    10. mulss xmm0,fAngle
    11. divss xmm0,r3         ; 1000.0
    12. movss fAngle,xmm0
    13.  
    или так:
    Код (ASM):
    1.  
    2. call timeGetTime
    3. xor edx,edx
    4. mov ecx,1000
    5. div ecx
    6. mov fAngle,edx
    7. fild fAngle
    8. fstp fAngle
    9. movss xmm0,r1          ; 2.0
    10. mulss xmm0,r2          ; 3.141592653   =   D3DX_PI
    11. mulss xmm0,fAngle
    12. divss xmm0,r3          ; 1000.0
    13. movss fAngle,xmm0
    14.  
    ради интереса протестировал оба кода на скорость исполнения
    то есть зациклил код определённое количество раз - (0FFFFFFFh)
    первый код показал результат - 4711 (в милисекундах)
    второй код показал результат - 5226 (в милисекундах)
    оказалось что с (fild и fstp) код работает чуть чуть помедленнее
    но этот алгоритм выстроен чисто в лоб
    то есть строго соблюден порядок исполнения арифметических действий
    если сделать оптимизацию например вместо
    последнего деления - divss xmm0,r3 (1000.0)
    сделать умножение - mulss xmm0,r3 (0.001)
    что как выясняется для данного случая даёт один и тот же результат
    Код (ASM):
    1.  
    2. call timeGetTime
    3. xor edx,edx
    4. mov ecx,1000
    5. div ecx
    6. cvtsi2ss xmm0,edx
    7. movd fAngle,xmm0
    8. movss xmm0,r1         ; 2.0
    9. mulss xmm0,r2         ; 3.141592653   -   D3DX_PI
    10. mulss xmm0,fAngle
    11. mulss xmm0,r3         ; 0.001
    12. movss fAngle,xmm0
    13.  
    при тестировании на скорость исполнения
    этот код показал результат - 4056 (в милисекундах)
    не исключаю что можно и ещё по оптимизировать
    но впадать в Перфекционизм это уже каждый решает сам
    в зависимости от поставленной задачи
     
    Indy_ нравится это.
  10. Indy_

    Indy_ Well-Known Member

    Публикаций:
    4
    Регистрация:
    29 апр 2011
    Сообщения:
    4.775
    assch,

    Вы использовали правильный механизм тестов на профайл - использовали таймер низким разрешением и не линейный, но погрешность убрали длительным циклом, тогда само поведение таймера не имеет смысла.

    Это чисто рациональный подход, лайкну даже. Но вот дальше следует не рациональное. Точнее нужно понимать как это устроено, иначе не решить. Блок математики, это любые компонетны NPX(fpu, sse etc) обрабатываются особым образом ядром. При первой встрече этих блоков(срабатывает ловушка) запускается выгрузка полного контекста задачи, на все эти блоки контекст один. Из за размера блока и проверок безопасности это очень тяжёлая по таймингу операция и профайл резко просядет. Но после первого обращения отменить выгрузку невозможно, в течении нескольких квантов контекст будет выгружаться полный. Полный конкретно значит fxsave. Иначе эти блоки ядро не использует.

    Это значит что тот же алгоритм реализованный базовым набором(GRP), будет иметь на порядки более высокий тайминг. NPX блоки не следует трогать, если нет задачи по вычислению плавающей математики(синусы етц).