нужна c функция pow на асме

Тема в разделе "WASM.ASSEMBLER", создана пользователем _hidden_, 10 май 2005.

  1. _hidden_

    _hidden_ New Member

    Публикаций:
    0
    Регистрация:
    10 май 2005
    Сообщения:
    30
    Адрес:
    Russia
    уже долгое время никак не могу понять как работает функция pow для вычисления произвольной степени числа

    в дизассемлировании не силен



    может быть кто нибудь скажет, как она работает? чесное слово, не в цикле же она умножает ;)



    полный исходный код был бы в тему ;)



    хотелось бы мне в итоге получить 100% совместимую со cтандартной c pow, но на асме ;)
     
  2. Ms Rem

    Ms Rem New Member

    Публикаций:
    0
    Регистрация:
    17 апр 2005
    Сообщения:
    1.057
    Адрес:
    С планеты "Земля"
    > не в цикле же она умножает

    А почему нет? Команды возведения в степень у процессора не имеется, поэтому приходится умножать в цикле.
     
  3. Avoidik

    Avoidik New Member

    Публикаций:
    0
    Регистрация:
    29 дек 2004
    Сообщения:
    288
    Адрес:
    Russia
    Код (Text):
    1.  
    2. ;ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД ДДДДДДДДДД
    3. ; push  _powah
    4. ; push  _number
    5. ; call  _pow
    6. ;
    7. ; Podnosi _number do potegi _powah.
    8. ; Gdy _powah == 0, to _number = 1.
    9. ;
    10. ; na wejsciu:
    11. ; _powah  - wykladnik potegi
    12. ; _number - podstawa
    13. ;
    14. ; na wyjsciu:
    15. ; eax    - wynik
    16. ;
    17. ; modyfikowane rejestry:
    18. ; eax
    19. ;
    20. ; AntonOne/AAOCG
    21. ;ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД ДДДasmpakД
    22.  
    23. _pow proc uses ecx ebx value:DWORD, power:DWORD
    24.  
    25.     mov eax, value
    26.     mov ecx, power
    27.     jecxz   _pow_1
    28.  
    29.     dec ecx
    30.     jz  _pow_end
    31.  
    32.     xor ebx, ebx
    33.     mov ebx, eax
    34. @@:
    35.     imul    eax, ebx
    36.     dec ecx
    37.     jnz @B
    38.  
    39. _pow_end:
    40.     ret
    41. _pow_1:
    42.     xor eax, eax
    43.     inc eax
    44.     ret
    45.  
    46. _pow endp
    47.  
     
  4. _hidden_

    _hidden_ New Member

    Публикаций:
    0
    Регистрация:
    10 май 2005
    Сообщения:
    30
    Адрес:
    Russia
    > А почему нет? Команды возведения в степень у процессора

    > не имеется, поэтому приходится умножать в цикле.



    Да, ребята, не ожидал ;)



    Спасибо за код, но в цикле я и сам бы мог написать ;)

    То что мне надо я к счастью нашел, думаю это будет интересно.


    Код (Text):
    1. ; fpower - функция возведения X в степень Y
    2. ; Вход:  st(0) = X , st(1) = Y
    3. ; Выход: st(0) = X ^ Y , CF=NC=0 в случае успеха, CF=CY=1 при X<0 и нецелом Y ( st(0)=0 )
    4. ; Изменяемые регистры: AX, BL
    5. fpower      proc
    6.         ; st0=X, st1=Y
    7.  
    8.         ftst                   ; st0=X=0 ?
    9.         fstsw   ax
    10.         sahf
    11.         jz  @@Zero         ; Да, результат = 0 (CF=NC=0, кстати!)
    12.         mov bl,ah          ; BL and 1=1 при X<0, 0 при X>0 (исп-ся после получения результата)
    13.         ja  @@PositiveX    ; Если X>0, то никаких проверок нам больше не надо
    14.  
    15.         fxch                   ; Обмен st0 <-> st1 (st0=Y, st1=X)
    16.         fld st(0)          ; st2=st1=X, st1=st0=Y, st0=st0=Y
    17.         frndint                ; st0=Round(st0)=Round(Y)
    18.         fcomp                  ; Сраниваем st0 и st1; st0=st1=Y, st1=st2=X, st3=пусто
    19.         fstsw   ax             ; В AH флаг ZF=ZR=1 при целом Y
    20.         sahf                   ; Y целое?
    21.         jnz @@Error        ; Нет, отрицательные числа нельзя возводить в нецелую степень!
    22.  
    23.         fld1
    24.         fld1
    25.         fadd                   ; st2=st1=X, st1=st0=Y, st0=2
    26.         fld st(1)          ; st3=st2=X, st2=st1=Y, st1=st0=2, st0=st1=Y
    27.         fprem                  ; st0=st0 mod st1=Y mod 2
    28.         ftst                   ; st0=0 (Y mod 2=0, т.е. чётное) ?
    29.         fstsw   ax             ; В AH флаг ZF=ZR=1 при чётном Y (CF=NC=0, кстати!)
    30.         fstp    st(0)          ; Удаляем остаток от деления
    31.         fstp    st(0)          ; Удаляем число 2 (st0), st0=st1=Y, st1=st2=X, st2=пусто
    32.         fxch                   ; Обмен st0 <-> st1 (st0=X, st1=Y)
    33. @@PositiveX:
    34.         fabs                   ; st0=|st0|=|X|
    35.         fyl2x                  ; st0 = st1*log2(st0) = Y*log2(|X|)
    36.         fld st(0)          ; st1=st0
    37.         frndint                ; st0=Round(st0)
    38.         fsub    st(1),st(0)    ; st1=st1-st0
    39.         fld1                   ; st1=st0, st0=1
    40.         fscale                 ; st0=st0*2^st1
    41.         fstp    st(1)          ; Удаляем st1
    42.         fincstp                ; st7=st0, st0=st1
    43.         f2xm1                  ; st0=(2^st0)-1
    44.         fmul    st(0),st(7)    ; st0=st0*st7
    45.         fdecstp                ; st1=st0, st0=st7
    46.         fadd                   ; st0=st0+st1, st0=пусто
    47.         ; Результат в st0 !!!
    48.  
    49.         test    bl,1           ; X<0 ? (CF=NC=0, кстати!)
    50.         jz  @@End          ; Нет, завершаем
    51.         sahf                   ; Y чётное
    52.         jz  @@End          ; Да, завершаем
    53.         fchs                   ; Если X<0, а Y нечётное, то меняем знак результата
    54. @@End:      ret                    ; Выходим!
    55. @@Error:
    56.         fldz                   ; Заносим 0
    57.         fstp    st(1)          ; Удаляем X
    58.         stc                    ; CF=CY=1 - ошибка
    59. @@Zero:
    60.         fstp    st(1)          ; Удаляем Y
    61.         ret                    ; Выходим!
    62.  
    63. fpower      endp
     
  5. _hidden_

    _hidden_ New Member

    Публикаций:
    0
    Регистрация:
    10 май 2005
    Сообщения:
    30
    Адрес:
    Russia
    и все же на wasm.ru я все таки нашел еще один ответ на мой вопрос:

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



    осталось только найти дизасм сишной функции для полной совместимости с сишными программами



    эта функция будет незаменима для демок
     
  6. leo

    leo Active Member

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

    > "хотелось бы мне в итоге получить 100% совместимую со cтандартной c pow, но на асме ;)"



    В борландовском C++Builder'e эта функция реализована на asm'e с подробными комментариями и пояснениями (..\source\..\math\pow.asm).

    В частности говорится, что для целых степеней < 100 быстрее работает вычисление в цикле. Но цикл ес-но не тупой, а основанный на разложении степени exponent по степеням двойки => возведим base в квадрат, делаем shr exponent, если мл.бит <> 0, то умножаем результат на текущее значение base^2n и т.д. пока exponent <> 0 (см. FPU и 10^X). Итого N = log2(exponent) итераций и максимум 2N умножений.
     
  7. Dart_Bobr

    Dart_Bobr New Member

    Публикаций:
    0
    Регистрация:
    24 сен 2004
    Сообщения:
    100
    Адрес:
    Ukraine
    Я чето не пойму exp(А*ln(В)) уже не рулит??
     
  8. kaspersky

    kaspersky New Member

    Публикаций:
    0
    Регистрация:
    18 май 2004
    Сообщения:
    3.006
    2leo:

    ты не это имеешь ввиду?
    Код (Text):
    1. ; pow.asm
    2. comment ^
    3. This sample program shows one method of calculating X raised to
    4. the Y power where Y is a relatively small positive integer.
    5. This code requires a numeric coprocessor.
    6.  
    7. The algorithm:
    8. Starting from the most significant bit (bit number i) in our
    9. exponent, we calculate Z = X raised to the Y power as in the
    10. following psuedocode:
    11.  
    12. Z = X
    13. while (i > 0)
    14. {
    15.   Z = Z * Z
    16.   if (bit i in exponent is 1)
    17.   {
    18.     Z = Z * X
    19.   }
    20.   i = i - 1
    21. }
    22. written on Wed  09-06-1995  by Ed Beroset
    23. and released to the public domain by the author
    24. ^
    25. .MODEL tiny
    26. .486
    27.  
    28. ;        STACK   400h
    29.  
    30.         .DATA
    31. X           dt  23.125          ; an arbitrary X
    32. Y           db  12              ; a positive integral exponent
    33. result      dt  ?               ; the answer, as everyone knows,
    34.                                 ; is 23387343638035088 and change
    35.  
    36.         .CODE
    37. main proc
    38.         .STARTUP
    39.         finit                           ; initialize the NPU
    40.         mov     cx,8                    ; get set for eight bits max
    41.         mov     al,[Y]                  ; load our exponent
    42.         or      al,al                   ; Q: is our exponent zero?
    43.         jnz     LoadX                   ;   N: we continue
    44.         fld1                            ;   Y: we know the answer
    45.         jmp     Exit                    ; and exit
    46. LoadX:
    47.         fld     [X]                     ; ST(0) = X
    48.         fld     [X]                     ; ST(0) = X, ST(1) = X
    49. Slider:
    50.         dec     cx                      ; decrement our count
    51.         shl     al,1                    ; shift exponent left until..
    52.         jnc     Slider                  ;  ..we find our first set bit
    53. CalcExp:
    54.         fmul    st(0), st(0)            ; square our result
    55.         shl     al,1                    ; test high bit
    56.         jnc     SkipMul                 ; if it's clear, skip mul
    57.         fmul    st(0), st(1)            ; multiply by original X
    58. SkipMul:
    59.         loop    CalcExp                 ; continue with all remaining bits
    60. Exit:
    61.         fstp    [result]                ; store sin(angle) in result
    62.         ffree   st(0)                   ; clean up
    63.         .EXIT 0
    64. main endp
    65.         END
     
  9. NoName

    NoName New Member

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

    leo Active Member

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

    > "ты не это имеешь ввиду?"



    Если речь о возведении в целую степень, то не совсем то, а если о pow.asm, то совсем не то :)



    В бормановском варианте анализ экспоненты идет от младших бит к старшим и соответсвенно не нужен поиск старшего значащего бита. Псевдокод примерно такой:

    Z = 1

    while (Y <> 0)

    {

    if (мл.бит Y = 1)

    {Z = Z * X}

    X = X*X

    Y = Y >> 1

    }

    Что касается "сишной" pow.asm в бормановской реализации, то при небольших целых Y степень вычисляется по приведенному выше алгоритму, а при больших или дробных ес-но по общей формуле Z = 2^(Y*Log2(X)) - примерно также как привел _hidden_, только вроде там еще анализ переполнения экспоненты делается.
     
  11. NoName

    NoName New Member

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

    Как ты результат работы забирал из сопроцессора?
     
  12. _hidden_

    _hidden_ New Member

    Публикаций:
    0
    Регистрация:
    10 май 2005
    Сообщения:
    30
    Адрес:
    Russia
    В смысле?
     
  13. NoName

    NoName New Member

    Публикаций:
    0
    Регистрация:
    1 авг 2004
    Сообщения:
    1.229
    Зайди пж-та в мою тему, ссылка сверху.