GCC inline ASM -- calling C functions from __asm__ blocks 
Author Message
 GCC inline ASM -- calling C functions from __asm__ blocks

I've read all of the GCC documentation on using inline assembly for
GCC, but none of it mentions how to call a C function from within
inline assembly.

I've tried several ways of doing it:

void function(void)
{
    printf("DOODIE!!!!!!!!!\n");

Quote:
}

That was the C function

With inline ASM I tried:

First:
    __asm__ ("lea %0,%%edx\n"
             "jmp %%edx\n"
    :
    : "function" (function())
    : "%edx");

This gives me a warning, "void value not ignored as it ought to be",
which I tried to remedy by having : "function" (function(void)) for
the input line, but that gives me more errors.

I also tried:
    __asm__ ("jmp %0\n"
    :
    : "function" (function())
    : "%edx");

Which also gives me "void value not ignored as it ought to be", also
giving me errors when tweaking every little thing (and even though
"%edx" isn't really clobbered, it {*filter*}es if I don't put it in there
-- but that's a GCC problem, not really an ASM issue right there),
such as "function" (&function()), "_function" (&function), etc...
blah.

Since GNU developers aren't too keen on documentation, I'm hoping some
ASM gurus here who've done this sort of coding might be able to give
some helpful advice on how to do this properly.



Wed, 03 Nov 2004 09:12:10 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> I've read all of the GCC documentation on using inline assembly
> for GCC, but none of it mentions how to call a C function from
> within inline assembly.

> I've tried several ways of doing it:

> void function(void)
> {
>     printf("DOODIE!!!!!!!!!\n");
> }

> That was the C function

> With inline ASM I tried:

> First:
>     __asm__ ("lea %0,%%edx\n"
>              "jmp %%edx\n"
>:
>: "function" (function())
>: "%edx");

I'm no GAS or GNU C expert, but what you have to do is,
first, check the calling convention of function() and adhere to
it, and 2nd, use call instead of jmp.

You _can_ use jmp instead of call under certain condition:
- the function call is the last thing the calling function does
- you clean up its stack frame before jumping
- the calling/returning conventions match
- if "c" calling convention is used, no. of args must match.
It's called "tail recursion elimination" and very useful for
implementing functional languages but probably not what
you are trying to do.

I think the easiest way to get where you want is, tell the
compiler not to inline the function, write a test function
that calls your function, say, 3 times (so you don't confuse
the calls with the test function's setup/cleanup code), then
have the compiler emit GAS and work from that.

ON



Wed, 03 Nov 2004 17:56:01 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

[...]
| I also tried:
|     __asm__ ("jmp %0\n"
|:
|: "function" (function())
|: "%edx");

Two problems:

a) You need to use CALL instead of JMP (unless you either never want the
function to return, or you're happy with it messing up the stack)
b) You need the address of the function (function), not its return value
(function()) -- this is a big difference but only a subtle change in C
syntax

Try this:

    __asm__("call *%0"
      :
      : "r" (function))

This isn't the most efficient way of doing it when function is absolute, but
it still works when you do this:

    the_address_of_a_function = calculate_address();
    __asm__("call *%0"
      :
      : "r" (the_address_of_a_function))

--
Tim Robinson
http://www.themoebius.org.uk/



Wed, 03 Nov 2004 20:56:01 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> I also tried:
>     __asm__ ("jmp %0\n"
>:
>: "function" (function())
>: "%edx");

> Which also gives me "void value not ignored as it ought to be", also
> giving me errors when tweaking every little thing (and even though
> "%edx" isn't really clobbered, it {*filter*}es if I don't put it in there
> -- but that's a GCC problem, not really an ASM issue right there),
> such as "function" (&function()), "_function" (&function), etc...
> blah.

The problem seems to be basic ANSI C knowledge.

Hint: you're not passing a function pointer to the assembly, but the
result of a function call (which is void in your case and thus gives
an error). If you just want to use the return value of the function that's
ok, but not when you want to actually call it. I would suggest to get a
good C book and read up about function pointers.

-Andi



Wed, 03 Nov 2004 20:56:01 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks
I don't know for sure, but what if you do a
"call _function", with _function being the symbol of the function name.
This of course only works if the function symbol is C. else you need to make
the function extern C.
Of course I don't know if this is how GCC inline asm supports it.

Mike



Quote:
> I've read all of the GCC documentation on using inline assembly for
> GCC, but none of it mentions how to call a C function from within
> inline assembly.

> I've tried several ways of doing it:

> void function(void)
> {
>     printf("DOODIE!!!!!!!!!\n");
> }

> That was the C function

> With inline ASM I tried:

> First:
>     __asm__ ("lea %0,%%edx\n"
>              "jmp %%edx\n"
>:
>: "function" (function())
>: "%edx");

> This gives me a warning, "void value not ignored as it ought to be",
> which I tried to remedy by having : "function" (function(void)) for
> the input line, but that gives me more errors.

> I also tried:
>     __asm__ ("jmp %0\n"
>:
>: "function" (function())
>: "%edx");

> Which also gives me "void value not ignored as it ought to be", also
> giving me errors when tweaking every little thing (and even though
> "%edx" isn't really clobbered, it {*filter*}es if I don't put it in there
> -- but that's a GCC problem, not really an ASM issue right there),
> such as "function" (&function()), "_function" (&function), etc...
> blah.

> Since GNU developers aren't too keen on documentation, I'm hoping some
> ASM gurus here who've done this sort of coding might be able to give
> some helpful advice on how to do this properly.



Thu, 04 Nov 2004 01:38:59 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks
You can use this:

void function(void)
{
    printf("DOODIE!!!!!!!!!\n");

Quote:
}

/* Code */
__asm__ ("call function \n\t"); /* Call function()*/
/* More code */
---------------------------------

?Sistemas Operativos? ?Vistala!
http://www.arrakis.es/~jespejo
---------------------------------


Thu, 04 Nov 2004 01:39:09 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> Try this:

>     __asm__("call *%0"
>:
>: "r" (function))

Ah, since I posted my original question last night I figured out to
use 'call' instead of 'jmp', and to specify the function's name only
without the brackets (I would've known to do that if I was a bit more
awake at the time :])-- but I still couldn't figure out why the GCC
compiler kept translating the function into "$_function__Fv" like it
was a hard-coded value ... so I needed a * before the parameter.

Well it works now, thanks !



Thu, 04 Nov 2004 02:55:53 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> a) You need to use CALL instead of JMP (unless you either never want the
> function to return, or you're happy with it messing up the stack)
> b) You need the address of the function (function), not its return value
> (function()) -- this is a big difference but only a subtle change in C
> syntax

> Try this:

>     __asm__("call *%0"
>:
>: "r" (function))

With "i" or "g" gcc would fill in the function label as needed.
Then the * is not needed and it would be shorter.

In addition unless the function has special calling conventions and
saves all registers he needs to specify what registers it clobbers too

On the other hand usually the only reason for calling functions from
inline assembly are special calling conventions, e.g. when one doesn't
want to disturb the register allocation of the main function just for
some infrequently called slow path. Using a stub for a function with
callee saved registers only can be a nice alternative there.

-Andi



Thu, 04 Nov 2004 02:55:57 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

>Since GNU developers aren't too keen on documentation,

Amen

Quote:
> I'm hoping some
>ASM gurus here who've done this sort of coding might be able to give
>some helpful advice on how to do this properly.

The best advice I can offer is "don't use inline assembly with GCC".
Write your functions with a separate assembler can call them as
external functions.

GCC's in-line assembly syntax changes on a frequent enough basis
to really{*filter*}you off if you have to maintain your code.  Also, in-line
assembly syntax is about one-tenth as readable as standard assembly
code.  Worse, GCC doesn't have a problem at all converting single
instructions you specify into a sequence of instructions, reallocating
registers, stuff like that.  If GCC is doing this to your assembly code,
you might question why even write assembly in the first place (note that
what GCC does is orders of magnitude worse than MASM translating
an LEA instruction into a MOV or something similar).
Randy Hyde



Thu, 04 Nov 2004 05:56:03 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> GCC's in-line assembly syntax changes on a frequent enough basis
> to really{*filter*}you off if you have to maintain your code.

Can you give *one* example of such "frequent syntax changes" ?

---
Joe Leherbauer             Leherbauer at telering dot at



Thu, 04 Nov 2004 16:55:59 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> GCC's in-line assembly syntax changes on a frequent enough basis
> to really{*filter*}you off if you have to maintain your code.  Also, in-line
> assembly syntax is about one-tenth as readable as standard assembly
> code.  Worse, GCC doesn't have a problem at all converting single

Given. gcc 3.1 has named arguments at least which makes them
somewhat better.

        asm("movl %[input],%[output]" : [output] "m" (var) : [input] "i" (1));

The advantage of gcc complicated syntax over others is first that it
keeps the compiler portale because it doesn't require it to contain
a full assembler just to find out what registers are clobbered by
the inline assembly (needed e.g. by the Microsoft/Watcom syntax)
and in addition they are much friendlier to the optimizer because
you tell it what it needs to know to optimize them.

Quote:
> instructions you specify into a sequence of instructions, reallocating
> registers, stuff like that.  If GCC is doing this to your assembly code,

If you want to allocate registers by hand perhaps you shouldn't use a C
compiler;)

