アセンブリで対数関数をプログラムしようとしています。この関数は、基数 (32 ビット整数) と値 x (64 ビット浮動小数点) の 2 つの引数を取ります。
私が現在これを行う必要があるアイデアは、対数の性質を使用して FYL2X と FDIVP を使用することです。
log (base a) b = (log (base 10) b / log (base 10) a) なので、対数関数を実装できると思います。XMMが使えないので、FPUのレジスタにどのように設定すればよいですか?
アセンブリで対数関数をプログラムしようとしています。この関数は、基数 (32 ビット整数) と値 x (64 ビット浮動小数点) の 2 つの引数を取ります。
私が現在これを行う必要があるアイデアは、対数の性質を使用して FYL2X と FDIVP を使用することです。
log (base a) b = (log (base 10) b / log (base 10) a) なので、対数関数を実装できると思います。XMMが使えないので、FPUのレジスタにどのように設定すればよいですか?
FDIVP は で除算st(0)
しst(1)
ます。つまり、最初に除数をロードし、次に対数を計算し、FDIVP でファイナライズする必要があります。
OTOH、関数FYL2X
は ST(1) = ST(1) * Log2(ST(0)) です。続いて pop st(0);
したがって、log2(base) の逆数を計算し、それを FYL2X の乗数として使用できます。
さらに、これらの値のいくつかを表にして、次のようなものを使用することはおそらく理にかなっています。
shl bx, 3
fld inv_log_base[bx]
fld argument
fyl2x
bsr
したがって、2 進整数の log2 を ( で) 計算し、FPU を介してそれを 10 進数に変換するコメント付きの例を次に示します。コードは 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
この助けを願っています。
FPU命令とレジスタを使用するだけで、XMM命令とレジスタはそれらとは何の関係もありません。
FLD
および命令を使用して、FILD
浮動小数点値と整数値を FPU レジスタ スタックにロードします。
CPU リファレンスがない場合は、今すぐ intel.com にアクセスしてダウンロードしてください。無料で。