曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 5152|回复: 0
打印 上一主题 下一主题

三角函数及指令

[复制链接]

4917

主题

5879

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34382
跳转到指定楼层
楼主
发表于 2010-3-9 01:03:00 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
FSIN 和 FCOS 指令

在 FPU 中,基本的三角函数都按照相同的方式实现。这些指令都使用一个隐含的源操作数,它位于 ST0 寄存器中。当函数完成时,结果存放在 ST0 寄存器中。

这些函数唯一难以处理的地方是它们都使用弧度作为源操作数的单位。如果正在处理的应用程序使用角度,那么在使用三角函数指令前,要将其转换为弧度,转换公式为:
radians = (degrees * pi) / 180
公式由来:因为 180 个角度对应 pi 弧度。

在 FPU 中,使用下面的代码片段可以完成上面的转换:
fsts  degree1             # 装角度值到 ST0
fidivs val180             # 除以 180,结果存在 ST0 中
fldpi                         # 装 pi 到 ST0,上面的除法结果被移到 ST1 中
fmul %st(1), %st(0)  #计算弧度值

下面程序演示 FSIN 和  FCOS 指令的应用:
.section .data
degree1:
    .float 90.0
val180:
    .int 180

.section .bss
    .lcomm radian1, 4
    .lcomm result1, 4
    .lcomm result2, 4

.section .text
.global _start
_start:
    nop
    finit
    flds degree1
    fidivs val180
    fldpi
    fmul %st(1), %st(0)
    fsts radian1
    fsin
    fsts result1
    flds radian1
    fcos
    fsts result2

    movl $1, %eax
    movl $0, %ebx
    int $0x80
在 gdb 里可以看到最终的计算结果:
(gdb) x/f &result1
0x80490bc <result1>:    1        # sin(90)
(gdb) x/f &result2
0x80490c0 <result2>:    -4.37113883e-08        #cos(90)
注:预先计算 pi/180 的值并且把它存储在 FPU 中要更有效率,因为这样就无需每次都计算这个值。

FSINCOS 指令
如果需要同时获得角的正弦值和余弦值可用FSINCOS 指令。这条指令先把正弦结果放到 ST0 中,然后把余弦结果压入堆栈,这样结果就是正弦值被放到了 ST1 ,而余弦值则存在 ST0。下面程序演示这条指令:
.section .data
degree1:
    .float 90.0
val180:
    .int 180

.section .bss
    .lcomm sinresult, 4
    .lcomm cosresult, 4

.section .text
.global _start
_start:
    nop
    finit
    flds degree1
    fidivs val180
    fldpi
    fmul %st(1), %st(0)
    fsincos
    fstps cosresult      #存完后弹出 ST0
    fsts sinresult

    movl $1, %eax
    movl $0, %ebx
    int $0x80
在 gdb 中可以看到结果:
(gdb) x/f &cosresult
0x80490b0 <cosresult>:    -2.71050543e-20
(gdb) x/f &sinresult
0x80490ac <sinresult>:    1
cosresult 的值并不精确的等于 0,但已经非常接近。sinresult 是正确的值 1。

正切和反正切指令 FPTAN 和 FPATAN
FPTAN 使用隐含在 ST0 中的操作数 (同样,角的单位必须是弧度,不能是角度)。正切值计算出来后存在 ST0 中,然后接着压入 1.0 到 FPU 堆栈,结果正切值被下移到 ST1 中,而 ST0 中的值为 1.0 。这样做是因为 Intel 要向下兼容 80287 FPU 协处理器写的应用程序,在那个时候还没有 FSIN 和 FCOS,计算这些值需要正切值的倒数。通过在FPTAN 指令之后使用简单的 FDIVR 指令,就可以计算出余切的值。

FPATAN 使用两个隐含的源操作数。它计算角值ST1/ST0的反正切值,入下图所示:

然后把结果存放在ST1中,然后弹出FPU堆栈,然后把值移动到ST0。

正切与余切的关系是互为倒数。
tan(x)=y       ---- 正切
arctan(y)=x 即 arctan(tan(x))=x ---- 反正切
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2024-5-14 12:43 , Processed in 0.060721 second(s), 22 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表