Skip to content

Inline Assembly

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

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 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 = &a;
usz 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.