Skip to content

Inline Assembly

C3 provides two ways to insert inline assembly code: asm strings and asm blocks.

Assembly strings

This form takes a single compile time string and passes it directly to the underlying backend without any changes.

int x = 0;
asm("nop");
int y = x;

Assembly blocks

Assembly blocks use a common grammar for all types of processors. C3's asm implementation assumes that all assembly statements can be reduced to variations of the following general format:

instruction (arg (',' arg)*)?;

Where an arg is:

  1. An identifier, e.g. FOO, x.
  2. A numeric constant 1 0xFF etc.
  3. A register name (always lower case with a '$' prefix) e.g. $eax $r7.
  4. The address of a variable e.g. &x.
  5. An indirect address: [addr] or [addr + index * <const> + offset].
  6. Any expression inside of "()" (will be evaluated before entering the asm block).

An example:

int aa = 3;
int g;
int* gp = &g;
int* xa = &aa;
sz asf = 1;
asm
{
    movl x, 4;                  // Move 4 into the variable x
    movl [gp], x;               // Move the value of x into the address in gp
    movl x, 1;                  // Move 1 into x
    movl [xa + asf * 4 + 4], x; // Move x into the address at xa[asf + 1]
    movl $eax, (23 + x);        // Move 23 + x into EAX
    movl x, $eax;               // Move EAX into x
    movq [&z], 33;              // Move 33 into the memory address of z
}
The asm block will infer register clobbers and in/out parameters.

Note

The current state of inline asm is a work in progress. Only a subset of x86, aarch64 and riscv instructions are available, and other platforms have no support at all. It is likely that the grammar will be extended as more architectures are supported. More instructions can be added as they are needed, so please file issues when you encounter missing instructions you need.