根据英特尔的文档,这就是FPTAN所做的:
用其近似切线替换ST(0),并将1推到FPU堆栈上。
这是我在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)在这里,我发现fSt0和fSt1的值是:
fSt0 = 5.60479e+044
fSt1 = -1.#IND
但是,fSt0和fSt1不应该都是1吗
发布于 2017-06-16 00:42:27
正如Michael已经在评论中指出的那样,您有一个简单的错误。您没有将fVal声明为浮点值(如预期的那样),而是将其声明为32位整数。更改:
fVal: dd 4至:
fVal: dd 4.0然后,您的代码将按预期工作。它写得很正确。
如果要接受整数输入,可以通过更改代码以使用FIDIV指令来实现。该指令将首先将一个整数转换为一个双精度浮点值,然后执行以下除法:
fldpi
fidiv dword [fVal] ; st(0) = pi / fVal
fptan ; st(0) = tan(st(0))
; st(1) = 1.0
fstp qword [fSt0]
fstp qword [fSt1]但是由于转换是必需的,所以这比刚刚将输入作为浮点值提供的效率略低。
请注意,如果要这样做,在某些旧CPU上分解负载将更有效,以便将其与除法分离-例如,
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]换句话说,我们将FIDIV指令分解成单独的FILD (整数加载)和FDIVP (除法和pop)指令。这改善了重叠,从而减少了代码执行速度的几个时钟周期。(在较新的CPU上,来自AMD家族15h推土机和英特尔奔腾II及更高版本--将FIDIV分解为FILD+FDIV没有真正的优势;无论用哪种方式编写它,都应该具有同等的性能。)
当然,由于这里的所有内容都是常量,并且是tan(pi/4) == 1,所以您的代码相当于:
fld1
fld1…这就是优化编译器会产生的结果。:-)
https://stackoverflow.com/questions/44574993
复制相似问题