Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Direct C function call using GCC's inline assembly

If you want to call a C/C++ function from inline assembly, you can do something like this:

void callee() {}
void caller()
{
    asm("call *%0" : : "r"(callee));
}

GCC will then emit code which looks like this:

movl $callee, %eax
call *%eax

This can be problematic since the indirect call will destroy the pipeline on older CPUs.

Since the address of callee is eventually a constant, one can imagine that it would be possible to use the i constraint. Quoting from the GCC online docs:

`i'

An immediate integer operand (one with constant value) is allowed. This includes symbolic constants whose values will be known only at assembly time or later.

If I try to use it like this:

asm("call %0" : : "i"(callee));

I get the following error from the assembler:

Error: suffix or operands invalid for `call'

This is because GCC emits the code

call $callee

Instead of

call callee

So my question is whether it is possible to make GCC output the correct call.

like image 213
mtvec Avatar asked Aug 12 '10 11:08

mtvec


People also ask

Does C support inline assembly?

Inline assembly (typically introduced by the asm keyword) gives the ability to embed assembly language source code within a C program. Unlike in C++, inline assembly is treated as an extension in C.

What is __ asm __ in C?

The __asm keyword invokes the inline assembler and can appear wherever a C or C++ statement is legal. It cannot appear by itself. It must be followed by an assembly instruction, a group of instructions enclosed in braces, or, at the very least, an empty pair of braces.

What is inline assembly explain with an example?

In computer programming, an inline assembler is a feature of some compilers that allows low-level code written in assembly language to be embedded within a program, among code that otherwise has been compiled from a higher-level language such as C or Ada.

Does GCC automatically inline functions?

GCC automatically inlines member functions defined within the class body of C++ programs even if they are not explicitly declared inline . (You can override this with -fno-default-inline ; see Options Controlling C++ Dialect.)


1 Answers

I got the answer from GCC's mailing list:

asm("call %P0" : : "i"(callee));  // FIXME: missing clobbers

Now I just need to find out what %P0 actually means because it seems to be an undocumented feature...

Edit: After looking at the GCC source code, it's not exactly clear what the code P in front of a constraint means. But, among other things, it prevents GCC from putting a $ in front of constant values. Which is exactly what I need in this case.


For this to be safe, you need to tell the compiler about all registers that the function call might modify, e.g. : "eax", "ecx", "edx", "xmm0", "xmm1", ..., "st(0)", "st(1)", ....

See Calling printf in extended inline ASM for a full x86-64 example of correctly and safely making a function call from inline asm.

like image 65
mtvec Avatar answered Sep 28 '22 03:09

mtvec