gcc just copies the assembly instruction literally to the output and doesn't
parse them except for the % escapes.

I guess you're confused about the input/output parameters. If you
don't want gcc to use registers for these you give the right constraint
(like "m" for memory or "i" for immediate or "g" for any addressing mode or
some others, see the gcc manual)

For best generated code you should never hardcode registers in the inline
assembly, but instead just let the compiler assign one for you.

-Andi



Fri, 05 Nov 2004 01:55:58 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:


>> GCC's in-line assembly syntax changes on a frequent enough basis
>> to really{*filter*}you off if you have to maintain your code.

>Can you give *one* example of such "frequent syntax changes" ?

Personally, I can't because I don't use inline assembly.
However, subscribe to the Linux Assembly mailing list and you
get all sorts of examples.
Randy Hyde


Sat, 06 Nov 2004 01:56:01 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:


>> GCC's in-line assembly syntax changes on a frequent enough basis
>> to really{*filter*}you off if you have to maintain your code.  Also, in-line
>> assembly syntax is about one-tenth as readable as standard assembly
>> code.  Worse, GCC doesn't have a problem at all converting single

>Given. gcc 3.1 has named arguments at least which makes them
>somewhat better.

>        asm("movl %[input],%[output]" : [output] "m" (var) : [input] "i"
(1));

