Assembly 使用泰勒展开的sin(x)的汇编代码

Assembly 使用泰勒展开的sin(x)的汇编代码,assembly,x86,trigonometry,Assembly,X86,Trigonometry,在x86Linux中,如何使用Taylor扩展在汇编代码中实现sin(x) 它有两个用于计算近似sin(x)值的算法,包括C和汇编版本。当然,这是ARM组装,但是它的要点应该很容易翻译成x86或类似的版本。您没有说明是哪种CPU体系结构,所以我假设是x86 最简单(可能也是最低效)的方法是用RPN编写公式,它几乎可以直接映射到FPU指令 例如 代数公式:x-(x^3/3!)+(x^5/5!) RPN:x x x*x*3 2*/-x x*x*x*x*5 4*3*2*/+ 即: fld x fld

在x86Linux中,如何使用Taylor扩展在汇编代码中实现sin(x)


它有两个用于计算近似sin(x)值的算法,包括C和汇编版本。当然,这是ARM组装,但是它的要点应该很容易翻译成x86或类似的版本。

您没有说明是哪种CPU体系结构,所以我假设是x86

最简单(可能也是最低效)的方法是用RPN编写公式,它几乎可以直接映射到FPU指令

例如

代数公式:x-(x^3/3!)+(x^5/5!)

RPN:x x x*x*3 2*/-x x*x*x*x*5 4*3*2*/+

即:

fld x
fld x
fld x
fmul
fld x
fmul
fild [const_3]
fild [const_2]
fmul
fdiv
fsub
fld x
fld x
fmul 
fld x
fmul
fld x
fmul
fld x
fmul
fild [const_5]
fild [const_4]
fmul
fild [const_3]
fmul
fild [const_2]
fmul
fdiv
fadd
有一些明显的优化策略-

  • 而不是计算x,xxx, xxxxx等,对于每个术语,存储一个 “运行乘积”和乘法 每次x*x
  • 而不是 计算每个变量的阶乘 术语,执行相同的“运行产品”
下面是x86 FPU的一些注释代码,每条FPU指令后的注释显示该指令执行后的堆栈状态,堆栈顶部(st0)位于左侧,例如:

fldz ; 0
fld1 ; 1, 0
--剪断--


为什么??自从80387(大约1987年)处理器问世以来,已经有了FCOS和FSIN操作码

资料来源:

维基百科


演示场景中的私人朋友

有人给我指出了初学者数学的方向。。请这个链接让我做噩梦:)@dark-star1:看看-有一组关于微积分播放列表一半的近似函数的视频,其中有涉及到它的每一个数学层次的视频。几年前做过一次。。。问题是不使用
fsin
来计算SIN,因为要求使用泰勒级数来近似它。最好使用fcos和fsin,因为它们比任何可以在C/C++中创建并且可以在一个周期内执行的东西都快得多,而泰勒方法则慢得多。但这不是问题所在我问了这个问题。这个问题问如何使用泰勒级数(展开式)。这是一项家庭作业,要求人们自己动手。
long double LD_COS(long double __X)
{
    register long double __VALUE;

    __asm__ __volatile__(
        "fcos                  \n\t"
        : "=t" (__VALUE)
        : "0" (__X)
    );
    return __VALUE;
}

long double LD_SIN(long double __X)
{
    register long double __VALUE;

    __asm__ __volatile__(
        "fsin                  \n\t"
        : "=t" (__VALUE)
        : "0" (__X)
    );
    return __VALUE;
}
$ ./taylor-sine 0.5 1
0.4791666667
$ ./taylor-sine 0.5 5
0.4794255386
$ echo "s(0.5)"|bc -l
.47942553860420300027
long double LD_COS(long double __X)
{
    register long double __VALUE;

    __asm__ __volatile__(
        "fcos                  \n\t"
        : "=t" (__VALUE)
        : "0" (__X)
    );
    return __VALUE;
}

long double LD_SIN(long double __X)
{
    register long double __VALUE;

    __asm__ __volatile__(
        "fsin                  \n\t"
        : "=t" (__VALUE)
        : "0" (__X)
    );
    return __VALUE;
}