Тривиальня задача о переборе символов.

Тема в разделе "WASM.A&O", создана пользователем NoName, 8 май 2005.

Статус темы:
Закрыта.
  1. flankerx

    flankerx New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    423
    Адрес:
    Moscow, Russia




    Есть команда IMUL, формирующая 64-битный результат умножения двух 32-х разрядных чисел. Реализовать на ней перемножение 64-ч разрядного числа и 32-х разрядного совсем не сложно.



    Разница между FPU и CPU:

    FPU == Floating Point Unit == блок для работы с числами с плавающей точкой

    В СPU тебя явно интересует только АЛУ, которое умеет работать _только_ с целыми числами.
     
  2. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229


    Это всем ясно. Меня больше интересует скорость работы и другие неявные отличия.





    Хех. r32.
     
  3. flankerx

    flankerx New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    423
    Адрес:
    Moscow, Russia


    Ну откуда такие сведения, а?

    Результат IMUL помещается в регистровую пару EDX:EAX. RTFM.





    NO COMMENTS.
     
  4. Stiver

    Stiver Партизан дзена

    Публикаций:
    0
    Регистрация:
    18 дек 2004
    Сообщения:
    812
    Адрес:
    Germany
    NoName





    Мда.. ну и чему тут радоваться? Ошибка уже в 5-6 знаке означает, что на практике его функцию можно только выкрасить и выбросить :) Такую точность Ньютоном наверное и то можно быстрее получить...
     
  5. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    flankerx



    Если считаешь что я непонял что-то или глупый, лучше напиши об этом. Не нада делать гордого молчания. :)



    Насчет EDX:EAX я невниматален, ночью мозги несоображали.





    Ничему, статья так себе. Подкачаюсь посматрю может хватит материала на статью.
     
  6. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    Короче говоря неможет твой imul все равно умножать большие числа, как не крути. Только с толку сбил.



    Зато я немножко поискал и выяснилось что статьи по fpu на wasme уже давно есть, функция на сопроцессоре написана, чему я безумно рад (достаточно взглянуть на ее универсальность и код).



    Статьи:

    <ol type=1>

    http://www.wasm.ru/print.php?article=edfpu01

    http://www.wasm.ru/print.php?article=edfpu02

    </ol> Причем они выполнены не кем-то а самим Edmond'ом.



    Функция pow (a^b) на сопроцессоре.
     
  7. flankerx

    flankerx New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    423
    Адрес:
    Moscow, Russia




    Плохо крутишь, очень плохо....
     
  8. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    flankerx

    Если покажешь код тогда поверю.



    Набрасал тут сорс один для работы с целыми числами сейчас тестю. Он получился меньше, но зато неработает :)
     
  9. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    Прошу ознокомится с сорсом который неработает. Почему незнаю, причина в ламерстве.
    Код (Text):
    1. .586
    2. .model flat, stdcall
    3. option casemap:none
    4. include windows.inc
    5. include kernel32.inc
    6. include user32.inc
    7. includelib user32.lib
    8. includelib kernel32.lib
    9.  
    10. .data
    11. format db "%d",0
    12. buffer db 256 dup(0)
    13.  
    14. .data?
    15. temp dd ?
    16. temp2 dq ?  ;8 bytes
    17. total_comb dt ? ;10 bytes
    18.  
    19. .code
    20. start:
    21. ffree st
    22. ffree st(1)
    23. ffree st(7) ;for "p" functions, else #PF
    24.    
    25.     mov eax,10d
    26.     mov temp,eax  ;mantisa
    27.     fld temp      ;st(0)
    28.     fst st(1)
    29.     mov ecx,3d    ;poryadok ^
    30. f_mul: 
    31.     fmul st,st(1) ;result in st
    32.     loop f_mul         
    33.     fbstp total_comb ;see here
    34. ;   fstp temp2      ;see here
    35.     invoke wsprintf,offset buffer,offset format,offset total_comb    
    36.     invoke MessageBox,0,offset buffer,0,0  
    37.     call ExitProcess
    38. end start


    Цикл работает нормально, st нормально умножается на st1. Но результат забрать неудается. Получается вовсе не то число которое должно быть. На входе числа как видите целые, ошибки в расчетах нет.
     
  10. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
  11. flankerx

    flankerx New Member

    Публикаций:
    0
    Регистрация:
    2 июл 2004
    Сообщения:
    423
    Адрес:
    Moscow, Russia
    NoName

    Правда чтоли?

    Ну тогда вот, стандартный файл из CRT MS Visual C++ .NET (2003)....



     
  12. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    NoName

    > "Получается вовсе не то число которое должно быть"

    А ты с fbstp ничего не напутал ? Сохраняешь как BCD а в wsprintf выводишь как обычный decimal integer ? Нужно просто fistp dword [..] или qword.



    > "Да, кстати говоря ясной разницы между fpu и cpu я неуслышал. Как они хотябы в скорости?"

    Вот латентности по А.Фогу и IA-32 Optim.:
    Код (Text):
    1. Проц->  P6  P4(F2x) P4(F3x)
    2. mul 4   14-18   10
    3. fmul    5   7   8
    4. fild    5   ~10
    5. fist    5   ~10
    Как видим на FPU достаточно долго выполняются преобразования fild\fist, поэтому для однократного умножения (даже int64 по алгоритму приведенному flankerx) на FPU получается или дольше или фифти-фифти. А вот при возведении в степень, когда загрузка-выгрузка одна, а умножений много - ес-но на FPU для int64 получается быстрее.



    PS: на P4 CPUID < F3x целочисленное умножение реализовано на FPU_MUL, поэтому и выполняется дольше чем fmul (но внутрення конвертация делается быстрее, чем fild+fist)



    > "Набрасал тут сорс один для работы с целыми числами.."

    Вот тебе "веками" проверенный сорс из дельфей:
    Код (Text):
    1. ;function IntPower(Base: Extended; Exponent: Integer): Extended;
    2. ;asm
    3.         ;в eax - Exponent
    4.         mov     ecx, eax
    5.         cdq
    6.         fld1                      ;{ Result := 1 }
    7.         xor     eax, edx
    8.         sub     eax, edx          ;{ eax := Abs(Exponent) }
    9.         jz      @@3
    10.         fld     Base
    11.         jmp     @@2
    12. @@1:    fmul    ST, ST            ;{ X := Base * Base }
    13. @@2:    shr     eax,1
    14.         jnc     @@1
    15.         fmul    ST(1),ST          ;{ Result := Result * X }
    16.         jnz     @@1
    17.         fstp    st                ;{ pop X from FPU stack }
    18.         cmp     ecx, 0
    19.         jge     @@3
    20.         fld1
    21.         fdivrp                    ;{ Result := 1 / Result }
    22. @@3:
    23.         fwait
    24.         ;Result в st(0)
    25. ;end;
    Думаю адаптировать под int64 и убрать обработку отрицательных степеней особого труда не составит :)
     
  13. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    flankerx

    Будем считать что ты прав.



    leo

    Спасибо за разъеснение, попробую портировать.
     
  14. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    leo

    Сорсы то что мне дал мне непригодились. Мой код который я написал здесь также отлично работает и делает именно то что мне нужно за исключением конвертации BCD упакованных чисел.

    Кстати говоря в делфийском коде зря стоит fwait. Начиная с 386 эта инструкция выполняется автоматически.



    Я понимаю под BCD числами числа вида [16d = 16h]*

    Число возвращаемое тем (моим, касперски, hidden) сорсом постоянное при любых начальных условиях. Это странно и в случае предположения (*) так быть недолжно.
     
  15. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    NoName



    > "за исключением конвертации BCD упакованных чисел"

    > "Число возвращаемое тем (моим, касперски, hidden) сорсом постоянное при любых начальных условиях"



    Я ж тебе скромно намекал, что дело в неверном вызове wsprintf:

    1) раз ты сохраняешь число в BCD, то формат должен быть не "%d", а "%X"

    2) но главное - аргументом должен быть не указатель на число (offset total_comb), а само число. Вот видимо ты и выводишь всегда постоянное число = offset total_comb ;)



    Если тебе нужны большие числа в BCD формате, то нужно делать примерно так:

    format db "%X%.8X%.8X",0

    mov eax,offset total_comb

    invoke wsprintf,offset buffer,offset format,[eax+8],[eax+4],[eax]



    А в твоем сорсе еще ошибочка или опечаточка: после mov temp,eax должно идти fild temp, а не fld temp. Но раз ты говоришь, что "нормально умножается", то наверное это просто очепятка ;)





    > "Кстати говоря в делфийском коде зря стоит fwait. Начиная с 386 эта инструкция выполняется автоматически"



    Что ты говоришь =( Кем выполняется, процессором ?

    А вот в IA-32 (volume 1, раздел 8.6 x87 FPU Exception Synchronization) нечто совершенно обратное говорится:

    настоятельно рекомендуется использовать fwait чтобы в случае немаскированного FPU исключения, оно проявило себя не позднее fwait, а не "путешествовало" вместе с ошибочными результатами по программе, пока не встретится еще одна FPU-операция. (Все FPU исключения проявляются не на самой инструкции вызвавшей исключение, а в момент вызова следующей за ней FPU-инструкции или wait/fwait)
     
  16. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229


    Начиная с 387 это работает автоматом, поверь :)





    Это я тестил на 0.5





    Ты прав, это я со строчками переработал...





    Если в моем коде убрать offset, то он работает. Нужно сделать format db "%X",0. Тогда все верно. Все правильно.

    Всем большое спасибо за помощь.

    Только большие числа не выводятся. Не получилось больше чем 2^59 да и то с калькулятором не сходится.
     
  17. leo

    leo Active Member

    Публикаций:
    0
    Регистрация:
    4 авг 2004
    Сообщения:
    2.542
    Адрес:
    Russia
    Noname



    > "Только большие числа не выводятся. Не получилось больше чем 2^59"



    А ты чего хотел от FBSTP - вместо положенных 18 цифр выгрузить 19 ;)

    Читаем описание FBSTP в IA-32:

    Converts the value in the ST(0) register to an 18-digit packed BCD integer.

    If the converted value is too large for the destination format,..an invalid-arithmetic-operand condition is

    signaled. If the invalid-operation exception is masked, the packed BCD indefinite value is stored in memory.


    Размаскируй исключение IA (0-й бит) в FPU Control Word и получишь "приятное известие" от винды ;)



    > "да и то с калькулятором не сходится"



    Наверное опять FPU Control Word:

    Если CW = 02ххh, то все понятно - double precision = 53 бита, нужно установить 03xxh - extended 64 бита. Cм.аналогичный вопрос



    > "Начиная с 387 это работает автоматом, поверь :)"



    Может быть "начиная и заканчивая" ;) Помнится в 386 и сопроцессор был внешний и мнемоника ESC использовалась, которая сейчас считается obsolete :))

    Задокументированный в IA-32 и проверенный жизнью факт: по крайней мере процессоры PIII и P4 после FPU инструкции, вызывающей исключение, просто устанавливают в status word два флага - ES (error summary status) и B (FPU Busy) и ждут подходящего случая для сигнализации исключения. FPU становится заблокированным, но блоки integer ALU продолжают работать как обычно. Поэтому если после FPU инструкции, вызвавшей ошибку, идут целочисленные операции то программа может "убежать" довольно далеко от места ошибки. А проявляется эта ошибка при вызове WAIT или любой FPU инструкции (т.к. FPU заблокирован). Поэтому заботливый Borland в соответствии с рекомендацией IA-32 и ставит fwait после fdivrp, чтобы возможная ошибка проявилась сразу, а не где-то потом после возврата из функции.



    Если сомневаешься, то лучше не верить, а проверить.

    См.аналогичный вопрос и элементарный тест в аттаче, который показывает что exception вылетает не на fdiv, а на "отдаленном" fwait



    [​IMG] _226747233__FPU_wait.zip
     
  18. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    Кошмар, узнал страшную тайну.

    LONGLONG Int32x32To64(

    LONG Multiplier,

    LONG Multiplicand

    );
     
Статус темы:
Закрыта.