Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use a macro in linux C inline assembly

I want to call an address that is determined by other configuration result. And that call is in an inline assembly.

Currently, it's like this and is manually modified:

asm volatile ("call 0xc0200c20\n\t");

My question is can I write it like this?

#define CALL_ADDR 0xC0200c20

asm volatile ("call CALL_ADDR\n\t");

Thanks!

like image 545
xiaogw Avatar asked Jun 30 '14 20:06

xiaogw


People also ask

How to use inline assembly language in C code?

6.47 How to Use Inline Assembly Language in C Code. The asm keyword allows you to embed assembler instructions within C code. GCC provides two forms of inline asm statements. A basic asm statement is one with no operands (see Basic Asm), while an extended asm statement (see Extended Asm) includes one or more operands.

How to write a macro in assembly language?

Writing a macro is another way of ensuring modular programming in assembly language. A macro is a sequence of instructions, assigned by a name and could be used anywhere in the program. In NASM, macros are defined with %macro and %endmacro directives. The macro begins with the %macro directive and ends with the %endmacro directive.

What is the difference between macros and inline functions in C++?

But there is risk in macros which can be dangerous when the argument is an expression. They can include multiple lines of code without trailing backlashes. Inline functions have their own scope for variables and they can return a value. Debugging code is easy in case of Inline functions as compared to macros.

How do I know if inline assembly will work with different processors?

If you have inline assembly that you want supported on different processors, use preprocessor macros to check which processor the code is being compiled for and to select the appropriate assembly code section. Future Performance Changes Inline assembly may be written expecting delays based upon a certain processor clock speed.


2 Answers

Just ordinary string concatenation should do the trick, with two wrapper macros to create a stringified version of the value:

#define QUAUX(X) #X
#define QU(X) QUAUX(X)

asm volatile ("call " QU(CALL_ADDR) "\n\t");
like image 142
Kerrek SB Avatar answered Sep 18 '22 01:09

Kerrek SB


Promoting my comment to an answer:

The P modifier for gcc's inline assembly operands stops the compiler from emitting 'constant-indicating prefixes' in the generated assembly code. See the linked reference for a more verbose explanation, quoting Linus.

If you've tried:

#define CALL_ADDR 12345678
asm volatile("call %0\n\t" :: "i"(CALL_ADDR));

you noticed you get an error from the assembler, because the generated code says call $12345678 and that's not valid assembly syntax. Using %P0 instead makes the compiler not emit the $ at the beginning, and it's fine.

There's no need to work with preprocessor string concatenation here - the disadvantage of that is, as you've found, that "nesting" (two levels of macros) is needed so that the CALL_ADDR is expanded before the concatenation is done.

like image 29
FrankH. Avatar answered Sep 19 '22 01:09

FrankH.