2011-01-09 8 views
26

Busco la implementación de pow(real, real) en Asamblea x86. También me gustaría entender cómo funciona el algoritmo.Cómo: pow (real, real) en 86

+0

¿Está utilizando x87 o SSE? aplicación –

+0

de glibc de la 'pow()' función es [en sysdeps/IEEE754/dbl-64/e_pow.c] (http://repo.or.cz/glibc.git/blob/HEAD:/sysdeps/ieee754/ dbl-64/e_pow.c). Utiliza algunos exámenes enteros de los patrones de bits de FP, y algunos FP se multiplican y añaden, pero no utilizan ninguna instrucción especial de x87. Para x86-64, que se compila en '__ieee754_pow_sse2()' ([por este código que se #Includes] (http://repo.or.cz/glibc.git/blob/455d6e4373c81da49892d39f33dc312b0c54097d:/sysdeps/x86_64/fpu/ multiarch/e_pow.c)). De todos modos, x87 no es la mejor manera de hacerlo en CPU modernas. –

+0

Supongo que el código de glibc es más preciso o más rápido que x87. Posiblemente ambos, pero tal vez solo más precisos (redondeados correctamente al más cercano). Sin embargo, no utiliza un bucle, y al recorrer las instrucciones, no hay * que * muchos para 'pow (1.175, 33.75)'. FYL2X es una instrucción muy lenta (~ 100 ciclos) en CPU modernas, por lo que no debería ser tan difícil de superar. –

Respuesta

55

sólo calcula como 2^(y*log2(x)).

Hay una FYL2X de instrucciones x86 para calcular y * log2 (x) y una F2XM1 de instrucciones x86 hacer exponenciación. F2XM1 requiere un argumento en el rango [-1,1], por lo que deberá agregar algún código intermedio para extraer la parte entera y el resto, exponer el resto, usar FSCALE para escalar el resultado con una potencia adecuada de 2.

+2

+1 ¡Una respuesta tan simple y elegante! – templatetypedef

+2

Super, gracias por compartir y tener un buen domingo. –

+2

Sé que este es un hilo viejo, pero aquí hay una implementación: [madwizard.org] (http://www.madwizard.org/programming/snippets?id=36) – Matth

15

OK, implementado en power(double a, double b, double * result); x 86 tal y como lo recomienda.

Código: 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

Podría recomendar que continúes e incluir ese código aquí, en tu respuesta? –

+1

Hecho, incluido. –

+1

Debe 'sub esp, 8' para mantenerlo alineado para empujar ebx. También puede cambiar tmp y ControlWord, p. '% define tmp DWORD [ebp-4]', por lo que está alineado. –