FPTAN Example x86

僤鯓⒐⒋嵵緔 提交于 2020-02-05 06:15:07

问题


According to Intel documentation, this is what FPTAN does:

Replace ST(0) with its approximate tangent and push 1 onto the FPU stack.

And this is a code I wrote in NASM:

section .data
    fVal: dd 4
    fSt0: dq 0.0
    fSt1: dq 0.0

section .text
    fldpi
    fdiv  dword[fVal]  ; divide pi by 4 and store result in ST(0).
    fptan
    fstp  qword[fSt0]  ; store ST(0)
    fstp  qword[fSt1]  ; store ST(1)

At this point the values of fSt0 and fSt1, I find are:

fSt0 = 5.60479e+044
fSt1 = -1.#IND

But, shouldn't fSt0 and fSt1 be both 1?


回答1:


As Michael Petch has already pointed out in a comment, you have a simple typo. Instead of declaring fVal as a floating-point value (as intended), you declared it as a 32-bit integer. Change:

fVal: dd 4

to:

fVal: dd 4.0

Then your code will work as intended. It is correctly written.

If you wanted to take an integer input, you could do it by changing your code to use the FIDIV instruction. This instruction will first convert an integer to a double-precision floating-point value, and then do the divide:

fldpi
fidiv  dword [fVal]    ; st(0) = pi / fVal
fptan                  ; st(0) = tan(st(0))
                       ; st(1) = 1.0
fstp   qword [fSt0]
fstp   qword [fSt1]

But because the conversion is required, this is slightly less efficient than if you had just given the input as a floating-point value.

Note that, if you were going to do this, it would be more efficient on certain older CPUs to break up the load so that it was done separately from the division—e.g.,

fldpi
fild   dword [fVal]
fdivp  st(1), st(0)    ; st(0) = pi / fVal
fptan                  ; st(0) = tan(st(0))
                       ; st(1) = 1.0
fstp   qword [fSt0]
fstp   qword [fSt1]

In other words, we break the FIDIV instruction apart into separate FILD (integer load) and FDIVP (divide-and-pop) instructions. This improves overlapping, and thus shaves off a couple of clock cycles from the execution speed of the code. (On newer CPUs, from AMD Family 15h [Bulldozer] and Intel Pentium II and later—there's no real advantage to breaking up FIDIV into FILD+FDIV; either way you write it should be equally performant.)

Of course, since everything you have here is a constant, and tan(pi/4) == 1, your code is equivalent to:

fld1
fld1

…which is what an optimizing compiler would generate. :-)



来源:https://stackoverflow.com/questions/44574993/fptan-example-x86

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!