Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.73/15: Рейтинг темы: голосов - 15, средняя оценка - 4.73
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502

__asm вставка на x64

16.01.2023, 21:52. Показов 3557. Ответов 14
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Привет всем.
Использовал такую функцию, которую мне подсказал очень хороший человек на этом форуме,
для перевода long double в double.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
double to64(unsigned char *x)
{
    unsigned char c[10] = { 0 };
    ::memcpy(c, x, 10);
 
    double d = 0;
 
    __asm
    {
        fld   TBYTE PTR c
        fstp  d
    }
 
    return d;
}
Но сейчас возникла необходимость использовать ее в x64 проекте, а там, как известно асм вставки не поддерживаются.
Прочитал, что можно подключить .asm файл к проекту и использовать его.
Сделал как тут написано https://learn.microsoft.com/ru... w=msvc-160
Но проблема, что функцию как я понял, надо переписать на чистом asm. А я в этом не силен. Помогите, кто умеет, буду очень признателен.
0
Лучшие ответы (1)
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
16.01.2023, 21:52
Ответы с готовыми решениями:

asm вставка в C++
#include <iostream> int a = 10; void func( int& aIn ) { __asm { mov aIn, 15 } }

Вставка asm в С++
Здравствуйте! Помогите пожалуйста! Задание: Вычислить арифметическое выражение. Требуется написать функцию на языке C++ с вставкой на...

asm вставка в C++
есть код #include "stdafx.h" #include <iostream> #include <fstream> using namespace std; slozh(int* pi1, int...

14
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,859
16.01.2023, 22:19
а чем
C++
1
2
 long double a=0.1;
 cout<<(double)(a);
не устроила, я что-то пропустил?

Добавлено через 3 минуты
в x64 проекте, а там, как известно асм вставки не поддерживаются
о как, мне, например не известно, писал даже не зная об этом
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
16.01.2023, 22:22
Цитата Сообщение от abit Посмотреть сообщение
я что-то пропустил?
В Visual Studio long double совпадает по представлению с double. Поэтому ваш пример фактически ничего не делает.

Задача состоит в том, что вам дано бинарное представление 80-битного плавающего значения, т.е. "настоящее" long double

C
1
unsigned char c[] = { 0xba, 0x4b, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0xfc, 0x3f };
Нужно преобразовать его в 64-битное плавающее значение (ака double).
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
16.01.2023, 22:23  [ТС]
Цитата Сообщение от abit Посмотреть сообщение
о как, мне, например не известно, писал даже не зная об этом
В смысле?
long double не поддерживается Visual Studio. Я считываю 10 байт из файла и перевожу их в double.
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,859
16.01.2023, 22:39
Я понял, это какая-то местная причуда visual studio, к сожалению не работаю с виндой, но суть задачи понял, в gcc и clang вопросов нет воткнуть ассемблер в x64

Добавлено через 12 минут
а там что, только мантиссу достаточно отрезать?
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
16.01.2023, 22:42
Лучший ответ Сообщение было отмечено zombivadim как решение

Решение

Цитата Сообщение от zombivadim Посмотреть сообщение
надо переписать на чистом asm.
Это можно сделать и без ассемблера (см. например https://stackoverflow.com/ques... it-in-msvc)

Но в ассемблере будет, конечно, намного компактнее и эффективнее.

Что-то в этом роде

Файл .asm

Assembler
1
2
3
4
5
6
7
8
9
10
11
12
public convert10to8
 
.code
 
convert10to8 proc
  fld TBYTE PTR [rcx]
  fst QWORD PTR [rsp - 8]
  movsd xmm0, mmword ptr [rsp - 8]  
  ret
convert10to8 endp
 
end
В C коде

C
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
 
double convert10to8(const unsigned char *ld);
 
int main(void)
{
  unsigned char c[] = { 0xba, 0x4b, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0xfc, 0x3f };
  double d = convert10to8(c);
  printf("%lf\n", d);
}
В С++ коде

C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
 
extern "C" double convert10to8(const unsigned char *ld);
 
int main(void)
{
  unsigned char c[] = { 0xba, 0x4b, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0xfc, 0x3f };
  double d = convert10to8(c);
  std::cout << d << std::endl;
}
2
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,859
16.01.2023, 22:46
если только мантиссу отрезать, то вроде просто
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <iostream>
 
unsigned char c[] = { 0xba, 0x4b, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0xfc, 0x3f };
 
double to64(unsigned char *x)
{
    double d(*(double*)x);
    return d;
}
 
using namespace std;
 
int main()
{
    cout<<to64(c);
 
    return 0;
}
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
16.01.2023, 23:06
Цитата Сообщение от abit Посмотреть сообщение
если только мантиссу отрезать,
Откуда взялось странное предположение, что нужно только "мантиссу отрезать"? Описание представления плавающих форматов свободно доступно в инете. И нет, там не только "мантиссу отрезать". Это не говоря уже о том, что ваш код "отрезает" не с той стороны.

Готовые примеры для тестирования я приводил вот в этой теме: Представление чисел с плавающей запятой в hex редакторе

Code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
{ 0xba, 0x4b, 0x55, 0x55, 0x55, 0x55, 0x55, 0xd5, 0xfc, 0x3f }
0.20833333333333330000315154750811785788755514658987522125244140625
 
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x3f }
0.5
 
{ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xd0, 0xc0, 0x0c, 0x40 }
12340.0
 
{ 0x00, 0x98, 0x77, 0x9c, 0xa2, 0x23, 0xb9, 0xfc, 0xfb, 0x3f }
0.12339999999999999580335696691690827719867229461669921875
 
{ 0x00, 0x58, 0x82, 0xc5, 0xe1, 0xcc, 0xaf, 0xe6, 0xf1, 0x3f }
0.000110000000000000003916138247017642015634919516742229461669921875
 
{ 0x00, 0x68, 0x00, 0x6f, 0x01, 0x80, 0xa2, 0x96, 0x13, 0x40 }
1234000.00069999997504055500030517578125
 
{ 0x00, 0x38, 0xd6, 0xc5, 0x6d, 0x34, 0x80, 0xb7, 0xf4, 0xbf }
-0.000699999999999999992887633748495090912911109626293182373046875
Десятичное представление выше дано для исходной 80-битной точности. В представлении double должны получиться примерно такие же значения.
0
 Аватар для abit
870 / 529 / 149
Регистрация: 03.02.2013
Сообщений: 1,859
16.01.2023, 23:16
TheCalligrapher,
ну я просто спросил, если нет, то могу предложить разобрать и собрать назад по тем правилам, что вы написали:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <cstring>
 
unsigned char c[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0xfe, 0x3f };
 
double to64(const unsigned char x[10])
{
    int e = (((x[9] << 8) | x[8]) & 0x7FFF);
    uint64_t m =
        ((uint64_t)x[7] << 56) | ((uint64_t)x[6] << 48) | ((uint64_t)x[5] << 40) | ((uint64_t)x[4] << 32) | 
        ((uint64_t)x[3] << 24) | ((uint64_t)x[2] << 16) | ((uint64_t)x[1] << 8) | (uint64_t)x[0];
    unsigned char d[8] = {0};
    double result;
 
    d[7] = x[9] & 0x80;
 
    if ((e == 0x7FFF) || (e == 0))
    {
        if (e == 0x7FFF)
        {
            d[7] |= 0x7F;
            d[6] = 0xF0;
        }
        else
        {
            memcpy(&result, d, 8);
            return result;
        }
    }
    else
    {
        e = e - 0x3FFF + 0x03FF;
 
        if (e <= -52) 
        {
            memcpy(&result, d, 8);
            return result;
        }
        else if (e >= 0x7FF)
        {
            d[7] |= 0x7F;
            d[6] = 0xF0;
            memset(d, 0x00, 6);
            memcpy(&result, d, 8);
            return result;
        }
        else
        {
            d[7] |= (e & 0x7F0) >> 4;
            d[6] |= (e & 0xF) << 4;
        }
    }
 
    m >>= 11;
 
    if (e < 0) m>>=(-e + 1);
 
    d[0] = m & 0xFF;
    d[1] = (m >> 8) & 0xFF;
    d[2] = (m >> 16) & 0xFF;
    d[3] = (m >> 24) & 0xFF;
    d[4] = (m >> 32) & 0xFF;
    d[5] = (m >> 40) & 0xFF;
    d[6] |= (m >> 48) & 0x0F;
    memcpy(&result, d, 8);
 
    return result;
}
 
int main(void)
{
   std::cout<<to64(c);
}
но порядочный компилятор должен предоставлять cast или преобразование типов из коробки
0
12 / 11 / 2
Регистрация: 03.04.2016
Сообщений: 502
17.01.2023, 13:02  [ТС]
abit,
Работает. Хорошее решение.
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
17.01.2023, 13:09
Цитата Сообщение от abit Посмотреть сообщение
но порядочный компилятор должен предоставлять cast или преобразование типов из коробк
Как-то я тоже был всегда в том уверен.
Это не так?!
0
 Аватар для SmallEvil
