feelfree
feelfree

Reputation: 11753

How could I obtain double accuracy cos function value with assembly codes?

I am now running the following assembly codes to get the cos function value:

float cosx( float radians ) {
    float result;

    __asm__ __volatile__ ( "fld %1;"
                            "fcos;"
                            "fstp %0;"
                            : "=m" (result)
                            : "m" (radians)
    ) ;
    return result ;
}

However, the above function can accept float argument, and the obtained function value is also float type. I was therefore writing a similar function that can accept double argument, and the returned function value is supposed to reach double accuracy as well:

double cosx( double radians ) {
    double result;

    __asm__ __volatile__ ( "fld %1;"
                            "fcos;"
                            "fstp %0;"
                            : "=m" (result)
                            : "m" (radians)
    ) ;
    return result ;
}

However, the second function has been proved not to work properly. I am therefore wondering what I should do in oder to make the second function work well. Thanks! I am using gcc for compiling the above codes.

EDIT: Here I will show why the second function does not work well:

int main() {
    float theta ;
    printf( "Enter theta  : " ) ;
    scanf( "%f", &theta ) ;  
     printf( "cosx(%f) = %lf\n", theta, cosx(theta) );  // line 5
     printf( "cosx(%f) = %lf\n", theta, cosx(double(theta)) ); // line 6

    return 0 ;
}

As we can see line5 and line6 invoke the first and the second function respectively. We expect they can have the same value. However, the output of the demonstration program is as follows:

Enter theta in  :  0.5236 // pi/6
cos(0.5236) = 0.8660;
cos(0.5236) = 0.0000;

Upvotes: 1

Views: 291

Answers (1)

JasonD
JasonD

Reputation: 16582

GCC is picky about the operand types:

__asm__ __volatile__ ( "fld %1;"
                        "fcos;"
                        "fstp %0;"
                        : "=m" (result)
                        : "m" (radians)

Should be:

__asm__ __volatile__ ( "fldl %1;"
                        "fcos;"
                        "fstpl %0;"
                        : "=m" (result)
                        : "m" (radians)

Though you could also write it as:

__asm__ __volatile__ ( "fldl %1;"
                      "fcos;"
                      : "=t" (result)
                      : "m" (radians)
                      ) ;

(and the same for the float version)

Upvotes: 1

Related Questions