2011-01-09 114 views
26

我正在尋找x86 Assembly中的pow(real, real)的實現。另外我想了解算法的工作原理。如何在x86中使用pow(real,real)

+0

您正在使用的x87或SSE? – 2011-01-09 09:28:51

+0

glibc的`pow()`函數的實現是[在sysdeps/ieee754/dbl-64/e_pow.c]中(http://repo.or.cz/glibc.git/blob/HEAD:/sysdeps/ieee754/ DBL-64/e_pow.c)。它使用FP位模式的一些整數檢查,並且一些FP相乘並相加,但不使用任何特殊的x87指令。對於x86-64,它被編譯爲`__ieee754_pow_sse2()`([通過包含它的代碼](http://repo.or.cz/glibc.git/blob/455d6e4373c81da49892d39f33dc312b0c54097d:/sysdeps/x86_64/fpu/ multiarch/e_pow.c))。無論如何,x87並不是在現代CPU上實現它的最佳方式。 – 2016-09-19 02:28:37

+0

我假設glibc的代碼要麼比x87更準確,要麼更快。可能兩者,但也許只是更準確(正確舍入到最近)。雖然它沒有使用循環,並且單步執行指令,但對於pow(1.175,33.75),沒有*那麼多。 FYL2X在現代CPU上是一個非常緩慢的指令(約100個週期),所以它不應該很難打敗它。 – 2016-09-19 02:30:57

回答

55

只要計算它爲2^(y*log2(x))

有一個x86指令FYL2X來計算y * ​​log2(x)和一個x86指令F2XM1來進行指數運算。 F2XM1需要[-1,1]範圍內的參數,因此您必須在中間添加一些代碼以提取整數部分和餘數,然後取其餘部分,使用FSCALE以2的適當冪來縮放結果。

15

好的,我按照您的建議在x86中實現了power(double a, double b, double * result);

代碼: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