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
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: }
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));
}
Thank you for the information TimoVJL & jj2007 it's now clear!!
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. ;)
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!
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.
Yeah, I got
Asm: 160117.238655261 1094
C : 160117.238655240 1484
Thanks.
1) (https://latex.codecogs.com/gif.latex?sin%28x%29+cos%28x%29%3D%5Csqrt%7B2%7D%5Ccdot%20sin%28x+%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+cos%28x%29%3D1+x-%5Cfrac%7Bx%5E%7B2%7D%7D%7B2%7D-%5Cfrac%7Bx%5E%7B3%7D%7D%7B6%7D+%5Cfrac%7Bx%5E%7B4%7D%7D%7B24%7D+O%28x%5E%7B5%7D%29)