user2752471
user2752471

Reputation: 454

Convert this embedded assembly code as to work with gcc

I am trying to convert this piece of code as to work with the AT&T assembly that g++ uses:

double sqrt13(double n)
{
__asm{
 fld n
 fsqrt
 }
}

Based on this link: https://ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html: I tried this:

double raiz (double n)
    __asm__ ( "fld n\n\t"
    "fsqrt\n\t" );

but I keep receiving:

/tmp/cc2AQhHj.s|662|Error: junk `n' after expression|

The same error messages happens four more times in other lines of this file

I downloaded a program called "intel2gas" and he says to me that the code shall be this one:

    __asm__ volatile__ (
    "fld %0\n"
    "fsqrt\n"
    :"=m"(n)
    :
    :"memory", "esi", "edi", "eax", "ebx", "ecx", "edx"
    );

putting it inside the function and trying to run it, I receive:

 |39|error: expected ‘(’ before ‘volatile__’|
|42|error: expected ‘)’ before ‘:’ token|
|45|error: ‘volatile__’ was not declared in this scope|

plus a |46|warning: no return statement in function returning non-void|

So, any suggestions?

Upvotes: 0

Views: 506

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 364358

intel2gas apparently doesn't implement MSVC's support for leaving a return value in EAX (or ST0) in asm and then falling off the end of a non-void function. MSVC treats this as an actual return value even when inlining the function containing the __asm block. In GNU C inline asm, register values are only outputs if you use output or read/write constraints.

This is why you get warning: no return statement in function returning non-void and broken code.

As @MichaelPetch points out, you should ask the compiler for the input floating-pointer number on the x87 FP register stack already, using a t constraint (Top of x87 stack).

double raiz (double n) {
    __asm__ ("fsqrt"
       : "+t"(n)          // read-write operand: top of x87 stack
    );
     return n;
}

asm volatile not needed: the asm block no side-effects that need to run even if output is unused, and the output is a pure function of the input. (Unless you're changing the x87 rounding mode or precision).

It's fine to let the compiler optimize it away, or CSE between multiple runs of it.

As a stand-alone function, this compiles (on Godbolt) to

# gcc8.2 -O3 -ffast-math -m32   uses x87 by default, not SSE2
_Z4raizd:
    fld     QWORD PTR [esp+4]
   # start of inline asm
    fsqrt
   # end of inline asm.
    ret

Upvotes: 4

Related Questions