MIPS组装中的Taylor系列 [英] Taylor Series in MIPS assembly

查看:138
本文介绍了MIPS组装中的Taylor系列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试计算泰勒级数

I'm trying to calculate the Taylor Series

1 + x + x 2 /2! + x 3 /3! + ... + x 10 /10!.

1 + x + x2 / 2! + x3 / 3! + ... + x10 / 10!.

我的程序每次都给我无限,我是MIPS的新手.我只关心输入介于0到10之间(含0和10)的输入.当 n = 10时,我们在 x n / n!处停止我想出了什么:

My program gives me infinity every time, I'm brand new to MIPS. I am only concerned about the input when it is between 0 and 10, inclusive. we are stopping at xn/n! when n = 10. Heres what I came up with:

# A program to first, find the power of x^n and the factorial of n. x,n are both between 0-10 inclusive. Then it finds the taylor series
    .data
pr1:    .asciiz "Enter Float x: "

    .text
    .globl main
main: 
    la $a0, pr1     # prompt user for x
    li $v0,4        # print string
    syscall
    li $v0, 6       # read single 
    syscall         
    mtc1 $v0, $f0       # f0 <--- x

exponent:           # f0 --> x
    mul.s $f1, $f0, $f0     # f1 --> x^2
    mul.s $f2, $f1, $f0 # f2 --> x^3
    mul.s $f3, $f2, $f0 # f3 --> x^4
    mul.s $f4, $f3, $f0 # f4 --> x^5
    mul.s $f5, $f4, $f0 # f5 --> x^6
    mul.s $f6, $f5, $f0 # f6 --> x^7
    mul.s $f7, $f6, $f0     # f7 --> x^8
    mul.s $f8, $f7, $f0 # f8 --> x^9
    mul.s $f9, $f8, $f0 # f9 --> x^10
factorial:
        li $s0, 1       # n = 10
        li $t0, 1

        add $t0, $t0, $s0   # t0 = 2! = 2

        add $t1, $t0, $s0   # t1 = 3
        mul $t1, $t1, $t0   # t1 = 3! = 6

        add $t2, $t0, $t0   # t2 = 4
        mul $t2, $t2, $t1   # t2 = 4! = 24

        addi $t3, $t1, -1   # t3 = 5
        mul $t3, $t3, $t2   # t3 = 5! = 120

        add $t4, $t1, $zero # t4 = 6
        mul $t4, $t4, $t3   # t4 = 6! = 720

        addi $t5, $t1, 1    # t5 = 7
        mul $t5, $t5, $t4   # t5 = 7! = 5040

        add $t6, $t1, $t0   # t6 = 8
        mul $t6, $t6, $t5   # t6 = 8! = 40320

        add $t7, $t1, $t0
        addi $t7, $t7, 1    # t7 = 9
        mul $t7, $t7, $t6   # t7 = 9! = 362880

        mul $s1, $t0, 5     # s1 = 10
        mul $s1, $s1, $t7   # s1 = 10! = 3628800    

taylor:
    mtc1 $s0, $f10      # $f10 = 1
    cvt.s.w $f10, $f10  # convert to float
    add.s $f0, $f0, $f10    # = 1 + x

    mtc1 $t0, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f1   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^2/2!

    mtc1 $t1, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f2   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x +.. + x^3/3!

    mtc1 $t2, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f3   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x +..+ x^4/4!

    mtc1 $t3, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f4   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^5/5!

    mtc1 $t4, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f5   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^6/6!

    mtc1 $t5, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f6   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^7/7!

    mtc1 $t6, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f7   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^8/8!

    mtc1 $t7, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f8   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^9/9!

    mtc1 $s1, $f10      # move n! to cp1
    cvt.s.w $f10, $f10  # convert to float 
    div.s $f10, $f10, $f9   # divide x^n/ n
    add.s $f0, $f0, $f10    # = 1 + x + x^10/10!
end:
        mov.s $f12, $f0     # argument
        li $v0, 2       # print float
        syscall         
        li $v0, 10
        syscall

推荐答案

首先,您会遇到一些错误:

To start with, you have a few bugs:

