Pelles C forum

C language => Beginner questions => Topic started by: CLR on November 11, 2016, 09:03:24 PM

Title: Assembly
Post by: CLR on November 11, 2016, 09:03:24 PM
I compiled a simple function in C with Optimizations:None and ran podump to see the generated assembly.

I need help understanding assembly of fx. I see there are two call ___sin but there is no call to cos. Any help appreciated.


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

double fx(double x)
{
return cos(x) + sin(x);
}

int main(void)
{
printf("%f\n", fx(M_PI_2));
}

podump /disasm main.obj

_fx:
  [00000000] 55                     push              ebp
  [00000001] 89E5                   mov               ebp,esp
  [00000003] 83EC10                 sub               esp,10
  [00000006] 6A01                   push              1
  [00000008] DD4508                 fld               qword ptr [ebp+8]
  [0000000B] 83EC08                 sub               esp,8
  [0000000E] DD1C24                 fstp              qword ptr [esp]
  [00000011] E800000000             call              ___sin
  [00000016] 83C40C                 add               esp,C
  [00000019] DD5DF8                 fstp              qword ptr [ebp-8]
  [0000001C] 6A00                   push              0
  [0000001E] DD4508                 fld               qword ptr [ebp+8]
  [00000021] 83EC08                 sub               esp,8
  [00000024] DD1C24                 fstp              qword ptr [esp]
  [00000027] E800000000             call              ___sin
  [0000002C] 83C40C                 add               esp,C
  [0000002F] DD5DF0                 fstp              qword ptr [ebp-10]
  [00000032] DD45F8                 fld               qword ptr [ebp-8]
  [00000035] DC45F0                 fadd              qword ptr [ebp-10]
  [00000038] 89EC                   mov               esp,ebp
  [0000003A] 5D                     pop               ebp
  [0000003B] C3                     ret

Title: Re: Assembly
Post by: TimoVJL on November 12, 2016, 10:57:43 AM
PellesC internal __sin function use second parameter 0 for sin and 1 for cos.

[00000006] 6A01                   push              1
...
[0000001C] 6A00                   push              0

With -fp:fast_fx:
7: {
8: return cos(x) + sin(x);
  [00000000] DD442404               fld               qword ptr [esp+4]
  [00000004] D9FF                   fcos             
  [00000006] DD442404               fld               qword ptr [esp+4]
  [0000000A] D9FE                   fsin             
  [0000000C] DEC1                   faddp             st(1),st
  [0000000E] C3                     ret               
9: }
Title: Re: Assembly
Post by: jj2007 on November 12, 2016, 11:19:59 AM
As Timo wrote already, _sin covers both cos and sin. You can watch it in the debugger: For both calls, the x value is in ST(0), but different values are returned.

Btw the compiler does really complicated stuff here. A simple fsincos would have done the job, too:#include <stdio.h>
#include <math.h>

double fxA(double x)
{
_asm {
fld x;
fsincos;
fadd;
}
}

double fxC(double x) {
return cos(x) + sin(x);
}

int main(void)
{
printf("Asm: \t%1.15f\n", fxA(45.0));
printf("C:  \t%1.15f\n", fxC(45.0));
}
Title: Re: Assembly
Post by: CLR on November 12, 2016, 10:08:54 PM
Thank you for the information TimoVJL & jj2007 it's now clear!!
Title: Re: Assembly
Post by: frankie on November 12, 2016, 10:30:35 PM
The function is the same because of the trigonometric identity:
Quotecos(x) = sin(x + PI/2)
When calculating the cosine the flag is used to add PI/2 to the argument and then compute the sinus.  ;)
Title: Re: Assembly
Post by: CLR on November 12, 2016, 11:17:46 PM
Quote from: frankie on November 12, 2016, 10:30:35 PM
The function is the same because of the trigonometric identity:
Quotecos(x) = sin(x + PI/2)
When calculating the cosine the flag is used to add PI/2 to the argument and then compute the sinus.  ;)

Very cool trick. Thanks!
Title: Re: Assembly
Post by: jj2007 on November 13, 2016, 07:09:08 PM
On a Core i5, milliseconds for 20 Mio calls:Asm: 160117.238655261 999
C   : 160117.238655240 1388


Pelles C has it's own implementation of sine and cosine. In this special case, it's a bit slower than the FPU. But test yourself, source is attached.
Title: Re: Assembly
Post by: CLR on November 14, 2016, 12:04:03 AM
Yeah, I got


Asm:    160117.238655261        1094
C   :   160117.238655240        1484


Thanks.
Title: Re: Assembly
Post by: Mikl___ on December 13, 2016, 09:58:04 AM
1) (https://latex.codecogs.com/gif.latex?sin%28x%29&plus;cos%28x%29%3D%5Csqrt%7B2%7D%5Ccdot%20sin%28x&plus;%5Cfrac%7B%5Cpi%7D%7B4%7D%29)
2) Series expansion at (https://latex.codecogs.com/gif.latex?x%3D0) (https://latex.codecogs.com/gif.latex?sin%28x%29&plus;cos%28x%29%3D1&plus;x-%5Cfrac%7Bx%5E%7B2%7D%7D%7B2%7D-%5Cfrac%7Bx%5E%7B3%7D%7D%7B6%7D&plus;%5Cfrac%7Bx%5E%7B4%7D%7D%7B24%7D&plus;O%28x%5E%7B5%7D%29)