GCC Inline Assembly
Timeline
2025-09-27
init
Reference documentation:
Inline Assembly Language — embedding assembly code within C code.
Purpose:
- Optimization: optimize specific time-sensitive code.
- C code needs access to certain special instructions for special functionality, such as memory barrier instructions.
Two modes of inline assembly:
- Basic inline assembly
- Extended inline assembly
Basic Inline Assembly
Format:
1 | asm asm-qualifiers(AssemblerInstructions) |
asmkeyword: indicates this is a GNU extension.- Qualifiers:
volatile: typically not needed in basic inline assembly.inline: the asm assembly code will be as minimal as possible.
- Assembly code block (AssemblerInstructions):
- GCC treats the inline assembly as a string.
- GCC does not parse or analyze the inline assembly.
- Multiple assembly instructions need to be separated by
\n\t. - GCC’s optimizer may reorder assembly instructions. If you need to preserve order, use multiple inline assembly blocks.
Extended Inline Assembly
- Format:
asmkeyword: indicates this is a GNU extension.- Qualifiers (asm-qualifiers):
volatile: disables GCC optimization.inline: the asm assembly code will be as minimal as possible.goto: after the inline assembly, jump to a C label.
-
Output operands:
Describes C variables that can be modified within the instruction block, along with constraints.
- Each output constraint typically starts with
=, followed by a letter indicating the operand type, then the constraint for variable binding. - Output operands usually use
=or+as output constraints.=means the modified operand is write-only;+means it is read-write. - Output operands can be empty.
- Each output constraint typically starts with
1 | "=/+" + constraint modifier + variable |
Common constraint modifiers:
r: A register operand is allowed provided it is in a general register.
-
Input operands:
Describes C variables that can only be read within the instruction block, along with constraints.
- Input operand parameters are read-only. Do not attempt to modify input operand contents, because GCC assumes input operand contents are consistent before and after the inline assembly.
- You cannot use
=or+constraints in input operands; the compiler will report an error. - Input operands can be empty.
-
Clobbers:
- Assembly code may modify registers besides the output registers.
- If not communicated to the compiler, the compiler assumes these registers remain unchanged, potentially leading to errors or unpredictable behavior.
- Clobber also acts as a memory barrier (especially
"memory"), ensuring the compiler does not reorder or cache variables.
| Name | Purpose |
|---|---|
"x0", "x1", … |
General-purpose registers modified |
"cc" |
Condition code register (flags) modified |
"memory" |
Assembly accessed memory; ensures compiler flushes registers to memory and reloads |
"redzone" |
Using stack space in x86-64 redzone area |
"memory"tells GCC that the inline assembly modified memory values, forcing the compiler to flush all cached values before executing the assembly and reload them afterward — this prevents compiler reordering."cc"indicates the inline assembly modified status register flags.
- Do not list the stack pointer register (esp/rsp) in the clobber list.
- Do not duplicate output registers.
- The four types can be combined with commas.
- Instruction operand references:
%0corresponds to the first parameter in output/input operands,%1to the second, etc.
Output and Input Constraint Modifiers
Output and Input Constraint Modifiers — General
Output and Input Constraint Modifiers — ARM64
Assembly Symbolic Names Instead of % Prefix
%[name]→ reference a constraint variable.%w[name]→ reference the lower 32-bit register (e.g.,w0, w1).%x[name]→ reference the full 64-bit register (e.g.,x0, x1).
Experiment 1: Implementing a Simple memcpy Function
Pitfalls and Traps
- GDB cannot single-step through inline assembly.
- Output and input constraint modifiers must not be misused, otherwise the program will malfunction.
Experiment 3: Implementing memset Using Inline Assembly
Advanced Inline Assembly: Combining with Macros
- Technique 1: Using C’s
#operator. In parameterized macros,#acts as a preprocessing operator that converts a token to a string.
1 |
This macro can be used to generate multiple atomic operation functions:
1 | ATOMIC_OP(add, "addl") |
Which expands to:
1 | static inline void atomic_add(int i, atomic_t *v) { |
The macro in the image uses #asm_op because it needs to convert the macro parameter asm_op into a string literal for string concatenation or output. This syntax is called macro stringification.
asm_op is a macro parameter that is replaced with your provided value during macro expansion (e.g., "addl").
It is already a string, so when you call:
1 | ATOMIC_OP(add, "addl") |
After macro expansion:
1 | __asm__ __volatile__( |
Whereas:
1 | ATOMIC_OP(add, addl) |
After macro expansion becomes:
1 | __asm__ __volatile__( |
Which is not what we want.
##name — Token Pasting Operator
- Concatenates macro parameters with preceding/following identifiers into a new identifier (not a string).
- Commonly used to generate variable names, function names, etc.
1 |
|
Experiment 4: Combining Inline Assembly with Macros
Experiment 5: Implementing Macros for Reading/Writing System Registers
This uses GNU C statement expression syntax:
What is ({ ... })
-
This is a GNU extension, not standard C.
-
It allows a code block to execute like a statement while also returning a value.
-
Syntax rule:
({ statement1; statement2; ...; expression; })
The last expression (without a semicolon) in the block is the return value.
Inline Assembly: goto
The
gototemplate of inline assembly can jump to C language labels.
- The goto template’s output operands must be empty.
- A new
gotolabelssection lists C labels that are allowed as jump targets.
Experiment 6: goto Template Inline Assembly
%l[label] is a special syntax in GCC inline assembly for asm goto, indicating a jump to the C code label label.
Detailed explanation:
%l[...]tells the compiler this is a label symbol, not a regular register or immediate.labelis the label name you defined in your C code, such aslabel:in your code.asm gotoallows assembly code to directly jump to a C code label via conditional branches, implementing conditional branching.





















