Skip to main content

Inline Assembly

Zynx supports inline assembly through the asm keyword, following the GCC/Clang extended assembly format.

Use inline assembly only for narrow low-level cases (for example, CPU feature instructions, special register access, or hand-tuned leaf paths). Prefer normal Zynx/C code when possible.

Syntax

asm [volatile] ( template [ : outputs [ : inputs [ : clobbers ] ] ] );
  • volatile: Prevents the compiler from optimizing away the block.
  • template: A string literal containing the assembly code. Operands are referenced via %0, %1, etc.
  • outputs / inputs: Comma-separated list of operand constraints.
  • clobbers: A list of registers or memory modified by the assembly code.

Operands

Connect Zynx variables to assembly instructions:

[ "[" name "]" ] constraint ( expression )

  • name: Optional symbolic name for the operand.
  • constraint: A string literal specifying the storage class (e.g., "r" for register, "m" for memory).
  • expression: The Zynx variable to bind.

Clobbers

Instruct the compiler to save and restore registers or memory. Common clobbers include "memory" and "cc".

Platform and Toolchain Notes

  • Inline assembly support depends on the backend C compiler and target architecture.
  • Constraint letters and accepted templates are backend-defined (Clang/GCC style), not Zynx-specific.
  • Cross-target assembly must match the selected target ABI and instruction set.
  • Windows targets may require different syntax/constraints depending on toolchain behavior.

Common Pitfalls

  • Missing "memory" clobber when the assembly reads/writes memory not listed as operands can cause incorrect reordering.
  • Missing "cc" clobber when condition flags are modified can break surrounding branch logic.
  • Omitting volatile for side-effect-only instructions may let the optimizer remove the block.
  • Using wrong constraints (for example forcing register when memory is required) can fail compilation or miscompile.
  • Clobbering callee-saved registers manually is unsafe unless fully modeled through constraints/clobbers.

Examples

Basic

asm("nop");

Arithmetic

fn add(a: i32, b: i32) -> i32 {
let result: i32 = 0;
asm("add %2, %0"
: "=r"(result) // Output %0
: "0"(a), "r"(b) // Input %1 (tied to %0), Input %2
: "cc"
);
return result;
}

Volatile Operation

asm volatile ("cli"); // Disable interrupts

Memory Barrier Example

asm volatile ("" ::: "memory");

This empty template acts as a compiler barrier for memory reordering.