Question

I need to calculate the sum of y(i) = sin(5*i) in degree, where i is increased every iteration. I need to calculate the sum before it becomes greater than 3, and find i when the sum is greater.

With the code below, I get an infinite loop:

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
 }  
}
Was it helpful?

Solution

A few problems there.

  1. FMUL expects floating point arguments, but you pass long.
  2. FICOM only sets FPU flags, you have to move them to CPU or use FCOMI.
  3. JG is checking wrong flags, you need to check the carry flag.
  4. Your code unbalances the floating point stack.

Bonus: Since 5*PI/180 is constant, you can precalculate that.

You could use some code like this (adjust for your compiler's syntax, this is for gnu assembler):

.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.

OTHER TIPS

Maybe it's offtopic, but using simple trigonometric identities, you can calculate answer without any loops for arbitrary sum value with a simple formula:

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

where t is your step angle (5 degrees), result_sum - needed acumulated sum of consecutive sines (=3 in your case)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top