CodeBlanks Logo Icon CodeBlanks

asm! macro

Write assembly with core::arch::asm!.

The asm! macro

core::arch::asm! lets you write processor instructions directly inside Rust code (stable since Rust 1.59). It can only be used inside unsafe, because the compiler can't check what the instructions do. The default syntax on x86 is Intel:

use std::arch::asm;

let mut x: u64 = 3;
unsafe {
    asm!("add {0}, 4", inout(reg) x);
}
// x == 7

{0} is a placeholder; the compiler puts a register of its choosing there. The code is platform-specific, so it's usually guarded with #[cfg(target_arch = "x86_64")].

Portability

Assembly is tied to an architecture. To keep code buildable on every platform, a separate implementation per architecture or a generic fallback is written:

#[cfg(target_arch = "x86_64")]
fn dort_ekle(mut x: u64) -> u64 {
    unsafe { std::arch::asm!("add {0}, 4", inout(reg) x) };
    x
}

#[cfg(not(target_arch = "x86_64"))]
fn dort_ekle(x: u64) -> u64 {
    x + 4
}

Supported architectures: x86/x86-64, ARM/AArch64, RISC-V, LoongArch and a few others.

Practice First assembly

Write the dort_ekle function above with asm! for x86-64 and in plain Rust for other architectures. Print the result of dort_ekle(3).

Starter code

main.rs
fn main() {
    // buraya yaz
}

Sample solution

main.rs
#[cfg(target_arch = "x86_64")]
fn dort_ekle(mut x: u64) -> u64 {
    // SAFETY: yalnızca x'in yazmacını değiştirir.
    unsafe { std::arch::asm!("add {0}, 4", inout(reg) x) };
    x
}

#[cfg(not(target_arch = "x86_64"))]
fn dort_ekle(x: u64) -> u64 {
    x + 4
}

fn main() {
    println!("{}", dort_ekle(3));
}

Expected output

7

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 When is inline assembly a justified choice?

  • For readability
  • Never
  • When a special instruction or hardware access that Rust can't express is needed Correct answer
  • Always, to speed code up

Explanation: The compiler usually produces code as good as hand-written assembly; std::arch intrinsics and measurement are tried first.

2 Assembly macro

Question
unsafe {
    std::arch::____!("add {0}, 4", inout(reg) x);
}
Answer
unsafe {
    std::arch::asm!("add {0}, 4", inout(reg) x);
}

Explanation: asm! is for writing inline assembly.

3 Item and meaning

Term Meaning
asm!(..) Inline assembly
{0} Placeholder
inout(reg) x Input and output
#[cfg(target_arch)] Architecture guard

All lessons in Expert