-
Странное дело. Есть такой код:
var
t: double;
t := (1 / 1000); С включенной опцией компилятора Optimization получается число QNAN. Без оптимизации все нормально. Кто нибудь сталкивался? И как можно это дело обойти? Delphi XE6.
-
1.0/1000.0
-
1 и 1000 целочисленные.
-
как узнал, что там QNAN ? (32/64?)
-
Через FloatToStrF выводит строку NAN и в Watch List добавил переменную.
-
64
-
> dmk © (14.01.17 20:28) [2] > > 1 и 1000 целочисленные.
Это ты так считаешь. На самом деле что 1, что 1000 это константы неопределенного типа. Как их использует компилятор - знает только он.
-
Ставь точку останова и показывай асм/регистры
-
Да с регистрами все в порядке. Сразу после расчета 0.001 получается. Сделал переменные глобальными — стало все в порядке, а так компилятор рушил локальные переменные, хотя и не должен.
Получается так: 1. f := 1/1000; 2. Какие-то другие расчеты 3. Вызов внешней процедуры 4. Тут происходит слет внутренних переменных. 5. Использование переменных невозможно из-за слетевшего значения
А не должно быть так вроде :(
-
> 3. Вызов внешней процедуры с этого момента поподробнее ))
-
Тут дело в оптимизации в общем. Когда она включена, то переменные по возможности хранятся в XMM-регистрах, а когда выключена в памяти. Отсюда и слет при внешнем вызове. У меня XMM-регистры используются.
-
Видимо недоработка компилятора.
-
-
Да не, с передачей параметров у меня порядок. Какого черта компилятор переменные помещает в регистры?
-
-
>а как иначе процессору работать с переменными ?
Процессор тут не при чем. Это компилятор распихивает переменные. В случае оптимизации в регистры. Без - в память. Отсюда и глюк.
-
> В случае оптимизации в регистры.
и глюк в том, что ты тоже используешь эти регистры (из асм кода) не сохранив/восстановив их значение?
-
Ну да. Именно так. Подстава от компилятора :)
-
У меня просто оптимизация никогда не включалась. По умолчанию она выключена.
-
Так кто кого подставил?
-
>Так кто кого подставил? Компилятор меня. В хелпе про это нет ни слова.
-
Вообще странно, я проверил на ХЕ4 и на последнм Берлине, не воспроизвелось (ХЕ6 нет)
-
Для меня это тоже странно.
Там такой код:
//Единица на случай нулевой разницы if (gEndTime = gStartTime) then gEndTime := (gEndTime + 1); //Время использованное на отрисовку кадра в миллисекундах gUsedTime := (gEndTime - gStartTime); //Время использованное на отрисовку кадра в секундах gFrameTime := (gUsedTime / 1000); //Всего кадров отрисовано с момента сброса gTotalFrames := (gTotalFrames + 1); //Всего времени с момента сброса gTotalTime := (gTotalTime + gFrameTime); //Кадров в секунду с момента сброса gFPS := (gTotalFrames / gTotalTime);
Потом вызывается
//Рамка региона отсечения sBmp.RectAA(Rgn.X, Rgn.Y, Rgn.W, Rgn.H, crWhite, 255, 128);
Внутри RectAA есть вызов
//Рисуем линию FBlendScLine(lpDA, lpLen, dColor, dAlpha, dOpacity);
В линии (часть кода):
//Формируем маски очистки из одной movdqu xmm6, PClearMask //Читаем общую маску очистки movdqu xmm8, xmm6 //дублируем movdqu xmm9, xmm6 //дублируем psrldq xmm8, 1 //xmm8 - Маска очистки 15-го байта psrldq xmm9, 15 //xmm9 - маска инверсии psrldq xmm6, 8 //в xmm6 маска очистки 7..0 байтов
В общем использую xmm на полную. После выход а из нее переменная приобретает вид QNAN вместо 0,001 как было до нее.
Где я накосячил? Если сделать переменную глобальную - все в полном порядке. Если выключить оптимизацию - все хорошо. Поэтому вывод один - компилятор пихает локульную переменную в регистры. И да стека у меня нет. Ничего не сохраняю. Там все 16 xmm-регистров используются.
-
МОгу полный код FBlendScLine на почту скинуть. Кормить не хочу халявщиков :)
-
In line with the x64 Application Binary Interface (ABI), the contents of the following registers must be preserved and restored within inline assembly functions: R12, R13, R14, R15, RDI, RSI, RBX, RBP, RSP, XMM4, XMM5, XMM6, XMM7, XMM8, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, and XMM15. http://docwiki.embarcadero.com/RADStudio/XE6/en/Using_Inline_Assembly_Code
-
Ну да, меня предупреждали :(
-
Спасибо!
|