Skip to main content

Assembler

Struct Assembler 

Source
pub struct Assembler { /* private fields */ }
Expand description

x86-64 assembler with label support.

Uses direct pointer writes to the pre-allocated buffer for emission, avoiding per-byte Vec::push overhead (capacity check + len update).

Implementations§

Source§

impl Assembler

Source

pub fn new() -> Self

Source

pub fn with_capacity(code_capacity: usize, label_capacity: usize) -> Self

Create with pre-allocated capacity for code and labels. Uses Vec-backed buffer (for tests or when mmap is not needed).

Source

pub fn set_jit_va_base(&mut self, va: u64)

Set the eventual load VA for the code buffer. Must be called before any RIP-relative emitter that targets a fixed VA (i.e. CTX accesses).

Source

pub fn ensure_capacity(&mut self, n: usize)

Check capacity and grow if needed. Inlined for the fast path (no grow).

Source

pub fn new_label(&mut self) -> Label

Allocate a new label.

Source

pub fn labels_len(&self) -> usize

Current number of labels allocated.

Source

pub fn bulk_create_labels(&mut self, count: usize)

Bulk-allocate count unbound labels. The labels Vec is already pre-sized via calloc (zero pages). This just advances the logical length counter.

Source

pub fn bind_label(&mut self, label: Label)

Bind a label to the current write position.

Source

pub fn offset(&self) -> usize

Current code offset (write position).

Source

pub fn patch_i32(&mut self, offset: usize, value: i32)

Patch an i32 value at a previously recorded offset.

Source

pub fn mov_rr(&mut self, dst: Reg, src: Reg)

mov r64, r64

Source

pub fn mov_ri64(&mut self, dst: Reg, imm: u64)

mov r64, imm64

Source

pub fn mov_ri32(&mut self, dst: Reg, imm: u32)

mov r32, imm32 (zero-extends to 64-bit)

Source

pub fn mov_load32(&mut self, dst: Reg, base: Reg, disp: i32)

mov r32, [base + disp] — zero-extending 32-bit load

Source

pub fn mov_load64(&mut self, dst: Reg, base: Reg, disp: i32)

mov r64, [base + disp]

Source

pub fn movsxd_load_sib4(&mut self, dst: Reg, base: Reg, index: Reg)

movsxd r64, dword [base + index*4] — sign-extending load with SIB scale=4

Source

pub fn mov_store32(&mut self, base: Reg, disp: i32, src: Reg)

mov dword [base + disp], r32 — 32-bit store

Source

pub fn mov_store64(&mut self, base: Reg, disp: i32, src: Reg)

mov [base + disp], r64

Source

pub fn mov_store32_imm(&mut self, base: Reg, disp: i32, imm: i32)

mov dword [base + disp], imm32

Source

pub fn mov_store64_imm(&mut self, base: Reg, disp: i32, imm: i32)

mov qword [base + disp], sign-extended imm32

Source

pub fn movzx_load8_sib(&mut self, dst: Reg, base: Reg, index: Reg)

movzx r64, byte [base + index] — zero-extending u8 load

Source

pub fn movzx_load16_sib(&mut self, dst: Reg, base: Reg, index: Reg)

movzx r32, word [base + index] — zero-extending u16 load

Source

pub fn mov_load32_sib(&mut self, dst: Reg, base: Reg, index: Reg)

mov r32, dword [base + index] — zero-extending u32 load

Source

pub fn mov_load64_sib(&mut self, dst: Reg, base: Reg, index: Reg)

mov r64, qword [base + index]

Source

pub fn mov_store8_sib(&mut self, base: Reg, index: Reg, src: Reg)

mov byte [base + index], r8

Source

pub fn mov_store16_sib(&mut self, base: Reg, index: Reg, src: Reg)

mov word [base + index], r16

Source

pub fn mov_store32_sib(&mut self, base: Reg, index: Reg, src: Reg)

mov dword [base + index], r32

Source

pub fn mov_store64_sib(&mut self, base: Reg, index: Reg, src: Reg)

mov qword [base + index], r64

Source

pub fn mov_store32_sib_imm(&mut self, base: Reg, index: Reg, imm: i32)

mov dword [base + index], imm32

Source

