我想在程序集中編程一個對數函數,該函數需要兩個參數:基數(32位整數)和值x(64位浮點數) 。Linux x86-64中的日誌庫bx程序集
我現在要做的這個想法是通過使用對數性質來使用FYL2X和FDIVP。由於log(base a)b =(log(base 10)b/log(base 10)a),所以我相信我可以實現對數函數。我應該如何在FPU的寄存器中設置它,因爲我不能使用XMM?
我想在程序集中編程一個對數函數,該函數需要兩個參數:基數(32位整數)和值x(64位浮點數) 。Linux x86-64中的日誌庫bx程序集
我現在要做的這個想法是通過使用對數性質來使用FYL2X和FDIVP。由於log(base a)b =(log(base 10)b/log(base 10)a),所以我相信我可以實現對數函數。我應該如何在FPU的寄存器中設置它,因爲我不能使用XMM?
只要使用FPU指令和寄存器,XMM指令和寄存器與這些無關。
使用FLD
和FILD
指令將浮點值和整數值加載到FPU寄存器堆棧中。
如果您沒有CPU參考,現在是進入intel.com並下載它的好時機。免費。
因此,下面是一個評論示例,它計算二進制整數(與bsr
)的log2並通過FPU將其轉換爲十進制基數。代碼位於x86(i386)中,但可以輕鬆轉換爲x86-64(amd64)。
最棘手的部分是關於CW(FPU控制字)的操作。除此之外,如果習慣了「我的寄存器被用作堆棧」的事情,它或多或少是不言而喻的。
.text
.globl main
.type main, @function
main:
movl $1024, %eax ;; pushing the integer (1024) to analyze
bsrl %eax, %eax ;; bit scan reverse (give the smallest non zero index)
inc %eax ;; taking the 0th index into account
pushl %eax ;; saving the previous result on the stack
fildl (%esp) ;; loading the previous result to the FPU stack (st(0))
fldlg2 ;; loading log10(2) on the FPU stack
fmulp %st, %st(1) ;; multiplying %st(0) and %st(1) and storing result in %st(0)
;; We need to set the FPU control word to 'round-up'
;; (and not 'round-down' which is the default)
fstcw -2(%esp) ;; saving the old FPU control word
movw -2(%esp), %ax ;; storing the FPU control word in %ax
andw $0xf3ff, %ax ;; removing everything else
orw $0x0800, %ax ;; setting the proper bit to '1'
movw %ax, -4(%esp) ;; getting the value back to memory
fldcw -4(%esp) ;; setting the FPU control word to the proper value
frndint ;; rounding-up st(0)
fldcw -2(%esp) ;; restoring the original FPU control word
fistpl (%esp) ;; loading the final result to the stack
popl %eax ;; setting the return value to be our result
leave
ret
希望得到這個幫助。
FDIVP將st(0)
除以st(1)
,這意味着,您必須首先加載除數,然後計算對數,然後使用FDIVP進行最終確定。 (1)= ST(1)* Log2(ST(0));其中,ST(1)= ST其次是pop st(0);
因此可以計算log2(基數)的倒數,並將其用作FYL2X的乘數。
此外,它可能是有意義的製表其中的幾個值,並使用類似:
shl bx, 3
fld inv_log_base[bx]
fld argument
fyl2x