2011-01-09 1 views
26

Я ищу реализацию pow(real, real) в x86 Assembly. Также я хотел бы понять, как работает алгоритм.Практическое руководство: pow (real, real) in x86

+0

вы используете x87 или SSE? –

+0

реализация glibc функции 'pow()' [в sysdeps/ieee754/dbl-64/e_pow.c] (http://repo.or.cz/glibc.git/blob/HEAD:/sysdeps/ieee754/ ДВМ-64/e_pow.c). Он использует некоторое целочисленное исследование битовых шаблонов FP, а некоторые FP умножает и добавляет, но не использует никаких специальных инструкций x87. Для x86-64 он скомпилируется в '__ieee754_pow_sse2()' ([этим кодом, который # включает его] (http://repo.or.cz/glibc.git/blob/455d6e4373c81da49892d39f33dc312b0c54097d:/sysdeps/x86_64/fpu/ мультиархитектурная/e_pow.c)). Во всяком случае, x87 - это не лучший способ сделать это на современных процессорах. –

+0

Я предполагаю, что код glibc является более точным или быстрее, чем x87. Возможно, и то и другое, но, возможно, просто более точное (правильно округленное до ближайшего). Он не использует цикл, хотя и однократный по инструкциям, для * pow (1.175, 33.75) 'не существует * * *. FYL2X - очень медленная команда (~ 100 циклов) на современных процессорах, поэтому ее не должно бить так сложно. –

ответ

55

Просто вычислите его как 2^(y*log2(x)).

Существует инструкция x86 FYL2X для вычисления y * log2 (x) и инструкции x86 F86X1 для выполнения возведения в степень. F2XM1 требует аргумента в диапазоне [-1,1], поэтому вам нужно будет добавить некоторый код между ними, чтобы извлечь целую часть и оставшуюся часть, увеличив остаток, используйте FSCALE для масштабирования результата с соответствующей мощностью 2.

+2

+1 Такой простой, изящный ответ! – templatetypedef

+2

Супер, спасибо за обмен и приятное воскресенье. –

+2

Я знаю, что это старый поток, но вот реализация: [madwizard.org] (http://www.madwizard.org/programming/snippets?id=36) – Matth

15

OK, я внедрил power(double a, double b, double * result); в x86 так же, как вы рекомендовали.

Код: http://pastebin.com/VWfE9CZT

%define a    QWORD [ebp+8] 
%define b    QWORD [ebp+16] 
%define result   DWORD [ebp+24] 
%define ctrlWord   WORD [ebp-2] 
%define tmp    DWORD [ebp-6] 

segment .text 
    global power 

power: 
    push ebp 
    mov ebp, esp 
    sub esp, 6 
    push ebx 

    fstcw ctrlWord 
    or ctrlWord, 110000000000b 
    fldcw ctrlWord 

    fld b 
    fld a 
    fyl2x 

    fist tmp 

    fild tmp 
    fsub 
    f2xm1 
    fld1 
    fadd 
    fild tmp 
    fxch 
    fscale 

    mov ebx, result 
    fst QWORD [ebx] 

    pop ebx 
    mov esp, ebp 
    pop ebp 
    ret 
+3

Могу ли я рекомендовать вам продолжить и включить этот код здесь, в вашем ответе? –

+1

Готово, в комплекте. –

+1

Вы должны 'sub esp, 8', чтобы выровнять его для нажатия ebx. Вы также можете поменять tmp и ControlWord, например. '% define tmp DWORD [ebp-4]', поэтому он выровнен. –