уже долгое время никак не могу понять как работает функция pow для вычисления произвольной степени числа в дизассемлировании не силен может быть кто нибудь скажет, как она работает? чесное слово, не в цикле же она умножает полный исходный код был бы в тему хотелось бы мне в итоге получить 100% совместимую со cтандартной c pow, но на асме
> не в цикле же она умножает А почему нет? Команды возведения в степень у процессора не имеется, поэтому приходится умножать в цикле.
Код (Text): ;ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД ДДДДДДДДДД ; push _powah ; push _number ; call _pow ; ; Podnosi _number do potegi _powah. ; Gdy _powah == 0, to _number = 1. ; ; na wejsciu: ; _powah - wykladnik potegi ; _number - podstawa ; ; na wyjsciu: ; eax - wynik ; ; modyfikowane rejestry: ; eax ; ; AntonOne/AAOCG ;ДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДДД ДДДasmpakД _pow proc uses ecx ebx value:DWORD, power:DWORD mov eax, value mov ecx, power jecxz _pow_1 dec ecx jz _pow_end xor ebx, ebx mov ebx, eax @@: imul eax, ebx dec ecx jnz @B _pow_end: ret _pow_1: xor eax, eax inc eax ret _pow endp
> А почему нет? Команды возведения в степень у процессора > не имеется, поэтому приходится умножать в цикле. Да, ребята, не ожидал Спасибо за код, но в цикле я и сам бы мог написать То что мне надо я к счастью нашел, думаю это будет интересно. Код (Text): ; fpower - функция возведения X в степень Y ; Вход: st(0) = X , st(1) = Y ; Выход: st(0) = X ^ Y , CF=NC=0 в случае успеха, CF=CY=1 при X<0 и нецелом Y ( st(0)=0 ) ; Изменяемые регистры: AX, BL fpower proc ; st0=X, st1=Y ftst ; st0=X=0 ? fstsw ax sahf jz @@Zero ; Да, результат = 0 (CF=NC=0, кстати!) mov bl,ah ; BL and 1=1 при X<0, 0 при X>0 (исп-ся после получения результата) ja @@PositiveX ; Если X>0, то никаких проверок нам больше не надо fxch ; Обмен st0 <-> st1 (st0=Y, st1=X) fld st(0) ; st2=st1=X, st1=st0=Y, st0=st0=Y frndint ; st0=Round(st0)=Round(Y) fcomp ; Сраниваем st0 и st1; st0=st1=Y, st1=st2=X, st3=пусто fstsw ax ; В AH флаг ZF=ZR=1 при целом Y sahf ; Y целое? jnz @@Error ; Нет, отрицательные числа нельзя возводить в нецелую степень! fld1 fld1 fadd ; st2=st1=X, st1=st0=Y, st0=2 fld st(1) ; st3=st2=X, st2=st1=Y, st1=st0=2, st0=st1=Y fprem ; st0=st0 mod st1=Y mod 2 ftst ; st0=0 (Y mod 2=0, т.е. чётное) ? fstsw ax ; В AH флаг ZF=ZR=1 при чётном Y (CF=NC=0, кстати!) fstp st(0) ; Удаляем остаток от деления fstp st(0) ; Удаляем число 2 (st0), st0=st1=Y, st1=st2=X, st2=пусто fxch ; Обмен st0 <-> st1 (st0=X, st1=Y) @@PositiveX: fabs ; st0=|st0|=|X| fyl2x ; st0 = st1*log2(st0) = Y*log2(|X|) fld st(0) ; st1=st0 frndint ; st0=Round(st0) fsub st(1),st(0) ; st1=st1-st0 fld1 ; st1=st0, st0=1 fscale ; st0=st0*2^st1 fstp st(1) ; Удаляем st1 fincstp ; st7=st0, st0=st1 f2xm1 ; st0=(2^st0)-1 fmul st(0),st(7) ; st0=st0*st7 fdecstp ; st1=st0, st0=st7 fadd ; st0=st0+st1, st0=пусто ; Результат в st0 !!! test bl,1 ; X<0 ? (CF=NC=0, кстати!) jz @@End ; Нет, завершаем sahf ; Y чётное jz @@End ; Да, завершаем fchs ; Если X<0, а Y нечётное, то меняем знак результата @@End: ret ; Выходим! @@Error: fldz ; Заносим 0 fstp st(1) ; Удаляем X stc ; CF=CY=1 - ошибка @@Zero: fstp st(1) ; Удаляем Y ret ; Выходим! fpower endp
и все же на wasm.ru я все таки нашел еще один ответ на мой вопрос: http://www.wasm.ru/article.php?article=edfpu02 осталось только найти дизасм сишной функции для полной совместимости с сишными программами эта функция будет незаменима для демок
_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 умножений.
2leo: ты не это имеешь ввиду? Код (Text): ; pow.asm comment ^ This sample program shows one method of calculating X raised to the Y power where Y is a relatively small positive integer. This code requires a numeric coprocessor. The algorithm: Starting from the most significant bit (bit number i) in our exponent, we calculate Z = X raised to the Y power as in the following psuedocode: Z = X while (i > 0) { Z = Z * Z if (bit i in exponent is 1) { Z = Z * X } i = i - 1 } written on Wed 09-06-1995 by Ed Beroset and released to the public domain by the author ^ .MODEL tiny .486 ; STACK 400h .DATA X dt 23.125 ; an arbitrary X Y db 12 ; a positive integral exponent result dt ? ; the answer, as everyone knows, ; is 23387343638035088 and change .CODE main proc .STARTUP finit ; initialize the NPU mov cx,8 ; get set for eight bits max mov al,[Y] ; load our exponent or al,al ; Q: is our exponent zero? jnz LoadX ; N: we continue fld1 ; Y: we know the answer jmp Exit ; and exit LoadX: fld [X] ; ST(0) = X fld [X] ; ST(0) = X, ST(1) = X Slider: dec cx ; decrement our count shl al,1 ; shift exponent left until.. jnc Slider ; ..we find our first set bit CalcExp: fmul st(0), st(0) ; square our result shl al,1 ; test high bit jnc SkipMul ; if it's clear, skip mul fmul st(0), st(1) ; multiply by original X SkipMul: loop CalcExp ; continue with all remaining bits Exit: fstp [result] ; store sin(angle) in result ffree st(0) ; clean up .EXIT 0 main endp END
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_, только вроде там еще анализ переполнения экспоненты делается.