NO

Author Topic: Assembly  (Read 4772 times)

CLR

  • Guest
Assembly
« 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.

Code: [Select]
#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


Offline TimoVJL

  • Global Moderator
  • Member
  • *****
  • Posts: 2115
Re: Assembly
« Reply #1 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
Code: [Select]
_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: }
« Last Edit: November 12, 2016, 01:15:12 PM by TimoVJL »
May the source be with you

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Assembly
« Reply #2 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:
Code: [Select]
#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));
}
« Last Edit: November 12, 2016, 11:30:21 AM by jj2007 »

CLR

  • Guest
Re: Assembly
« Reply #3 on: November 12, 2016, 10:08:54 PM »
Thank you for the information TimoVJL & jj2007 it's now clear!!

Offline frankie

  • Global Moderator
  • Member
  • *****
  • Posts: 2113
Re: Assembly
« Reply #4 on: November 12, 2016, 10:30:35 PM »
The function is the same because of the trigonometric identity:
Quote
cos(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.  ;)
"It is better to be hated for what you are than to be loved for what you are not." - Andre Gide

CLR

  • Guest
Re: Assembly
« Reply #5 on: November 12, 2016, 11:17:46 PM »
The function is the same because of the trigonometric identity:
Quote
cos(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!

Offline jj2007

  • Member
  • *
  • Posts: 536
Re: Assembly
« Reply #6 on: November 13, 2016, 07:09:08 PM »
On a Core i5, milliseconds for 20 Mio calls:
Code: [Select]
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.

CLR

  • Guest
Re: Assembly
« Reply #7 on: November 14, 2016, 12:04:03 AM »
Yeah, I got

Code: [Select]
Asm:    160117.238655261        1094
C   :   160117.238655240        1484

Thanks.

Offline Mikl___

  • Member
  • *
  • Posts: 15
Re: Assembly
« Reply #8 on: December 13, 2016, 09:58:04 AM »
1)
2) Series expansion at
« Last Edit: December 13, 2016, 08:35:41 PM by Mikl___ »