What Is Inline Assembly?
Inline assembly (veya “embedded assembly”) is the practice of embedding low-level assembly code directly within a high-level language like C, C++, or Rust.
It allows you to write assembly instructions inline with your regular code, offering more control over how your program runs on the hardware.
This hybrid coding technique is used when:
- Speed is critical
- Precise hardware access is needed
- A feature isn’t available in standard libraries
1. Why Use Inline Assembly?
| Use Case | Purpose |
|---|---|
| Optimization | Write highly-tuned, CPU-specific code |
| Hardware Access | Control special registers, ports |
| System Programming | Write parts of OS kernels or device drivers |
| Instruction-level Operations | Use instructions not accessible in high-level languages |
| Experimentation & Learning | Study compiler output and machine behavior |
It gives you manual control over register usage, instruction choice, and execution timing — but with great power comes great responsibility.
2. Basic Syntax: GCC (AT&T-style)
GCC (GNU Compiler Collection) supports inline assembly via the asm or __asm__ keyword.
Simple Example:
__asm__("movl $1, %eax");
This moves the value 1 into the EAX register.
3. GCC Extended Inline Assembly Format
Extended syntax gives more flexibility and safety:
__asm__ volatile (
"movl %1, %%eax;"
"addl %%eax, %0;"
: "=r"(result) // output operand
: "r"(value) // input operand
: "%eax" // clobbered register
);
Format Breakdown:
- Assembly code in quotes
- Output operands: where result goes
- Input operands: values used
- Clobbered registers: registers that are modified
4. Inline Assembly in MSVC (Intel-style)
Microsoft’s compiler uses a different syntax with Intel-style notation:
__asm {
mov eax, 1
add eax, 2
}
- No need for
%in register names - Doesn’t require operands section like GCC
Note: Microsoft deprecated inline assembly in 64-bit builds. Use intrinsics or external assembly instead.
5. Real-World Use: cpuid Instruction Example
Inline assembly can access CPU info not available in C:
void get_cpu_vendor(char* vendor) {
int eax, ebx, ecx, edx;
__asm__ volatile (
"cpuid"
: "=b"(ebx), "=d"(edx), "=c"(ecx)
: "a"(0)
);
memcpy(vendor, &ebx, 4);
memcpy(vendor+4, &edx, 4);
memcpy(vendor+8, &ecx, 4);
vendor[12] = '\0';
}
This returns a string like "GenuineIntel" or "AuthenticAMD".
6. Pros and Cons
| Pros | Cons |
|---|---|
| Absolute control over machine code | Non-portable across architectures |
| Maximize performance for hot paths | Harder to read and debug |
| Access special hardware features | Error-prone and easy to misuse |
| Lower overhead than external asm | May break across compiler versions |
| Reuse high-level code | Fragile across compiler optimizations |
7. Compiler Optimization and volatile
To prevent the compiler from optimizing away your inline assembly, use the volatile keyword:
__asm__ volatile("nop");
8. Common Pitfalls
- Incorrect register clobbering → Causes undefined behavior
- Wrong operand constraints → Unexpected compilation errors
- Tight coupling to architecture → Code breaks on ARM or RISC-V
- Hard to maintain → Obscures logic and confuses readers
- Stack corruption → If calling conventions aren’t respected
9. Alternatives to Inline Assembly
| Option | When to Use |
|---|---|
| Intrinsics | Access hardware features with safer syntax |
| External Assembly | For large ASM code blocks |
| Compiler Builtins | Leverage predefined functions (e.g., __builtin_popcount) |
| Libraries (e.g., SIMD) | Use vectorized math or crypto ops |
Example (GCC intrinsic):
int x = __builtin_ctz(16); // Count trailing zeros
10. Inline Assembly in Rust (nightly)
Rust allows inline assembly via the asm! macro (nightly only):
#![feature(asm)]
let x: u32;
unsafe {
asm!("mov {0}, 5", out(reg) x);
}
This gives low-level access while still maintaining Rust’s safety boundaries — as long as you stay in unsafe.
11. Inline Assembly vs Macros
Inline assembly is run-time, while macros are compile-time code generation. Use inline asm when:
- Performance truly matters
- Behavior can’t be replicated with macros
12. Performance Considerations
- Carefully placed inline assembly can outperform compiled code
- BUT: modern compilers optimize better than most humans
- Use profiling tools to measure actual gains before introducing inline ASM
13. Security Considerations
- Hardcoded registers and memory addresses are risky
- Buffer overflows and race conditions are more likely
- Inline assembly may expose CPU-specific timing attacks
Only use inline ASM in trusted, performance-critical, isolated components
Summary
| Feature | Inline Assembly |
|---|---|
| Purpose | Embed low-level machine code |
| Languages | C, C++, Rust (nightly), MSVC |
| Syntax | Varies (AT&T vs Intel) |
| Advantages | Performance, control, direct hardware access |
| Disadvantages | Portability, maintainability, readability |
| Alternatives | Intrinsics, builtins, external .asm files |
Inline assembly is a precision tool — powerful when used correctly, disastrous if misused.
Related Keywords
- Assembly Language
- Machine Code
- GCC Extended Assembly
- MSVC Inline Assembly
- asm Keyword
- CPU Registers
- CPUID
- Intrinsics
- Volatile
- Instruction Set
- Operand Constraints
- Register Clobbering
- Calling Convention
- System Programming
- Security Hardening
- Optimization Techniques
- Memory-Mapped IO
- Interrupts
- Rust Inline ASM
- SIMD Instructions









