Как из целого числа (QWORD) сделать вещественное число (DOUBLE)

Тема в разделе "WASM.BEGINNERS", создана пользователем assch, 13 фев 2024.

  1. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    Например есть 8-байтная переменная - х

    с помощью команд сопроцессора (FPU) это можно сделать вот так

    Код (ASM):
    1.  
    2. fild qword ptr х   ; Загрузить целое число
    3. fstp qword ptr х   ; Записать и вытолкнуть вещественное число
    4.  
    а как это можно сделать командами блока - XMM

    кто в теме подскажите пожалуйста
     
  2. CaptainObvious

    CaptainObvious Member

    Публикаций:
    1
    Регистрация:
    18 янв 2024
    Сообщения:
    78
    Чат гпт чо говорит?
     
  3. MaKsIm

    MaKsIm Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    68
    Напрямую для 64-битных int команд нету. Для xmm есть int 32-х битный
    Код (Text):
    1. cvtsi2sd xmm0, x
     
  4. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    я знал эту команду cvtsi2sd но она к сожалению не подходит

    перед тем как создать тему
    ради интереса решил посмотреть как это сделает мой - Microsoft Visual Studio 2013

    unsigned __int64 fff;
    double ddd;

    ddd = fff;


    при дизасме выдал вот такой код:

    Код (ASM):
    1.  
    2. mov edx,fff+4
    3. mov ecx,fff
    4. call sub_4024CC
    5. movsd ddd,xmm0
    6.  
    ну и соответственно функцию к ней

    Код (ASM):
    1.  
    2. sub_4024CC proc near
    3. test edx, edx
    4. jnz short loc_4024E5
    5. cvtsi2sd xmm0, ecx
    6. shr ecx, 1Fh
    7. movsd xmm1, ds:qword_403280[ecx*8]
    8. addsd xmm0, xmm1
    9. retn
    10. loc_4024E5:
    11. movd xmm4, ds:dword_4032F8
    12. movd xmm5, ds:dword_4032FC
    13. movd xmm6, ds:dword_4032F4
    14. movd xmm0, ecx
    15. movd xmm1, edx
    16. punpckldq xmm0, xmm1
    17. mov eax, 20h
    18. bsr ecx, edx
    19. sub eax, ecx
    20. movd xmm2, eax
    21. psllq xmm0, xmm2
    22. movdqa xmm3, xmm0
    23. psllq xmm3, 33h
    24. psrlq xmm3, 33h
    25. movdqa xmm1, xmm3
    26. psrlq xmm0, 0Dh
    27. psllq xmm0, 1
    28. pcmpgtd xmm3, xmm4
    29. punpckldq xmm3, xmm3
    30. psubq xmm0, xmm3
    31. pcmpgtd xmm1, xmm5
    32. punpckldq xmm1, xmm1
    33. psubq xmm0, xmm1
    34. psubq xmm6, xmm2
    35. psllq xmm6, 34h
    36. paddq xmm0, xmm6
    37. retn
    38. sub_4024CC endp
    39.  
    протестировав функцию я убедился в том что функция отрабатывает нормально
    но Visual Studio обычно старается делать оптимизированный код
    по этому я был сильно удивлён предложенным вариантом
    ведь код описанный мной выше

    Код (ASM):
    1.  
    2. fild qword ptr fff   ; Загрузить целое число
    3. fstp qword ptr ddd   ; Записать и вытолкнуть вещественное число
    4.  
    не только компактен но и сделает это гораздо быстрее
     
  5. alex_dz

    alex_dz Active Member

    Публикаций:
    0
    Регистрация:
    26 июл 2006
    Сообщения:
    410
    попробуйте другии студии, 2019, 2022
    а также другие компиляторы - gcc, clang
    благо счас все есть онлайн
    например https://godbolt.org/
     
  6. MaKsIm

    MaKsIm Member

    Публикаций:
    0
    Регистрация:
    11 фев 2008
    Сообщения:
    68
    Если в программе использовать одновременно сопроцессор и see, тогда придется переключаться командами finit/emms. А эти команды выполняются гораздо дольше указанной функции.
     
  7. assch

    assch Member

    Публикаций:
    0
    Регистрация:
    17 мар 2011
    Сообщения:
    203
    теперь ради интереса решил посмотреть как это сделает - Dev-Cpp

    unsigned __int64 fff
    ;
    double ddd;

    ddd = fff;

    при дизасме выдал вот такой код:

    Код (ASM):
    1.  
    2. fild ds:fff
    3. fstp [ebp+var_28] ; используется стековый адрес памяти
    4. cmp dword ptr ds:fff+4, 0
    5. jns short loc_4012DA
    6. fld ds:tbb ; глобальная константная лексема - tbb dt 1.8446744073709551616e19
    7. fld [ebp+var_28]
    8. faddp st(1), st
    9. fstp [ebp+var_28]
    10. loc_4012DA:
    11. fld [ebp+var_28]
    12. fstp ds:ddd
    13.  
    после анализа я понял почему Visual Studio или Dev-Cpp так делают
    это по тому что после определённого 8-байтного значения - fff
    код:

    Код (ASM):
    1.  
    2. fild fff ; Загрузить целое число
    3. fstp ddd ; Записать и вытолкнуть вещественное число
    4.  
    на выходе даёт не правильный результат

    Visual Studio и Dev-Cpp проверяют старшиий (dword) 8-байтного значения
    и если он не ноль применяют дополнительный алгоритм

    я конечно могу ошибаться но тестами я выявил что максимальное значение
    при котором дополнительный алгоритм не нужен это значение - 7fffffffffffffffh
    и только начиная со значения - 8000000000000000h
    нужно применить дополнительный алгоритм

    я пересобрал и упростил код выданный - Dev-Cpp

    Код (ASM):
    1.  
    2. .const
    3. tbb dt 1.8446744073709551616e19
    4. .code
    5.  
    6. fild fff
    7. fstp ddd
    8. cmp byte ptr fff+7,80h
    9. jb ??1
    10. fld tbb
    11. fld ddd
    12. faddp st(1),st
    13. fstp ddd
    14. ??1:
    15.  
    вроде бы работает как надо