2013-04-25 52 views
1

我想在程序集中编程一个对数函数,该函数需要两个参数:基数(32位整数)和值x(64位浮点数) 。Linux x86-64中的日志库bx程序集

我现在要做的这个想法是通过使用对数性质来使用FYL2X和FDIVP。由于log(base a)b =(log(base 10)b/log(base 10)a),所以我相信我可以实现对数函数。我应该如何在FPU的寄存器中设置它,因为我不能使用XMM?

回答

1

只要使用FPU指令和寄存器,XMM指令和寄存器与这些无关。

使用FLDFILD指令将浮点值和整数值加载到FPU寄存器堆栈中。

如果您没有CPU参考,现在是进入intel.com并下载它的好时机。免费。

1

因此,下面是一个评论示例,它计算二进制整数(与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 

希望得到这个帮助。

1

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