Inline assembler
lastmod 2018-08-17created 2015-04-0412 edits
Intro
In inline assembly, you need to specify the following.
- assembly code
- output variables
- input variables
- registers whose values change besides the output
-
__asm__ - Inline assembly keyword.
- This keyword can also be written as asm, but
asmis not defined when compiling with theansioption, so it is better to write__asm__.
-
__volatile__ - This keyword pins the inline assembly so that optimization does not remove or change it.
- According to the GCC manual, if the assembly is considered to have no side effects, an optimization may remove it or move it out of a loop.
- For example, if there is an output but the variable used as the output is never used afterward, the compiler assumes the inline assembly has no effect on program execution and removes it. Of course, if you specify the conditions precisely it will work correctly even without adding
__volaitile__, but it sometimes goes wrong in unexpected ways, so it is better to think carefully when writing inline assembly and add__volatile__.
-
asms - Assembly string enclosed in double quotes. Inside the string, input and output arguments can be used in the form
%n, and after the arguments are substituted they appear as-is in the compiled assembly.
-
output - A comma-separated list of "constraint"(variable) entries, each representing an output argument used in the inline assembly.
-
input - Same form as output, and represents the input arguments.
-
clobber - A comma-separated list of register names enclosed in double quotes, representing registers that do not appear in input or output but whose values change as a result of running the assembly.
Note that ouput, input, and clobber can be omitted from the end if they are empty. However, when a preceding parameter is empty, it must be marked with :.
Example
An example that actually uses input and output is shown below.
int test_and_set_bit(int nr, volatile unsigned * addr)
{
int oldbit;
__asm__ __volatile__(
"lock; btsl %2,%1\n\tsbbl %0,%0"
:"=r" (oldbit),"=m" (*addr)
:"r" (nr));
return oldbit;
}
Simple example
Suppose we have the following code with all unnecessary code removed.
You can inspect the asm code with objdump1 as shown below.
_main:
0: 55 pushq %rbp
1: 48 89 e5 movq %rsp, %rbp
4: 31 c0 xorl %eax, %eax
6: c7 45 fc 00 00 00 00 movl $0, -4(%rbp)
d: c7 45 f8 0b 00 00 00 movl $11, -8(%rbp)
14: 5d popq %rbp
15: c3 retq
On line d, you can see the code that inserts 11 into rbp.
Inline asm code that changes the value of a to 20 can be applied as follows.
#include <stdio.h>
int main()
{
int a = 11;
__asm__ __volatile__ ("movl $20, -8(%rbp)");
printf("%d", a);
return 0;
}
When you run it, you can see that 20 is printed.
See also
Favorite site
References
Pages that link here