LINUX.ORG.RU

В чем смысл ассемблерной конструкции (x86)?

 ,


0

5

Декомпилируя очередную библиотеку наткнулся на странную конструкцию (на входе xmm0):

movss xmm1, dword ptr [ebx-303BE0h]
movss xmm2,xmm0
divss xmm2,xmm1
mulss xmm1,xmm2
subss xmm0,xmm1
Для чего такое могло понадобиться? Это ж тождественно нулю должно быть? Или не?


Декомпилируя очередную библиотеку

Но зачем???

наткнулся на странную конструкцию

Библиотека, случаем, не времён fdiv_bug?

redgremlin ★★★★★
()
Ответ на: комментарий от anonymous

Я на первый коммент смотрел :) Обычно этот финт используется для целочисленной арифметики, чтобы выровнять чего-нибудь по страницам, например, или строго равномерно поделить картинку на части.

Тем не менее - суть та же самая, приведение x2 к такому значению, чтобы в x2 гарантировано было представимое в «single-precision floating-point» количество x1.

Stanson ★★★★★
()
Ответ на: комментарий от Stanson

Оно и так представимо посредством присутствия в xmm0

anonymous
()
Ответ на: комментарий от MBK

дайте файл посмотрим что скажет hexrays

anonymous
()

Похоже на попытку оценить погрешность вычислений, так сказать, минимальную дельту при работе с числами сравнимыми с dword ptr [ebx-303BE0h]

anonymous
()
Ответ на: комментарий от MBK

На самом деле арифметика не целочисленная, следовательно xmm0/xmm1*xmm1==xmm0 В чем тогда подвох?

Если рассматривать совсем не целочисленный single precision float, например, то если xmm0 = 1e-23 а xmm1 = 1e23, то (xmm0/xmm1)*xmm1==0 а не xmm0. В других случаях может быть внезапно inf а не xmm0. Можешь проверить.

Но на самом деле я всё понял.

Типичный детект fdiv_bug:

4195835.0 - 3145727.0*(4195835.0/3145727.0) = 0    (Correct value)
4195835.0 - 3145727.0*(4195835.0/3145727.0) = 256  (Flawed Pentium)

В общем, это проверка на наличие FDIV_BUG скомпилённая с SSE :) в [ebx-303BE0h] должно лежать 3145727.0, а в xmm0 где-то ранее загружаться 4195835.0

Stanson ★★★★★
()
Последнее исправление: Stanson (всего исправлений: 3)
Ответ на: комментарий от Stanson

В общем, это проверка на наличие FDIV_BUG скомпилённая с SSE :) в [ebx-303BE0h] должно лежать 3145727.0, а в xmm0 где-то ранее загружаться 4195835.0

Это чертовски похоже на истину, но, к сожалению, навряд ли. :( Более расширенный кусок кода выглядит так:

ucomiss xmm0, dword ptr [ebx-303BE0h] ;-7.81686689859073E-16
jbe loc_562DB1
movss xmm1, dword ptr [ebx-303BE0h]   ;-7.81686689859073E-16
movss xmm2,xmm0
divss xmm2,xmm1
mulss xmm1,xmm2
subss xmm0,xmm1
movss dword ptr [eax],xmm0
jmp loc_562DF9
loc_562DB1:
movss xmm1, dword ptr [ebx-303BDCh]   ;-5.77456881880694E-16
ucomiss xmm1,xmm0
jbe loc_562DF4
movss xmm1, dword ptr [ebx-303BE0h]   ;-7.81686689859073E-16
movss xmm2,xmm0
divss xmm2,xmm1
mulss xmm1,xmm2
addss xmm1,xmm0
movss dword ptr [eax],xmm1
jmp loc_562DF9

То есть, все страньше и страньше... :(

MBK
() автор топика
Ответ на: комментарий от anonymous

К сожалению, библиотеку полностью предоставить не могу. Да и не пойму, чем она может помочь? Возможно, я напутал с константами [ebx-303BE0h] = Hex 0x4C18E14E = Real -7.81686689859073E-16 [ebx-303BDCh] = Hex 0xCC18E14E = Real -5.77456881880694E-16 Или не?

MBK
() автор топика
Ответ на: комментарий от MBK

а че толку гадать на ромашках если нельзя это посмотреть декомпилятором ?

anonymous
()
Ответ на: комментарий от MBK

Не очень понятно, как -7.81686689859073E-16 может хранится в dword. ближайшее число представимое в single precision float - -7.81686684714236017235e-16

Stanson ★★★★★
()
Ответ на: комментарий от xaizek

Hex 0x4C18E14E = Real +4.00766E7
Hex 0xCC18E14E = Real -4.00766E7

Ай, спасибо, мил человек, это все ставит на место! Так решились все заботы, так узнали чё к чему! Единственный вопрос - это чего ж винхекс так в заблуждение вводит своим странным интерпретатором данных?

MBK
() автор топика
Ответ на: комментарий от MBK

Если он действительно на 0x4C18E14E говорит, что число отрицательное, то он что-то совсем не то делает. Знаковый бит же сброшен.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

Ну логика конструкции следующая:

if (x>4.00766E7) x-=x/4.00766E7*4.00766E7; else
{
   if (x<-4.00766E7) x+=x/4.00766E7*4.00766E7;
}
И это весьма смахивает на истину.

MBK
() автор топика
Ответ на: комментарий от Einstok_Fair

Разъясняю для опоздавших на праздник. Данная конструкция - классический пример индийского кода в вакууме. Задумывалась проверка переполнения на +-40076600 (я думаю, многие догадались даже что это за волшебная цифра) но глупые индусы не учли что арифметика не целочисленная в итоге имеем такой безумный код

MBK
() автор топика
Ответ на: комментарий от MBK

Длина экватора Земного шара равна 40 075 696 м.

Но мне непонятно, почему плюс-минус (а например не от нуля, до плюс длины, или плюс-минус ПОЛОВИНА длины)

Einstok_Fair ★★☆
()
Последнее исправление: Einstok_Fair (всего исправлений: 2)
Ответ на: комментарий от Einstok_Fair

180 это не 360. А длина экватора это 360

Так дикари-с! :D

MBK
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.