(1)正如Jester所说,您的读取浮动"系统调用存在一个错误.

(1) As Jester mentioned, your "read float" syscall had a bug.

(2)您正在计算factorial(n),但是泰勒余弦级数使用factorial(2n),因此它的增长速度更快.

(2) You're calculating factorial(n) but the Taylor cosine series uses factorial(2n), so it increases more quickly.

(3)[将要有正确的阶乘的[em]会出现的另一个问题]是您正在使用整数数学作为阶乘.当计算到10次迭代时,阶乘将溢出32位整数.对于10次迭代,我们最终得到[至少] factorial(18),它约为6.4e15(即 not 是否适合32个整数).使用整数数学时,阶乘(而不是稳定增加)将在值包装32位时振荡".

(3) Another problem you may be having [would be having with the correct factorial] is that you're using integer math for the factorial. When calculating to 10 iterations, the factorial will overflow a 32 bit integer. For 10 iterations, we end up with [at least] factorial(18) which is ~6.4e15 (i.e. does not fit in a 32 integer). With integer math, the factorial, instead of increasing steadily, will "oscillate" whenever the value wraps 32 bits.

我采用了稍微不同的方法.

I've taken a slightly different approach.

我创建了一个使用循环的解决方案,而不是预先计算所有事情(如您所完成的).这可能会或可能不会帮助您调试自己的实现,但是如果我不建议重构的话,我将不知所措.

