このページの目次
インラインアセンブリ
asm!マクロにより、Rust でターゲットマシンのアセンブリ命令を直接埋め込めます。制約(constraints)はレジスタの入出力関係を記述し、clobbers はどのレジスタが破壊されるかを宣言します。各アセンブリテンプレートはアーキテクチャ固有(x86_64 と ARM64 では書き方が全く異なります)であり、本質的には「この行を越えて最適化しないでください」という、コンパイラ最適化に対する壁です。
asm! の基礎
use asm;
let x: u64;
unsafe
// TSC (Time Stamp Counter) = EDX:EAX
// out("rax") _ — 上位32ビット、値は破棄 (_)
// out("rdx") _ — rdx の下位32ビット、破棄
// lateout("rax") x — x に結合された値
asm! は Rust 1.59+ で導入された新しいマクロです(古い llvm_asm! に取って代わります)。制約の妥当性をコンパイル時にチェックし、レジスタの競合、無効なオペランド、型の不一致はすべてコンパイル時に報告されます。
制約(Constraints): 入出力仕様
let mut a: u64 = 4;
let b: u64 = 4;
unsafe
in(reg): 入力。コンパイラがレジスタを割り当て、値を読み込みます。out(reg): 出力。最終値を読み取ります。inout(reg): 入力+出力。lateout(reg): 出力。入力とレジスタを共有しません(入力レジスタが clobber されるシナリオ用)。inlateout(reg): 入力+出力。入力とレジスタを共有しません。
Clobbers: どのレジスタが変更されるか
out と lateout は対応するレジスタを自動的に clobbered としてマークします。しかし、他の関数を呼び出す場合、ABI 全体の clobber セットをマークする必要があります。
unsafe
アーキテクチャ固有の条件コンパイル
unsafe
unsafe // ARM64 のサイクルカウンター
オプション
asm!;
// nomem: メモリへの読み書きを行わない(コンパイラはキャッシュを更新しなくてもよい)
// nostack: スタックの push/pop を行わない
// preserves_flags: EFLAGS/RFLAGS を変更しない
// pure: 副作用がない(最適化によって削除可能)
// readonly: メモリのみ読み取り
参考
- Rust Reference: inline assembly
- Rust By Example: asm
Keywords: asm!, inline assembly, constraints, clobbers, lateout, clobber_abi, per-arch asm