pub fn mov_store64_sib_imm(&mut self, base: Reg, index: Reg, imm: i32)

mov qword [base + index], sign-extended imm32

Source

pub fn mov_store8_sib_imm(&mut self, base: Reg, index: Reg, imm: u8)

mov byte [base + index], imm8

Source

pub fn mov_store16_sib_imm(&mut self, base: Reg, index: Reg, imm: u16)

mov word [base + index], imm16

Source

pub fn add_r64_mem(&mut self, dst: Reg, base: Reg, disp: i32)

add r64, qword [base + disp32]

Source

pub fn movzx_load8_deref(&mut self, dst: Reg, base: Reg)

movzx r64, byte [rax] (simple deref, no SIB needed) — for perm table lookup

Source

pub fn cmp_byte_sib_disp32(&mut self, base: Reg, index: Reg, disp: i32, imm: u8)

cmp byte [base + index + disp32], imm8 — compare memory byte with SIB+displacement

Source

pub fn cmp_byte_deref_imm(&mut self, base: Reg, imm: u8)

cmp byte [reg], imm8 — compare memory byte with immediate

Source

pub fn add_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn sub_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn and_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn or_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn xor_rr(&mut self, dst: Reg, src: Reg)

Source

pub fn cmp_rr(&mut self, a: Reg, b: Reg)

Source

pub fn test_rr(&mut self, a: Reg, b: Reg)

Source

pub fn test_byte_mem_disp32(&mut self, base: Reg, disp: i32, imm: u8)

test byte [base + disp32], imm8 — test memory byte against immediate bitmask.

Source

pub fn add_rr32(&mut self, dst: Reg, src: Reg)

Source

pub fn sub_rr32(&mut self, dst: Reg, src: Reg)

Source

pub fn add_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn sub_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn and_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn or_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn xor_ri(&mut self, dst: Reg, imm: i32)

Source

pub fn cmp_ri(&mut self, a: Reg, imm: i32)

Source

pub fn add_ri32(&mut self, dst: Reg, imm: i32)

Source

pub fn sub_ri32(&mut self, dst: Reg, imm: i32)

Source

pub fn cmp_ri32(&mut self, a: Reg, imm: i32)

Source

pub fn cmp_mem32_imm(&mut self, base: Reg, disp: i32, imm: i32)

cmp dword [base + disp], imm32

Source

pub fn cmp_mem32_r(&mut self, base: Reg, disp: i32, src: Reg)

cmp dword [base + disp], reg32 (sets flags: mem vs reg)

Source

pub fn sub_mem64_imm32(&mut self, base: Reg, disp: i32, imm: i32)

sub qword [base + disp32], sign-extended imm32. Always uses disp32 encoding (the imm32 is patched after emission for gas metering).

Source

pub fn add_mem64_imm32(&mut self, base: Reg, disp: i32, imm: i32)

add qword [base + disp32], imm32

Source

pub fn movzx_load8_at_index(&mut self, dst: Reg, idx: Reg)

movzx r64, byte [idx] — zero-extending u8 load

Source

pub fn movzx_load16_at_index(&mut self, dst: Reg, idx: Reg)

movzx r64, word [idx] — zero-extending u16 load

Source

pub fn mov_load32_at_index(&mut self, dst: Reg, idx: Reg)

mov r32, dword [idx] — zero-extending u32 load (writes EAX, clears upper 32)

Source

pub fn mov_load64_at_index(&mut self, dst: Reg, idx: Reg)

mov r64, qword [idx]

Source

pub fn mov_store8_at_index(&mut self, idx: Reg, src: Reg)

mov byte [idx], r8

Source

pub fn mov_store16_at_index(&mut self, idx: Reg, src: Reg)

mov word [idx], r16

Source

pub fn mov_store32_at_index(&mut self, idx: Reg, src: Reg)

mov dword [idx], r32

Source

pub fn mov_store64_at_index(&mut self, idx: Reg, src: Reg)

mov qword [idx], r64

Source

pub fn mov_store8_at_index_imm(&mut self, idx: Reg, imm: u8)

mov byte [idx], imm8

Source

pub fn mov_store16_at_index_imm(&mut self, idx: Reg, imm: u16)

mov word [idx], imm16

Source

pub fn mov_store32_at_index_imm(&mut self, idx: Reg, imm: i32)

mov dword [idx], imm32

Source

pub fn mov_store64_at_index_imm(&mut self, idx: Reg, imm: i32)

mov qword [idx], sign-extended imm32

Source

pub fn mov_load32_rip_rel(&mut self, dst: Reg, target_va: u64)

mov r32, dword [rip+disp32] (zero-extends to 64-bit)

Source

pub fn mov_load64_rip_rel(&mut self, dst: Reg, target_va: u64)

mov r64, qword [rip+disp32]

Source

pub fn mov_store32_rip_rel(&mut self, target_va: u64, src: Reg)

mov dword [rip+disp32], r32

Source

pub fn mov_store64_rip_rel(&mut self, target_va: u64, src: Reg)

mov qword [rip+disp32], r64

Source

pub fn mov_store32_rip_rel_imm(&mut self, target_va: u64, imm: i32)

mov dword [rip+disp32], imm32 — the trailing imm32 means the “next-instruction RIP” is 4 bytes further than disp32 alone.

Source

pub fn cmp_mem32_rip_rel_r(&mut self, target_va: u64, src: Reg)

cmp dword [rip+disp32], reg32 (sets flags: mem vs reg)

Source

pub fn add_r64_mem_rip_rel(&mut self, dst: Reg, target_va: u64)

add r64, qword [rip+disp32]

Source

pub fn sub_r64_imm32_patchable(&mut self, dst: Reg, imm: i32)

sub r64, imm32 in the always-imm32 (7-byte) encoding. offset() - 4 after this call points at the imm32 field; callers patch it after emission for per-block gas metering.

Source

pub fn imul_rr(&mut self, dst: Reg, src: Reg)

imul r64, r64

Source

pub fn imul_rr32(&mut self, dst: Reg, src: Reg)

imul r32, r32

Source

pub fn imul_rri(&mut self, dst: Reg, src: Reg, imm: i32)

imul r64, r64, imm32

Source

pub fn imul_rri32(&mut self, dst: Reg, src: Reg, imm: i32)

imul r32, r32, imm32

Source

pub fn mul_rdx_rax(&mut self, src: Reg)

mul r64 (unsigned RDX:RAX = RAX * src)

Source

pub fn imul_rdx_rax(&mut self, src: Reg)

imul r64 (signed RDX:RAX = RAX * src)

Source

pub fn div64(&mut self, src: Reg)

div r64 (unsigned RAX = RDX:RAX / src, RDX = remainder)

Source

pub fn idiv64(&mut self, src: Reg)

idiv r64 (signed)

Source

pub fn div32(&mut self, src: Reg)

div r32

Source

pub fn idiv32(&mut self, src: Reg)

idiv r32

Source

pub fn cqo(&mut self)

cqo (sign-extend RAX into RDX:RAX, 64-bit)

Source

pub fn cdq(&mut self)

cdq (sign-extend EAX into EDX:EAX, 32-bit)

Source

pub fn inc64(&mut self, dst: Reg)

inc r64

Source

pub fn dec64(&mut self, dst: Reg)

dec r64

Source

pub fn neg64(&mut self, dst: Reg)

neg r64

Source

pub fn neg32(&mut self, dst: Reg)

Source

pub fn not64(&mut self, dst: Reg)

not r64

Source

pub fn shift_cl64(&mut self, ext: u8, dst: Reg)

Source

pub fn shift_cl32(&mut self, ext: u8, dst: Reg)

Source

pub fn shl_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn shr_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn sar_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn shl_cl64(&mut self, dst: Reg)

Source

pub fn shr_cl64(&mut self, dst: Reg)

Source

pub fn sar_cl64(&mut self, dst: Reg)

Source

pub fn rol_cl64(&mut self, dst: Reg)

Source

pub fn ror_cl64(&mut self, dst: Reg)

Source

pub fn rol_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn ror_ri64(&mut self, dst: Reg, imm: u8)

Source

pub fn shl_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn shr_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn sar_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn shl_cl32(&mut self, dst: Reg)

Source

pub fn shr_cl32(&mut self, dst: Reg)

Source

pub fn sar_cl32(&mut self, dst: Reg)

Source

pub fn rol_cl32(&mut self, dst: Reg)

Source

pub fn ror_cl32(&mut self, dst: Reg)

Source

pub fn rol_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn ror_ri32(&mut self, dst: Reg, imm: u8)

Source

pub fn movsxd(&mut self, dst: Reg, src: Reg)

movsxd r64, r32 (sign-extend 32→64)

Source

pub fn movsx_8_64(&mut self, dst: Reg, src: Reg)

movsx r64, r8 (sign-extend 8→64)

Source

pub fn movsx_16_64(&mut self, dst: Reg, src: Reg)

movsx r64, r16 (sign-extend 16→64)

Source

pub fn movzx_8_64(&mut self, dst: Reg, src: Reg)

movzx r64, r8 (zero-extend 8→64)

Source

pub fn movzx_16_64(&mut self, dst: Reg, src: Reg)

movzx r32, r16 (zero-extends to 64 due to 32-bit operation)

Source

pub fn movzx_32_64(&mut self, dst: Reg, src: Reg)

Zero-extend 32→64: mov r32, r32 (implicit zero-extend)

Source

pub fn setcc(&mut self, cc: Cc, dst: Reg)

setcc r8 (sets low byte, need to movzx after)

Source

pub fn cmovcc(&mut self, cc: Cc, dst: Reg, src: Reg)

cmovcc r64, r64

Source

pub fn popcnt64(&mut self, dst: Reg, src: Reg)

popcnt r64, r64

Source

pub fn lzcnt64(&mut self, dst: Reg, src: Reg)

lzcnt r64, r64

Source

pub fn tzcnt64(&mut self, dst: Reg, src: Reg)

tzcnt r64, r64

Source

pub fn popcnt32(&mut self, dst: Reg, src: Reg)

popcnt r32, r32 (result zero-extended to 64 bits)

Source

pub fn lzcnt32(&mut self, dst: Reg, src: Reg)

lzcnt r32, r32 (result zero-extended to 64 bits)

Source

pub fn tzcnt32(&mut self, dst: Reg, src: Reg)

tzcnt r32, r32 (result zero-extended to 64 bits)

Source

pub fn bswap64(&mut self, dst: Reg)

bswap r64

Source

pub fn push(&mut self, reg: Reg)

Source

pub fn pop(&mut self, reg: Reg)

Source

pub fn push_imm32(&mut self, imm: i32)

push sign-extended imm32 (5 bytes: 0x68 + imm32).

Source

pub fn jmp_label(&mut self, label: Label)

jmp to label — uses rel8 for backward jumps within ±127 bytes.

Source

pub fn jcc_label(&mut self, cc: Cc, label: Label)

jcc to label — uses rel8 for backward jumps within ±127 bytes.

Source

pub fn jmp_reg(&mut self, reg: Reg)

jmp r64 (indirect)

Source

pub fn call_reg(&mut self, reg: Reg)

call r64 (indirect)

Source

pub fn call_label(&mut self, label: Label)

call label

Source

pub fn ret(&mut self)

ret

Source

pub fn lea(&mut self, dst: Reg, base: Reg, disp: i32)

lea r64, [base + disp]

Source

pub fn lea_32(&mut self, dst: Reg, base: Reg, disp: i32)

lea r32, [base + disp] — 32-bit result, zero-extends to 64-bit.

Source

pub fn lea_sib_scaled_32( &mut self, dst: Reg, base: Reg, index: Reg, scale_log2: u8, )

lea r32, [base32 + index32 * (1 << scale_log2)] scale_log2: 0=*1, 1=*2, 2=*4, 3=*8

Source

pub fn ud2(&mut self)

ud2 (undefined instruction, for traps)

Source

pub fn nop(&mut self)

nop

Source

pub fn int3(&mut self)

int3 (debug breakpoint)

Source

pub fn label_offset(&self, label: Label) -> Option<usize>

Get the resolved native offset for a label (only valid after bind_label).

Source

pub fn sync_len(&mut self)

Sync Vec length with the write cursor. Call before accessing self.code directly.

Source

pub fn finalize(&mut self) -> Vec<u8>

Resolve fixups and return the code as a Vec<u8>.

Trait Implementations§

Source§

impl Default for Assembler

Source§

fn default() -> Self

Returns the “default value” for a type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.