>The advantage of gcc complicated syntax over others is first that it
>keeps the compiler portale because it doesn't require it to contain
>a full assembler just to find out what registers are clobbered by
>the inline assembly (needed e.g. by the Microsoft/Watcom syntax)
>and in addition they are much friendlier to the optimizer because
>you tell it what it needs to know to optimize them.

But in doing so, it eliminates nearly every reason for using assembly
in the first place.  Indeed, I can only think of one place where GCC's
in-line assembly is actually useful (see below).  Perhaps you can
suggest others?

Quote:

>> instructions you specify into a sequence of instructions, reallocating
>> registers, stuff like that.  If GCC is doing this to your assembly code,

>If you want to allocate registers by hand perhaps you shouldn't use a C
>compiler;)

Then again, why even use assembly at all?
Granted, there are a few machine instructions that have semantics
that aren't available in C/C++ and maybe that *one* instruction is
all that you need, but playing games with in-line assembly as GCC
does almost completely eliminates the whole purpose of using
assembly in the first place (getting control over the code).

Quote:

>gcc just copies the assembly instruction literally to the output and
doesn't
>parse them except for the % escapes.

>I guess you're confused about the input/output parameters. If you
>don't want gcc to use registers for these you give the right constraint
>(like "m" for memory or "i" for immediate or "g" for any addressing mode or
>some others, see the gcc manual)

>For best generated code you should never hardcode registers in the inline
>assembly, but instead just let the compiler assign one for you.

I love that last statement.  I understand what you're trying to say, but I
can't
help but read it as "the compiler is smarter about register allocation than
a human" which, of course, will raise some eyebrows on clax.

My feeling is that 95% of the time, there's no execuse for using
in-line assembly and the 5% of the time that can be justified (i.e.,
to do that one asm statement that can't be done in C) it's probably
a better idea to rethink your program's organization and write
the whole function in assembly rather than one statement.

I've seen a lot of Linux kernel code that uses macros to emit
in-line assembly to do things like BSR and BSF, etc., and the
use of those macros almost always creates a situation where
the code is less efficient than had they coded the surrounding
statements in pure assembly (of course, Linux needs to be
portable, so they have no choice but to sacrifice efficiency in
exchange for a whole lot less assembly, but this is the example
that immediately comes to mind).

If you're going to follow all the rules about letting GCC allocate
the registers for you and convert single instructions to multiple
instructions, etc., you may as well code in p-code or in java-code
and let the JIT do the translation for you :-)
Randy Hyde



Sat, 06 Nov 2004 01:56:06 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:

