1

我正在尝试在 Assembly 中编写一个对数函数,它接受两个参数:基数(32 位整数)和值 x(64 位浮点数)。

我目前必须这样做的想法是通过使用对数的属性来使用 FYL2X 和 FDIVP。

既然 log (base a) b = (log (base 10) b / log (base 10) a),那么我相信我可以实现一个对数函数。我应该如何在 FPU 的寄存器中设置它,因为我不能使用 XMM?

4

3 回答 3

1

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

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

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

于 2013-04-25T05:00:32.717 回答
1

FDIVP 除以st(0)st(1)这意味着,您必须先加载除数,然后计算对数,最后用 FDIVP 确定。

OTOH,函数FYL2X是 ST(1) = ST(1) * Log2(ST(0)); 其次是弹出st(0);

因此可以计算 log2(base) 的倒数并将其用作 FYL2X 的乘数。
此外,将其中一些值制成表格并使用以下内容可能是有意义的:

  shl bx, 3
  fld inv_log_base[bx]
  fld argument
  fyl2x
于 2013-04-25T15:12:05.307 回答
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

希望这有帮助。

于 2013-04-25T06:39:26.823 回答