#c #assembly #visual-c #32bit-64bit #inline-assembly
Вопрос:
Я пытался преобразовать 32-битный игровой клиент в 64-битный. Но я не могу скомпилировать, потому что у клиента есть встроенный ASM-код, 64-битный не поддерживает __asm inline. Поэтому я не могу найти решение для этого. Я надеюсь, что смогу попасть в это сообщество.
определение встроенного кода:
#define PR_FLOAT_TO_INTASM __asm { __asm fld PR_FCNV __asm fistp PR_ICNV } #define PR_FLOAT_TO_INT(inreal, outint) { PR_FCNV = (inreal); PR_FLOAT_TO_INTASM; (outint) = PR_ICNV gt; PR_FCNV ? PR_ICNV - 1 : PR_ICNV; }
Пример кода с использованием:
float CMapOutdoor::GetTerrainHeight(float fx, float fy) { if (fy lt; 0) fy = -fy; long lx, ly; PR_FLOAT_TO_INT(fx, lx); PR_FLOAT_TO_INT(fy, ly); WORD usCoordX, usCoordY; usCoordX = (WORD)(lx / CTerrainImpl::TERRAIN_XSIZE); usCoordY = (WORD)(ly / CTerrainImpl::TERRAIN_YSIZE); BYTE byTerrainNum; if (!GetTerrainNumFromCoord(usCoordX, usCoordY, amp;byTerrainNum)) return 0.0f; CTerrain* pTerrain; if (!GetTerrainPointer(byTerrainNum, amp;pTerrain)) return 0.0f; return pTerrain-gt;GetHeight(lx, ly); }
Код ошибки:
error C2146: syntax error : missing ';' before identifier 'PR_ICNV' error C2146: syntax error : missing ';' before identifier 'fistp' error C2146: syntax error : missing ';' before identifier '}'
Комментарии:
1. Используйте любой основной компилятор, кроме MSVC. Но на самом деле вам не нужна или даже не нужна встроенная asm для этого или устаревшие инструкции x87 вообще. Похоже, вы просто конвертируетесь
float
вint32_t
функцию с округлением до ближайшего (fistp
), что вам следует сделать сlrint(float)
помощью или(int)nearbyint(float)
. За исключением того, что вы вручную округляете, чтобы реализовать округление в сторону-inf? Для этого нет инструкции SSE/AVX, которая могла бы переопределить режим округления, но с SSE4.1roundss
вы можете эффективно(int)floor(float)
2. Так что на самом деле лучше задать вопрос о том, как эффективно (при компиляции MSVC для x86-64 и, возможно, также 32-разрядной x86) реализовать преобразование в целое число с округлением в сторону-inf. Очень вероятно, что на самом деле это не оптимальный asm для 32-разрядной версии, особенно если он включает копирование вашей переменной с плавающей точкой в какую-либо случайную глобальную переменную и перезагрузку. Я предполагаю
PR_FCNV
, что это где-то определено?/3. @PeterCordes , Да, определились. ` плавающий PR_FCNV; длинный PR_ICNV;`