> >For best generated code you should never hardcode registers in the inline
> >assembly, but instead just let the compiler assign one for you.

> I love that last statement.  I understand what you're trying to say, but I
> can't
> help but read it as "the compiler is smarter about register allocation than
> a human" which, of course, will raise some eyebrows on clax.

It does when there is enough surrounding C around it. When there isn't
then you shouldn't use inline assembly but just write the whole function
in assembly.

Also often when you write assembly it doesn't actually matter what the
actual registers are. It just matters that thing X is always in the register
Y, but you do not really care what Y is just that it stays constant over
the runtime of your code. gcc gives you that.

Quote:
> My feeling is that 95% of the time, there's no execuse for using
> in-line assembly and the 5% of the time that can be justified (i.e.,
> to do that one asm statement that can't be done in C) it's probably
> a better idea to rethink your program's organization and write
> the whole function in assembly rather than one statement.

There are lots of instructions that are efficient in assembly, but
cannot be easily or efficiently done in pure C. Requiring a costly
function call would offset their speed advantage again and would
be especially silly if it is only one or two instructions.

Examples to the contrary:

- Locking: needs inline assembly for atomic operations. You *definitely*
do not want a function call for every lock, that would make the uncontended
lock case far slower than they need to be.
- Atomic operations: (lock inc .. ; lock dec ; cmpxchg). etc.
Same rationale; you definitely do not want a function call for every
atomic_add.
- Access to thread local data via %fs,%gs prefixes.
Basically same thing.
[Dos compilers often support that natively, but gcc does not so ones
has to use inline assembly for it]
- ntohl() - bswap
Same thing again. Compile your favourite TCP/IP stack with a function call
for each ntohl and see how it'll slow it down.
- outb(),inb() to access IO ports from C.
- FSIN, FSQRT
- CLI, STI when writing device driver code.
- bit operations (BSF etc.)
- ROL, ROR
(important for some cryptographic algorithms; gcc actually detects
them for some ways to code them in C, but not for all so often inline
assembly is still needed)

...

-Andi



Sat, 06 Nov 2004 04:56:46 GMT  
 GCC inline ASM -- calling C functions from __asm__ blocks

Quote:


>Examples to the contrary:

>- Locking: needs inline assembly for atomic operations. You *definitely*
>do not want a function call for every lock, that would make the uncontended
>lock case far slower than they need to be.
>- Atomic operations: (lock inc .. ; lock dec ; cmpxchg). etc.
>Same rationale; you definitely do not want a function call for every
>atomic_add.
>- Access to thread local data via %fs,%gs prefixes.
>Basically same thing.
>[Dos compilers often support that natively, but gcc does not so ones
>has to use inline assembly for it]
>- ntohl() - bswap
>Same thing again. Compile your favourite TCP/IP stack with a function call
>for each ntohl and see how it'll slow it down.
>- outb(),inb() to access IO ports from C.
>- FSIN, FSQRT
>- CLI, STI when writing device driver code.
>- bit operations (BSF etc.)
>- ROL, ROR
>(important for some cryptographic algorithms; gcc actually detects
>them for some ways to code them in C, but not for all so often inline
>assembly is still needed)

Much of what you're saying is true if you write a function
to replace a single machine instructions (duh...).
The point is to replace a larger block of C/C++ code
with well-written assembly.  Sorry I did not make that clear.
All of the examples you've given above, btw, fall into
that category that I claimed in-line assembly was
acceptable for -- using exactly one machine instruction
where C doesn't provide the capability you need (or is
too grossly inefficient to consider).

BTW, CLI and STI are bad choices when writing
device driver code -- even in assembly language.
There are too many problems with multiprocessor
systems out there that CLI/STI don't solve.
Randy Hyde



Sun, 07 Nov 2004 03:55:56 GMT  
 
 [ 15 post ] 

 Relevant Pages 

1. GCC inline ASM -- calling C functions from __asm__

2. porting inline Watcom asm to MSVC inline asm

3. gcc inline asm, can't do even simple things :-(

4. On inline asm in gcc

5. Help with gcc inline floating point asm

6. Inline asm syntax (gcc)

7. GCC inline asm question i386

8. inline asm in using gcc under linux 2.0.0

9. Inline asm with gcc on Linux.

10. Inline asm in GCC

11. Trying to use gcc inline asm correctly

12. GCC inline asm i386

 

 
Powered by phpBB® Forum Software