sin()的总和导致asm(x87)

时间:2012-11-03 19:40:13

标签: assembly x87

我需要计算y(i) = sin(5*i)度的总和,其中i每次迭代都会增加。我需要在总和大于3之前计算总和,并在总和更大时找到i

使用下面的代码,我得到一个无限循环:

int main() {

float Sum=0;
long i=0;
long A=5;
long B=180;
int C=3;

 _asm{
   finit
 m1:
   inc i
   fldpi    ; load PI
   fmul i   ; PI * i 
   fmul A   ; PI * i * 5
   fdiv B   ; PI * i * 5 / 180 (value in degree)
   fsin ; sin(PI * i * 5 / 180)
   fadd Sum ; counter all lopps result
   ficom C  ; check if lower than 3 go to m1 
   jg m1
 }  
}

2 个答案:

答案 0 :(得分:4)

那里有一些问题。

  1. FMUL需要浮点参数,但是您传递了long
  2. FICOM仅设置FPU标志,您必须将它们移至CPU或使用FCOMI
  3. JG正在检查错误的标志,您需要检查进位标志。
  4. 您的代码会使浮点堆不平衡。
  5. 奖励:由于5 * PI / 180是常数,因此可以预先计算。

    您可以使用这样的代码(根据编译器的语法进行调整,这适用于gnu汇编程序):

    .intel_syntax noprefix
    .globl main
    main:
        sub esp, 16               # allocate space for i, sum and fmt
        mov dword ptr [esp+4], -1 # i
        fild dword ptr [limit]    # limit
        fldz                      # sum
    1:
        inc dword ptr [esp+4]     # i += 1
        fild dword ptr [esp+4]    # i
        fmul qword ptr [factor]   # i * factor
        fsin
        faddp                     # add to sum
        fcomi st, st(1)           # check if below limit
        jb 1b
        fstp qword ptr [esp+8]    # store on stack for printf
        fstp st(0)                # remove limit from fpu stack
        mov dword ptr [esp], offset fmt
        call printf
        add esp, 16               # clean up stack
        xor eax, eax              # return value
        ret
    
    .data
    factor: .double .08726646259971647884 # 5 * PI / 180
    limit: .int 3
    fmt: .string "i=%d sum=%g\n"
    

    See in operation.

答案 1 :(得分:0)

也许它是offtopic,但是使用简单的三角标识,你可以用一个简单的公式计算答案而不需要任何和值的循环:

i=ceil(acos(cos(t/2)-2*result_sum*sin(t/2))/t-0.5)

其中t是你的步角(5度),result_sum - 需要连续正弦的累计和(在你的情况下= 3)