встроенный ассемблер прямой двойной в длинную длинную конверсию

По соображениям оптимизации я думал о вызове напрямую (с встроенным ассемблером)
к функциям «флдл» и «кулак». К сожалению, я не понимаю, как управлять этим, так как я не тот бог в ассемблере.

я не получил дальше, чем это:

double* input;
long long output;

__asm fldl input;
__asm fist output;

0

Решение

__asm fld input на самом деле попытается прочитать ваш указатель значение, как если бы это было значение с плавающей запятой. Если вы хотите прочитать значение с плавающей точкой указал указателем, Вы должны пройти двухэтапный процесс: прочитать адрес в регистр, а затем прочитать данные, используя адрес в реестре. На 32-битной платформе это будет что-то вроде

__asm {
mov eax, input
fld qword ptr [eax]
fistp output
}

Я только попробовал это в VS2005, и это работает. (Обратите внимание, что, как и другие люди заявили в комментариях, fist не поддерживает хранение в 64-битной версии long long, в то время как fistp делает. Но вам наверное нужно fistp во всяком случае, т. е. в магазине.)

1

Другие решения

Самым простым, вероятно, является:

double input;
long long output;

__asm fld input
__asm fisttp output

Это делает «нормальное» двойное и длинное длинное преобразование, усекающееся до нуля, точно так же, как в C-броске. Очень старые (до Pentium4) процессоры не поддерживают fistppВпрочем, поэтому на таких машинах нужно использовать fistp вместо этого, который использует текущий режим округления (обычно округление до ближайшего). Поэтому, если вы хотите, например, округлить в сторону -infinity, вам нужно сохранить текущий режим округления, установить его на то, что вы хотите, сделать fistp и восстановить режим округления:

double input;
long long output;
unsigned short oldcw, cw;

__asm fld input
__asm fstcw oldcw
cw = (oldcw & ~0xc00) | 0x400; // round towards -infinity
__asm fldcw cw
__asm fistp output
__asm fldcw oldcw
0

По вопросам рекламы [email protected]