4086 / 2975 / 813
Регистрация: 29.06.2020
Сообщений: 11,000
17.01.2023, 15:15
Цитата Сообщение от abit Посмотреть сообщение
но порядочный компилятор должен предоставлять cast или преобразование типов из коробки
Цитата Сообщение от KSergey9 Посмотреть сообщение
Как-то я тоже был всегда в том уверен.
Как вы себе это представляете ?
Компилятор обязан "заморачиваться" на всевозможные (вновь и вновь добавляемые) типы ?
И программист также будет все эти причуды "замороченного" компилятора разбирать/помнить ?
Мне правда интересно.
Наверное я просто далек от этой темы...
0
631 / 526 / 104
Регистрация: 05.08.2022
Сообщений: 2,810
17.01.2023, 15:26
Цитата Сообщение от SmallEvil Посмотреть сообщение
Компилятор обязан "заморачиваться" на всевозможные (вновь и вновь добавляемые) типы ?
Компилятор в любом случае "заморачивается" на все поддерживаемые им типы.
Возможно я не очень в курсе про этот long double и он просто не поддержан компилятором? (я по сообщению темы подумал, что поддерживает).
Если компилятор как таковой не поддерживает этот тип для использования, тогда, конечно, понятно, что в нём нет встроенной конвертации.
0
19500 / 10105 / 2461
Регистрация: 30.01.2014
Сообщений: 17,816
17.01.2023, 16:53
KSergey9, в visual studio тип long double идентичен типу double (это 64-битный тип). Этот факт не нарушает стандарт, насколько я знаю. Однако если откуда-то извне пришло представление 80-битного "настоящего" long double, то возникает потребность в преобразовании.
И поскольку для компилятора VS типы long double и double идентичны по представлению, то полагаться на какое-то "стандартное" преобразование нельзя.
0
Вездепух
Эксперт CЭксперт С++
 Аватар для TheCalligrapher
12942 / 6809 / 1821
Регистрация: 18.10.2014
Сообщений: 17,234
17.01.2023, 19:44
Цитата Сообщение от KSergey9 Посмотреть сообщение
Возможно я не очень в курсе про этот long double и он просто не поддержан компилятором? (я по сообщению темы подумал, что поддерживает).
??? Выше все уже объяснялось.

Язык С++ не оговаривает конкретного физического представления типов. У одного компилятора тип long double может представляться одним способом. У другого компилятора тип long double может представляться совсем другим способом. Задача состоит в том, чтобы преобразовать внутреннее представление long double одного компилятора во внутреннее представление long double другого компилятора.

В рамках данной задачи не имеет никакого значения, "поддерживает" ли компилятор long double или нет. Слово "поддерживает" в этом контексте ничего не значит и никак не помогает.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
17.01.2023, 19:44
Помогаю со студенческими работами здесь

asm вставка в C++ часть 2
есть код. за его написание отдельное спасибо Kastaneda) #include &lt;iostream&gt; #include &lt;fstream&gt; using namespace std; int...

Вычисление значения выражения (asm-вставка)
Надо, чтобы посчитало c=(a+b)/d-d2*a-b с помощью Assebler. Что мне нужно поменять? P.S. Код в _asm не соответствует примеру. #pragma...

Asm вставка в С++ возвести число в степень
Возвести число А в степень n (на Assemblerе в С++)

Asm вставка и возвращаемое системе значение
Здравствуйте. Почему эта программа #include &lt;iostream&gt; using std::cout; using std::cin; int main() { int z = 0; _asm { ...

Вставка asm, адрес члена локального объекта
TLongInteger &amp; TLongInteger:: operator + (const TLongInteger &amp;Additional) { TLongInteger Result; asm { } return...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Новые блоги и статьи
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
Установка CMake и MinGW 13.1 для сборки С и C++ приложений из консоли и из Qt Creator в EXE
8Observer8 10.03.2026
Содержание блога MinGW - это коллекция инструментов для сборки приложений в EXE. CMake - это система сборки приложений. Здесь описаны базовые шаги для старта программирования с помощью CMake и. . .
Как дизайн сайта влияет на конверсию: 7 решений, которые реально повышают заявки
Neotwalker 08.03.2026
Многие до сих пор воспринимают дизайн сайта как “красивую оболочку”. На практике всё иначе: дизайн напрямую влияет на то, оставит человек заявку или уйдёт через несколько секунд. Даже если у вас. . .
Модульная разработка через nuget packages
DevAlt 07.03.2026
Сложившийся в . Net-среде способ разработки чаще всего предполагает монорепозиторий в котором находятся все исходники. При создании нового решения, мы просто добавляем нужные проекты и имеем. . .
Модульный подход на примере F#
DevAlt 06.03.2026
В блоге дяди Боба наткнулся на такое определение: В этой книге («Подход, основанный на вариантах использования») Ивар утверждает, что архитектура программного обеспечения — это структуры,. . .
Управление камерой с помощью скрипта OrbitControls.js на Three.js: Вращение, зум и панорамирование
8Observer8 05.03.2026
Содержание блога Финальная демка в браузере работает на Desktop и мобильных браузерах. Итоговый код: orbit-controls-threejs-js. zip. Сканируйте QR-код на мобильном. Вращайте камеру одним пальцем,. . .
SDL3 для Web (WebAssembly): Синхронизация спрайтов SDL3 и тел Box2D
8Observer8 04.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-sync-physics-sprites-sdl3-c. zip На первой гифке отладочные линии отключены, а на второй включены:. . .
SDL3 для Web (WebAssembly): Идентификация объектов на Box2D v3 - использование userData и событий коллизий
8Observer8 02.03.2026
Содержание блога Финальная демка в браузере. Итоговый код: finish-collision-events-sdl3-c. zip Сканируйте QR-код на мобильном и вы увидите, что появится джойстик для управления главным героем. . . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru