A pure Rust multi-architecture assembly engine for offensive security. Zero unsafe, no_std-compatible, designed for embedding in exploit compilers, JIT engines, security tools, and shellcode generators.
Complete reference for the asm-rs public API.
For auto-generated Rust API docs, see docs.rs/asm-rs.
ArchTarget architecture selection:
pub enum Arch {
X86, // x86 (32-bit)
X86_64, // x86-64 (64-bit)
Arm, // ARM32 (A32)
Thumb, // Thumb / Thumb-2 (T32)
Aarch64, // AArch64 (ARM64 / A64)
Rv32, // RISC-V 32-bit (RV32I)
Rv64, // RISC-V 64-bit (RV64I)
}
SyntaxAssembly syntax flavor:
pub enum Syntax {
Intel, // Intel syntax (default for x86/x86-64)
Att, // AT&T / GAS syntax
}
OptLevelPeephole optimization level:
pub enum OptLevel {
None, // No optimizations
Size, // Optimize for code size (default)
}
assembleAssemble source text into machine code bytes:
pub fn assemble(source: &str, arch: Arch) -> Result<Vec<u8>, AsmError>
use asm_rs::{assemble, Arch};
let bytes = assemble("nop\nret", Arch::X86_64).unwrap();
assemble_atAssemble with a base address:
pub fn assemble_at(source: &str, arch: Arch, base: u64) -> Result<Vec<u8>, AsmError>
use asm_rs::{assemble_at, Arch};
let bytes = assemble_at("nop\nret", Arch::X86_64, 0x400000).unwrap();
Assembler (Builder API)use asm_rs::{Assembler, Arch};
let mut asm = Assembler::new(Arch::X86_64);
| Method | Description |
|---|---|
base_address(addr: u64) |
Set the base address for label resolution |
syntax(syntax: Syntax) |
Set the assembly syntax |
opt_level(level: OptLevel) |
Set the optimization level |
enable_listing() |
Enable listing output generation |
define_constant(name, value) |
Define an assembly-time constant |
define_external(name, addr) |
Define an external label address |
define_preprocessor_symbol(name, value) |
Define a preprocessor symbol |
| Method | Description |
|---|---|
emit(source: &str) |
Assemble source text (can be called multiple times) |
finish() |
Finalize and return AssemblyResult |
| Method | Returns | Description |
|---|---|---|
ascii(s) |
Result<&mut Self> |
Emit raw string bytes |
asciz(s) |
Result<&mut Self> |
Emit NUL-terminated string |
align(n) |
&mut Self |
Align to n-byte boundary (multi-byte NOPs) |
align_with_fill(n, fill) |
&mut Self |
Align with explicit fill byte |
org(offset) |
Result<&mut Self> |
Advance to byte offset |
org_with_fill(offset, fill) |
Result<&mut Self> |
Advance with fill byte |
fill(count, size, value) |
Result<&mut Self> |
Emit repeated pattern |
space(n) |
Result<&mut Self> |
Reserve n zero bytes |
use asm_rs::{Assembler, Arch};
let mut asm = Assembler::new(Arch::X86_64);
asm.base_address(0x401000);
asm.enable_listing();
asm.define_constant("EXIT_CODE", 0);
asm.emit(r#"
_start:
xor edi, edi
mov eax, 60
syscall
"#).unwrap();
let result = asm.finish().unwrap();
println!("{}", result.listing());
AssemblyResultReturned by Assembler::finish():
| Method | Returns | Description |
|---|---|---|
bytes() |
&[u8] |
Final machine code bytes |
len() |
usize |
Output size in bytes |
is_empty() |
bool |
Whether output is empty |
labels() |
&HashMap<String, u64> |
All label names and addresses |
label_address(name) |
Option<u64> |
Look up a specific label |
relocations() |
&[AppliedRelocation] |
Applied relocation records |
listing() |
String |
Human-readable hex dump |
base_address() |
u64 |
Base address used |
AppliedRelocationpub struct AppliedRelocation {
pub offset: usize, // Byte offset in output
pub size: usize, // Size of the relocation in bytes
pub label: String, // Label name
pub kind: RelocKind, // Relocation type
pub rip_relative: bool, // Whether RIP-relative
pub addend: i64, // Addend value
}
AsmErrorError types with source location information:
pub enum AsmError {
UnknownMnemonic { mnemonic: String, span: Option<Span> },
InvalidOperands { detail: String, span: Option<Span> },
UndefinedLabel { label: String, span: Option<Span> },
DuplicateLabel { label: String, span: Option<Span> },
BranchOutOfRange { label: String, span: Option<Span> },
InvalidImmediate { detail: String, span: Option<Span> },
ParseError { message: String, span: Option<Span> },
Multiple { errors: Vec<AsmError> },
// ... additional variants
}
SpanSource location tracking:
pub struct Span {
pub line: usize, // 1-based line number
pub column: usize, // 1-based column
pub offset: usize, // Byte offset from start
pub length: usize, // Span length in bytes
}
asm-rs-macros)asm_bytes!Assemble at compile time, returning &'static [u8]:
use asm_rs_macros::asm_bytes;
const CODE: &[u8] = asm_bytes!(x86_64, "nop; ret");
const BASED: &[u8] = asm_bytes!(x86_64, 0x400000, "nop; ret");
asm_array!Assemble at compile time, returning [u8; N]:
use asm_rs_macros::asm_array;
const NOP: [u8; 1] = asm_array!(x86_64, "nop");
| Token | Architecture |
|---|---|
x86 |
x86 (32-bit) |
x86_64 |
x86-64 |
arm |
ARM32 (A32) |
thumb |
Thumb/Thumb-2 |
aarch64 |
AArch64 (A64) |
rv32 |
RISC-V 32-bit |
rv64 |
RISC-V 64-bit |
Assembly errors become compile_error!() with full diagnostics.