Rather than pre-calculate everything [as you've done], I created a solution that uses a loop. That may or may not help you with debugging your own implementation, but I'd be remiss if I didn't recommend refactoring.

下面是用于循环实现的asm代码.我还使用了一个C版本来首先调试算法.还有一个带有一些调试语句的asm版本.

Below is asm code for the loop implementation. There is also a C version that I used to debug the algorithm first. There is also an asm version with some debug statements.

理论价格:

您正尝试使用泰勒级数求和/展开(至10次迭代)来计算cos.毕竟,公式确实使用求和"运算符.

You're trying to calculate cos using Taylor Series summation/expansion [to 10 iterations]. The formula does use a "summation" operator, after all.

您正在预先计算所有x^n项和所有阶乘项,并将它们放在不同的寄存器中.没问题,因为MIPS具有32个FP寄存器.但是,以双精度方式,我们必须使用两个寄存器,因此仅意味着16个数字.在某种程度上,您所做的等同于编译器执行循环展开".

You're precalculating all x^n terms and all factorial terms and putting them in different registers. That's fine as MIPS has 32 FP registers. But, with double precision, we'd have to use two registers, so that would mean only 16 numbers. In a way, what you did is the equivalent of a compiler doing "loop unrolling".

另一个问题是,很难跟踪所有这些寄存器.什么拥有什么价值.

Another issue is that it can be hard to keep track of all those registers. What is holding what value.

并且,假设问题在于使用20次迭代而不是10次迭代.我们可能会用完寄存器.实际上,这对于其他系列扩展可能是必需的,因为我们可能不会很快收敛.

And, suppose, the problem were to use 20 iterations instead of 10. We'd probably run out of registers. In practice, this might be necessary for other series expansions because we might not get convergence as quickly.

因此,我建议使用循环.每个功率项可以很容易地从上一个计算出来.同样,对于每个阶乘.

So, I'd recommend using a loop. Each power term is easily calculated from the previous one. Likewise, for each factorial.

使用循环方法的另一个优点是,我们可以监视术语值[cur](它越来越小),而不是使用固定的迭代次数,并且它的变化小于一定量[或小于该数量](例如,对于双精度,为1e-14),我们可以停下来,因为我们的值不会比浮点格式[和硬件]为我们提供的精度更好.

Another advantage to using the loop approach is that rather than using a fixed number of iterations, we can monitor the term value [cur] (which is getting smaller and smaller) and if it changes by less than a certain amount [or is smaller than that amount] (e.g. for double precision, 1e-14) we can stop because our values won't get any better than the precision our floating point format [and hardware] affords us.

注意:下面没有显示 ,但是易于实现.

Note: This is not shown below but is easy enough to implement.

这是asm版本.注释中使用的变量名称是指C代码中使用的变量名称(此后).

Here's the asm version. The variable names used in the comments refer to the variable names used in the C code [which follows afterward].

# A program to calculate cos(x) using taylor series
    .data
pr1:        .asciiz     "Enter Float x: "
sym_fnc:    .asciiz     "cos(x): "
nl:         .asciiz     "\n"

    .text
    .globl  main

main:
    li      $s7,0                   # clear debug flag #+

    # prompt user for x value
    li      $v0,4                   # print string
    la      $a0,pr1                 # prompt user for x
    syscall

    # read user's x value
    li      $v0,6                   # read float
    syscall

    jal     qcos

    la      $a0,sym_fnc             # string
    jal     prtflt

    li      $v0,10
    syscall

# qcos -- calculate cosine
#
# RETURNS:
#   f0 -- cos(x)
#
# arguments:
#   f0 -- x value
#
# registers:
#   f2 -- x value
#   f4 -- sum
#   f6 -- xpow (x^n)
#   f8 -- n2m1
#   f10 -- factorial (nfac)
#   f12 -- RESERVED (used in pflt)
#   f14 -- current term
#   f16 -- x^2
#
#   f18 -- a one value
#
#   t0 -- zero value
#   t1 -- one value
#
#   t6 -- negation flag
#   t7 -- iteration count
qcos:
    move    $s0,$ra                 # save return address
    mov.s   $f2,$f0                 # save x value

    mul.s   $f16,$f2,$f2            # get x^2

    li      $t0,0                   # get a zero
    li      $t1,1                   # get a one

    li      $t6,1                   # start with positive term

    # xpow = 1
    mtc1    $t1,$f6                 # xpow = 1
    cvt.s.w $f6,$f6                 # convert to float

    # n2m1 = 0
    mtc1    $t0,$f8                 # n2m1 = 0
    cvt.s.w $f8,$f8                 # convert to float

    # nfac = 1
    mtc1    $t1,$f10                # nfac = 1
    cvt.s.w $f10,$f10               # convert to float

    # get a one value
    mtc1    $t1,$f18                # onetmp = 1
    cvt.s.w $f18,$f18               # convert to float

    # zero the sum
    mtc1    $t0,$f4                 # sum = 0
    cvt.s.w $f4,$f4                 # convert to float

    li      $t7,10                  # set number of iterations

cosloop:

    div.s   $f14,$f6,$f10           # cur = xpow / nfac

    # apply the term to the sum
    bgtz    $t6,cospos              # do positive? yes, fly
    sub.s   $f4,$f4,$f14            # subtract the term
    b       cosneg

cospos:
    add.s   $f4,$f4,$f14            # add the term

cosneg:

    subi    $t7,$t7,1               # bump down iteration count
    blez    $t7,cosdone             # are we done? if yes, fly

    # now calculate intermediate values for _next_ term

    # get _next_ power term
    mul.s   $f6,$f6,$f16            # xpow *= x2

    # go from factorial(2n) to factorial(2n+1)
    add.s   $f8,$f8,$f18            # n2m1 += 1
    mul.s   $f10,$f10,$f8           # nfac *= n2m1

    # go from factorial(2n+1) to factorial(2n+1+1)
    add.s   $f8,$f8,$f18            # n2m1 += 1
    mul.s   $f10,$f10,$f8           # nfac *= n2m1

    neg     $t6,$t6                 # flip sign for next time
    j       cosloop

cosdone:
    mov.s   $f0,$f4                 # set return value

    move    $ra,$s0                 # restore return address
    jr      $ra

# dbgflt -- debug print float number
dbgflt:
    bnez    $s7,prtflt
    jr      $ra

# dbgnum -- debug print int number
dbgnum:
    beqz    $s7,dbgnumdone
    li      $v0,1
    syscall

dbgnumdone:
    jr      $ra

# dbgprt -- debug print float number
dbgprt:
    beqz    $s7,dbgprtdone
    li      $v0,4
    syscall

dbgprtdone:
    jr      $ra

# prtflt -- print float number
#
# arguments:
#   a0 -- prefix string (symbol name)
#   f12 -- number to print
prtflt:
    li      $v0,4                   # syscall: print string
    syscall

    li      $v0,2                   # print float
    syscall

    li      $v0,4                   # syscall: print string
    la      $a0,nl                  # print newline
    syscall

    jr      $ra


这是C代码[它也有sin(x)的代码]:


Here's the C code [it also has code for sin(x)]:

// mipsqsin/mipstaylor -- fast sine/cosine calculation

#include <stdio.h>
#include <math.h>

#define ITERMAX     10

// qcos -- calculate cosine
double
qcos(double x)
{
    int iteridx;
    double x2;
    double cur;
    int neg;
    double xpow;
    double n2m1;
    double nfac;
    double sum;

    // square of x
    x2 = x * x;

    // values for initial terms where n==0:
    xpow = 1.0;
    n2m1 = 0.0;
    nfac = 1.0;
    neg = 1;

    sum = 0.0;
    iteridx = 0;

    // NOTES:
    // (1) with the setup above, we can just use the loop without any special
    //     casing
    while (1) {
        // calculate current value
        cur = xpow / nfac;

        // apply it to sum
        if (neg < 0)
            sum -= cur;
        else
            sum += cur;

        // bug out when done
        if (++iteridx >= ITERMAX)
            break;

        // now calculate intermediate values for _next_ sum term

        // get _next_ power term
        xpow *= x2;

        // go from factorial(2n) to factorial(2n+1)
        n2m1 += 1.0;
        nfac *= n2m1;

        // now get factorial(2n+1+1)
        n2m1 += 1.0;
        nfac *= n2m1;

        // flip sign
        neg = -neg;
    }

    return sum;
}

// qsin -- calculate sine
double
qsin(double x)
{
    int iteridx;
    double x2;
    double cur;
    int neg;
    double xpow;
    double n2m1;
    double nfac;
    double sum;

    // square of x
    x2 = x * x;

    // values for initial terms where n==0:
    xpow = x;
    n2m1 = 1.0;
    nfac = 1.0;
    neg = 1;

    sum = 0.0;
    iteridx = 0;

    // NOTES:
    // (1) with the setup above, we can just use the loop without any special
    //     casing
    while (1) {
        // calculate current value
        cur = xpow / nfac;

        // apply it to sum
        if (neg < 0)
            sum -= cur;
        else
            sum += cur;

        // bug out when done
        if (++iteridx >= ITERMAX)
            break;

        // now calculate intermediate values for _next_ sum term

        // get _next_ power term
        xpow *= x2;

        // go from factorial(2n+1) to factorial(2n+1+1)
        n2m1 += 1.0;
        nfac *= n2m1;

        // now get factorial(2n+1+1+1)
        n2m1 += 1.0;
        nfac *= n2m1;

        // flip sign
        neg = -neg;
    }

    return sum;
}

// testfnc -- test function
void
testfnc(int typ,const char *sym)
{
    double (*efnc)(double);
    double (*qfnc)(double);
    double vale;
    double valq;
    double x;
    double dif;
    int iter;

    switch (typ) {
    case 0:
        efnc = cos;
        qfnc = qcos;
        break;

    case 1:
        efnc = sin;
        qfnc = qsin;
        break;

    default:
        efnc = NULL;
        qfnc = NULL;
        break;
    }

    iter = 0;
    for (x = 0.0;  x <= M_PI_2;  x += 0.001, ++iter) {
        vale = efnc(x);
        valq = qfnc(x);

        dif = vale - valq;
        dif = fabs(dif);

        printf("%s: %d x=%.15f e=%.15f q=%.15f dif=%.15f %s\n",
            sym,iter,x,vale,valq,dif,(dif < 1e-14) ? "PASS" : "FAIL");
    }
}

// main -- main program
int
main(int argc,char **argv)
{

    testfnc(0,"cos");
    testfnc(1,"sin");

    return 0;
}


这是我使用的带调试语句的asm版本.就像在C语言中一样,这是"printf调试".


Here's the asm version with debug statements I used. This is "printf debugging", just like in C.

或者,marsspim模拟器都具有内置的GUI调试功能.您可以通过单击一个按钮来单步执行代码.您可以实时显示所有寄存器值.

Alternatively, both the mars and spim simulators have builtin GUI debugging. You can single step the code by clicking on a single button. You can see a live display of all register values.

注意:就我个人而言,我更喜欢mars.这适用于mars,但我不知道spim是否支持.eqv伪操作.

Note: Personally, I prefer mars. This works with mars but I don't know if spim supports .eqv pseudo ops.

# A program to calculate cos(x) using taylor series

    .data
pr1:        .asciiz     "Enter Float x: "
sym_fnc:    .asciiz     "cos(x): "
nl:         .asciiz     "\n"

#+ddef  f2,x
    .eqv    fpr_x           $f2     #+
sym_x:      .asciiz     "x[f2]: "       #+
#+
#+ddef  f16,x2
    .eqv    fpr_x2          $f16    #+
sym_x2:     .asciiz     "x2[f16]: "     #+
#+
#+ddef  f4,sum
    .eqv    fpr_sum         $f4     #+
sym_sum:    .asciiz     "sum[f4]: "     #+
#+
#+ddef  f6,xpow
    .eqv    fpr_xpow        $f6     #+
sym_xpow:   .asciiz     "xpow[f6]: "    #+
#+
#+ddef  f8,n2m1
    .eqv    fpr_n2m1        $f8     #+
sym_n2m1:   .asciiz     "n2m1[f8]: "    #+
#+
#+ddef  f10,nfac
    .eqv    fpr_nfac        $f10    #+
sym_nfac:   .asciiz     "nfac[f10]: "   #+
#+
#+ddef  f14,cur
    .eqv    fpr_cur         $f14    #+
sym_cur:    .asciiz     "cur[f14]: "    #+
    #+

    .text
    .globl  main

main:
    #+dask
    la      $a0,dbgask              # prompt user #+
    li      $v0,4                   # print string #+
    syscall                         #+
    # get debug flag #+
    li      $v0,5                   #+
    syscall                         #+
    move    $s7,$v0                 #+
    .data                           #+
dbgask:     .asciiz     "Debug (0/1) ? "    #+
    .text                           #+
    #+

    # prompt user for x value
    li      $v0,4                   # print string
    la      $a0,pr1                 # prompt user for x
    syscall

    # read user's x value
    li      $v0,6                   # read float
    syscall

    jal     qcos

    la      $a0,sym_fnc             # string
    jal     prtflt

    li      $v0,10
    syscall

# qcos -- calculate cosine
#
# RETURNS:
#   f0 -- cos(x)
#
# arguments:
#   f0 -- x value
#
# registers:
#   f2 -- x value
#   f4 -- sum
#   f6 -- xpow (x^n)
#   f8 -- n2m1
#   f10 -- factorial (nfac)
#   f12 -- RESERVED (used in pflt)
#   f14 -- current term
#   f16 -- x^2
#
#   f18 -- a one value
#
#   t0 -- zero value
#   t1 -- one value
#
#   t6 -- negation flag
#   t7 -- iteration count
qcos:
    move    $s0,$ra                 # save return address
    mov.s   $f2,$f0                 # save x value
    #+dflt  x
    la      $a0,sym_x               #+
    mov.s   $f12,fpr_x              #+
    jal     dbgflt                  #+
    #+

    mul.s   $f16,$f2,$f2            # get x^2
    #+dflt  x2
    la      $a0,sym_x2              #+
    mov.s   $f12,fpr_x2             #+
    jal     dbgflt                  #+
    #+

    li      $t0,0                   # get a zero
    li      $t1,1                   # get a one

    li      $t6,1                   # start with positive term

    # xpow = 1
    mtc1    $t1,$f6                 # xpow = 1
    cvt.s.w $f6,$f6                 # convert to float

    # n2m1 = 0
    mtc1    $t0,$f8                 # n2m1 = 0
    cvt.s.w $f8,$f8                 # convert to float

    # nfac = 1
    mtc1    $t1,$f10                # nfac = 1
    cvt.s.w $f10,$f10               # convert to float

    # get a one value
    mtc1    $t1,$f18                # onetmp = 1
    cvt.s.w $f18,$f18               # convert to float

    # zero the sum
    mtc1    $t0,$f4                 # sum = 0
    cvt.s.w $f4,$f4                 # convert to float

    li      $t7,10                  # set number of iterations

cosloop:
    #+dprt  "cosloop: LOOP iter="
    la      $a0,dprt_1              #+
    jal     dbgprt                  #+
    .data                           #+
dprt_1:     .asciiz     "cosloop: LOOP iter="   #+
    .text                           #+
    #+
    #+dnum  $t7
    move    $a0,$t7                 #+
    jal     dbgnum                  #+
    #+
    #+dprt  "\n"
    la      $a0,dprt_2              #+
    jal     dbgprt                  #+
    .data                           #+
dprt_2:     .asciiz     "\n"            #+
    .text                           #+
    #+

    #+dflt  xpow
    la      $a0,sym_xpow            #+
    mov.s   $f12,fpr_xpow           #+
    jal     dbgflt                  #+
    #+
    #+dflt  nfac
    la      $a0,sym_nfac            #+
    mov.s   $f12,fpr_nfac           #+
    jal     dbgflt                  #+
    #+

    div.s   $f14,$f6,$f10           # cur = xpow / nfac
    #+dflt  cur
    la      $a0,sym_cur             #+
    mov.s   $f12,fpr_cur            #+
    jal     dbgflt                  #+
    #+

    # apply the term to the sum
    bgtz    $t6,cospos              # do positive? yes, fly
    #+dprt  "costerm: NEG\n"
    la      $a0,dprt_3              #+
    jal     dbgprt                  #+
    .data                           #+
dprt_3:     .asciiz     "costerm: NEG\n"    #+
    .text                           #+
    #+
    sub.s   $f4,$f4,$f14            # subtract the term
    b       cosneg

cospos:
    #+dprt  "costerm: POS\n"
    la      $a0,dprt_4              #+
    jal     dbgprt                  #+
    .data                           #+
dprt_4:     .asciiz     "costerm: POS\n"    #+
    .text                           #+
    #+
    add.s   $f4,$f4,$f14            # add the term

cosneg:
    #+dflt  sum
    la      $a0,sym_sum             #+
    mov.s   $f12,fpr_sum            #+
    jal     dbgflt                  #+
    #+

    subi    $t7,$t7,1               # bump down iteration count
    blez    $t7,cosdone             # are we done? if yes, fly

    # now calculate intermediate values for _next_ term
    #+dprt  "cosloop: CALC\n"
    la      $a0,dprt_5              #+
    jal     dbgprt                  #+
    .data                           #+
dprt_5:     .asciiz     "cosloop: CALC\n"   #+
    .text                           #+
    #+

    # get _next_ power term
    mul.s   $f6,$f6,$f16            # xpow *= x2

    # go from factorial(2n) to factorial(2n+1)
    add.s   $f8,$f8,$f18            # n2m1 += 1
    #+dflt  n2m1
    la      $a0,sym_n2m1            #+
    mov.s   $f12,fpr_n2m1           #+
    jal     dbgflt                  #+
    #+
    mul.s   $f10,$f10,$f8           # nfac *= n2m1
    #+dflt  nfac
    la      $a0,sym_nfac            #+
    mov.s   $f12,fpr_nfac           #+
    jal     dbgflt                  #+
    #+

    # go from factorial(2n+1) to factorial(2n+1+1)
    add.s   $f8,$f8,$f18            # n2m1 += 1
    #+dflt  n2m1
    la      $a0,sym_n2m1            #+
    mov.s   $f12,fpr_n2m1           #+
    jal     dbgflt                  #+
    #+
    mul.s   $f10,$f10,$f8           # nfac *= n2m1
    #+dflt  nfac
    la      $a0,sym_nfac            #+
    mov.s   $f12,fpr_nfac           #+
    jal     dbgflt                  #+
    #+

    neg     $t6,$t6                 # flip sign for next time
    j       cosloop

cosdone:
    mov.s   $f0,$f4                 # set return value

    move    $ra,$s0                 # restore return address
    jr      $ra

# dbgflt -- debug print float number
dbgflt:
    bnez    $s7,prtflt
    jr      $ra

# dbgnum -- debug print int number
dbgnum:
    beqz    $s7,dbgnumdone
    li      $v0,1
    syscall

dbgnumdone:
    jr      $ra

# dbgprt -- debug print float number
dbgprt:
    beqz    $s7,dbgprtdone
    li      $v0,4
    syscall

dbgprtdone:
    jr      $ra

# prtflt -- print float number
#
# arguments:
#   a0 -- prefix string (symbol name)
#   f12 -- number to print
prtflt:
    li      $v0,4                   # syscall: print string
    syscall

    li      $v0,2                   # print float
    syscall

    li      $v0,4                   # syscall: print string
    la      $a0,nl                  # print newline
    syscall

    jr      $ra


这是单个值的调试输出日志:


Here's the debug output log for a single value:

Debug (0/1) ? 1
Enter Float x: 0.123
x[f2]: 0.123
x2[f16]: 0.015129001
cosloop: LOOP iter=10
xpow[f6]: 1.0
nfac[f10]: 1.0
cur[f14]: 1.0
costerm: POS
sum[f4]: 1.0
cosloop: CALC
n2m1[f8]: 1.0
nfac[f10]: 1.0
n2m1[f8]: 2.0
nfac[f10]: 2.0
cosloop: LOOP iter=9
xpow[f6]: 0.015129001
nfac[f10]: 2.0
cur[f14]: 0.0075645004
costerm: NEG
sum[f4]: 0.9924355
cosloop: CALC
n2m1[f8]: 3.0
nfac[f10]: 6.0
n2m1[f8]: 4.0
nfac[f10]: 24.0
cosloop: LOOP iter=8
xpow[f6]: 2.2888667E-4
nfac[f10]: 24.0
cur[f14]: 9.536944E-6
costerm: POS
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 5.0
nfac[f10]: 120.0
n2m1[f8]: 6.0
nfac[f10]: 720.0
cosloop: LOOP iter=7
xpow[f6]: 3.4628265E-6
nfac[f10]: 720.0
cur[f14]: 4.8094813E-9
costerm: NEG
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 7.0
nfac[f10]: 5040.0
n2m1[f8]: 8.0
nfac[f10]: 40320.0
cosloop: LOOP iter=6
xpow[f6]: 5.2389105E-8
nfac[f10]: 40320.0
cur[f14]: 1.2993329E-12
costerm: POS
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 9.0
nfac[f10]: 362880.0
n2m1[f8]: 10.0
nfac[f10]: 3628800.0
cosloop: LOOP iter=5
xpow[f6]: 7.925948E-10
nfac[f10]: 3628800.0
cur[f14]: 2.1841789E-16
costerm: NEG
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 11.0
nfac[f10]: 3.99168E7
n2m1[f8]: 12.0
nfac[f10]: 4.790016E8
cosloop: LOOP iter=4
xpow[f6]: 1.1991168E-11
nfac[f10]: 4.790016E8
cur[f14]: 2.503367E-20
costerm: POS
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 13.0
nfac[f10]: 6.2270208E9
n2m1[f8]: 14.0
nfac[f10]: 8.7178289E10
cosloop: LOOP iter=3
xpow[f6]: 1.8141439E-13
nfac[f10]: 8.7178289E10
cur[f14]: 2.0809583E-24
costerm: NEG
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 15.0
nfac[f10]: 1.30767428E12
n2m1[f8]: 16.0
nfac[f10]: 2.09227885E13
cosloop: LOOP iter=2
xpow[f6]: 2.7446184E-15
nfac[f10]: 2.09227885E13
cur[f14]: 1.3117842E-28
costerm: POS
sum[f4]: 0.99244505
cosloop: CALC
n2m1[f8]: 17.0
nfac[f10]: 3.55687415E14
n2m1[f8]: 18.0
nfac[f10]: 6.4023735E15
cosloop: LOOP iter=1
xpow[f6]: 4.1523335E-17
nfac[f10]: 6.4023735E15
cur[f14]: 6.485616E-33
costerm: NEG
sum[f4]: 0.99244505
cos(x): 0.99244505

-- program is finished running --

这篇关于MIPS组装中的Taylor系列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