This page was last modified 2009-03-11 13:26:25 by Puchu.Net user Choco
. (Show history)
Inline assembly is a way of having complete control how code is generated, and is very useful when optimizing functions or accessing hardware directly.
Insert inline assembly into your C/C++ functions by using a basic assembly template that look like this:
04 : "=r"(...), "=r"(...), ...
05 : "r"(...), "r"(...)
06 : "...");
Lines 0 to 3 are the assembly code, the logic of your function. Each line of assembly code ends in
Line 4 contains the output variables and line 5 are the input variables. In quotes you can specify constraint for the variables.
= indicate that the variables will be written to.
r tells compiler that we want to place the value to a register. In
( ) we insert the variable names that will be mapped.
Variables are mapped to
%? variables in the template in the order listed and
? is replaced by a number between 0 and 9. If input and output refer to the same variable, then instead of specifying
r for constraint, you will list the number that the output variable is mapped to.
Line 6 indicate registers that will be overwritten, so that compiler can take steps to preserve values before entering inline assembly code.
To convert the following C code into inline assembly:
z1 = ((z2 + z3) * 4433);
tmp2 = z1 + (z3 * -15137);
tmp3 = z1 + (z2 * 6270);
Here is one translation:
asm("addu %1, %4, %5;
li %0, 4433;
multu %1, %0;
li %0, -15137;
mult %5, %0;
add %2, %1 %0;
li %0, 6270;
multu %4, %0;
addu %3, %1, %0;
:"=r"(zz), "=r"(z1), "=r"(tmp2), "=r"(tmp3)
:"r"(z2), "r"(z3), "0"(zz)
zz is a temporary variable where we load constants to. The last variable on input line shows how to map input to output (in this case, by declaring
"0" to map to
Notes and Restrictions
- Only 10 registers can be mapped.
- If temporary variable is required, you need to map it by listing it in the output variables line.
- It seems that long blocks of inline assembly code runs slower than smaller blocks of the same code. You should experiment and confirm with the compiler you are using.
- Use debugger or compiler flags to generate disassembly so that you can check the results.
- If you are getting compiler warnings about AT registers being used, it's probably because you typed
$1 instead of
%1 in your assembly code, and it is clobbering up a reserved MIPS register used by assembler.
- You can specify assembler directives to enforce certain behavior. For example,
.set noreorder to make sure code is executed exactly in the order you specify.
- If you want to use instructions that is not supported by the compiler, you will need to create a macro (use
.endm directives), and within the macro use
.word to map out the opcode. This may not work with inline assembly, so check your results.
- Atomic operations can be achieved via special assembly instructions. For ARM, use
strex; for MIPS, use
- To generate code listing of mixed C/assembly, compile with
-g -Wa,-a,-ad flags.
- If the application breaks between recompile, or if inline functions do not work, then it is possible that the constraint modifiers need to be checked carefully.
- Dean Elsner, Jay Fenlason & friends. Using Assembly Language in Linux. May 19, 2008 <http://goodfellas.shellcode.com.ar/docz/asm/as.html>.
- Sandeep.S. GCC-Inline-Assembly-HOWTO. May 15, 2008 <http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html>.
- Keith Wesolowski. GCC inline assembly, part 2. February 26, 2009 <http://blogs.sun.com/wesolows/entry/gcc_inline_assembly_part_2>.
- Gary Shute. MIPS Instruction Coding. March 11, 2009 <http://www.d.umn.edu/~gshute/spimsal/talref.html>.
Document is accessible from
© 2002-2010 Sean Yang, Karen Yang, Don Yang and/or respective authors,
all rights reserverd.
This material may contain (biased) opinions,
inappropriate materials for numerous individuals,
work of other authors from the internet,
links that refer to other web documents and resources, or
origial work that cannot be use for personal or commercial purposes.
Please respect the work of original authors.