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
impl Assembler
pub fn new() -> Self
Sourcepub fn with_capacity(code_capacity: usize, label_capacity: usize) -> Self
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).
Sourcepub fn set_jit_va_base(&mut self, va: u64)
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).
Sourcepub fn ensure_capacity(&mut self, n: usize)
pub fn ensure_capacity(&mut self, n: usize)
Check capacity and grow if needed. Inlined for the fast path (no grow).
Sourcepub fn labels_len(&self) -> usize
pub fn labels_len(&self) -> usize
Current number of labels allocated.
Sourcepub fn bulk_create_labels(&mut self, count: usize)
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.
Sourcepub fn bind_label(&mut self, label: Label)
pub fn bind_label(&mut self, label: Label)
Bind a label to the current write position.
Sourcepub fn patch_i32(&mut self, offset: usize, value: i32)
pub fn patch_i32(&mut self, offset: usize, value: i32)
Patch an i32 value at a previously recorded offset.
Sourcepub fn mov_load32(&mut self, dst: Reg, base: Reg, disp: i32)
pub fn mov_load32(&mut self, dst: Reg, base: Reg, disp: i32)
mov r32, [base + disp] — zero-extending 32-bit load
Sourcepub fn mov_load64(&mut self, dst: Reg, base: Reg, disp: i32)
pub fn mov_load64(&mut self, dst: Reg, base: Reg, disp: i32)
mov r64, [base + disp]
Sourcepub fn movsxd_load_sib4(&mut self, dst: Reg, base: Reg, index: Reg)
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
Sourcepub fn mov_store32(&mut self, base: Reg, disp: i32, src: Reg)
pub fn mov_store32(&mut self, base: Reg, disp: i32, src: Reg)
mov dword [base + disp], r32 — 32-bit store
Sourcepub fn mov_store64(&mut self, base: Reg, disp: i32, src: Reg)
pub fn mov_store64(&mut self, base: Reg, disp: i32, src: Reg)
mov [base + disp], r64
Sourcepub fn mov_store32_imm(&mut self, base: Reg, disp: i32, imm: i32)
pub fn mov_store32_imm(&mut self, base: Reg, disp: i32, imm: i32)
mov dword [base + disp], imm32
Sourcepub fn mov_store64_imm(&mut self, base: Reg, disp: i32, imm: i32)
pub fn mov_store64_imm(&mut self, base: Reg, disp: i32, imm: i32)
mov qword [base + disp], sign-extended imm32
Sourcepub fn movzx_load8_sib(&mut self, dst: Reg, base: Reg, index: Reg)
pub fn movzx_load8_sib(&mut self, dst: Reg, base: Reg, index: Reg)
movzx r64, byte [base + index] — zero-extending u8 load
Sourcepub fn movzx_load16_sib(&mut self, dst: Reg, base: Reg, index: Reg)
pub fn movzx_load16_sib(&mut self, dst: Reg, base: Reg, index: Reg)
movzx r32, word [base + index] — zero-extending u16 load
Sourcepub fn mov_load32_sib(&mut self, dst: Reg, base: Reg, index: Reg)
pub fn mov_load32_sib(&mut self, dst: Reg, base: Reg, index: Reg)
mov r32, dword [base + index] — zero-extending u32 load
Sourcepub fn mov_load64_sib(&mut self, dst: Reg, base: Reg, index: Reg)
pub fn mov_load64_sib(&mut self, dst: Reg, base: Reg, index: Reg)
mov r64, qword [base + index]
Sourcepub fn mov_store8_sib(&mut self, base: Reg, index: Reg, src: Reg)
pub fn mov_store8_sib(&mut self, base: Reg, index: Reg, src: Reg)
mov byte [base + index], r8
Sourcepub fn mov_store16_sib(&mut self, base: Reg, index: Reg, src: Reg)
pub fn mov_store16_sib(&mut self, base: Reg, index: Reg, src: Reg)
mov word [base + index], r16
Sourcepub fn mov_store32_sib(&mut self, base: Reg, index: Reg, src: Reg)
pub fn mov_store32_sib(&mut self, base: Reg, index: Reg, src: Reg)
mov dword [base + index], r32
Sourcepub fn mov_store64_sib(&mut self, base: Reg, index: Reg, src: Reg)
pub fn mov_store64_sib(&mut self, base: Reg, index: Reg, src: Reg)
mov qword [base + index], r64
Sourcepub fn mov_store32_sib_imm(&mut self, base: Reg, index: Reg, imm: i32)
pub fn mov_store32_sib_imm(&mut self, base: Reg, index: Reg, imm: i32)
mov dword [base + index], imm32
Sourcepub fn mov_store64_sib_imm(&mut self, base: Reg, index: Reg, imm: i32)
pub fn mov_store64_sib_imm(&mut self, base: Reg, index: Reg, imm: i32)
mov qword [base + index], sign-extended imm32
Sourcepub fn mov_store8_sib_imm(&mut self, base: Reg, index: Reg, imm: u8)
pub fn mov_store8_sib_imm(&mut self, base: Reg, index: Reg, imm: u8)
mov byte [base + index], imm8
Sourcepub fn mov_store16_sib_imm(&mut self, base: Reg, index: Reg, imm: u16)
pub fn mov_store16_sib_imm(&mut self, base: Reg, index: Reg, imm: u16)
mov word [base + index], imm16
Sourcepub fn add_r64_mem(&mut self, dst: Reg, base: Reg, disp: i32)
pub fn add_r64_mem(&mut self, dst: Reg, base: Reg, disp: i32)
add r64, qword [base + disp32]
Sourcepub fn movzx_load8_deref(&mut self, dst: Reg, base: Reg)
pub fn movzx_load8_deref(&mut self, dst: Reg, base: Reg)
movzx r64, byte [rax] (simple deref, no SIB needed) — for perm table lookup
Sourcepub fn cmp_byte_sib_disp32(&mut self, base: Reg, index: Reg, disp: i32, imm: u8)
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
Sourcepub fn cmp_byte_deref_imm(&mut self, base: Reg, imm: u8)
pub fn cmp_byte_deref_imm(&mut self, base: Reg, imm: u8)
cmp byte [reg], imm8 — compare memory byte with immediate
pub fn add_rr(&mut self, dst: Reg, src: Reg)
pub fn sub_rr(&mut self, dst: Reg, src: Reg)
pub fn and_rr(&mut self, dst: Reg, src: Reg)
pub fn or_rr(&mut self, dst: Reg, src: Reg)
pub fn xor_rr(&mut self, dst: Reg, src: Reg)
pub fn cmp_rr(&mut self, a: Reg, b: Reg)
pub fn test_rr(&mut self, a: Reg, b: Reg)
Sourcepub fn test_byte_mem_disp32(&mut self, base: Reg, disp: i32, imm: u8)
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.
pub fn add_rr32(&mut self, dst: Reg, src: Reg)
pub fn sub_rr32(&mut self, dst: Reg, src: Reg)
pub fn add_ri(&mut self, dst: Reg, imm: i32)
pub fn sub_ri(&mut self, dst: Reg, imm: i32)
pub fn and_ri(&mut self, dst: Reg, imm: i32)
pub fn or_ri(&mut self, dst: Reg, imm: i32)
pub fn xor_ri(&mut self, dst: Reg, imm: i32)
pub fn cmp_ri(&mut self, a: Reg, imm: i32)
pub fn add_ri32(&mut self, dst: Reg, imm: i32)
pub fn sub_ri32(&mut self, dst: Reg, imm: i32)
pub fn cmp_ri32(&mut self, a: Reg, imm: i32)
Sourcepub fn cmp_mem32_imm(&mut self, base: Reg, disp: i32, imm: i32)
pub fn cmp_mem32_imm(&mut self, base: Reg, disp: i32, imm: i32)
cmp dword [base + disp], imm32
Sourcepub fn cmp_mem32_r(&mut self, base: Reg, disp: i32, src: Reg)
pub fn cmp_mem32_r(&mut self, base: Reg, disp: i32, src: Reg)
cmp dword [base + disp], reg32 (sets flags: mem vs reg)
Sourcepub fn sub_mem64_imm32(&mut self, base: Reg, disp: i32, imm: i32)
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).
Sourcepub fn add_mem64_imm32(&mut self, base: Reg, disp: i32, imm: i32)
pub fn add_mem64_imm32(&mut self, base: Reg, disp: i32, imm: i32)
add qword [base + disp32], imm32
Sourcepub fn movzx_load8_at_index(&mut self, dst: Reg, idx: Reg)
pub fn movzx_load8_at_index(&mut self, dst: Reg, idx: Reg)
movzx r64, byte [idx] — zero-extending u8 load
Sourcepub fn movzx_load16_at_index(&mut self, dst: Reg, idx: Reg)
pub fn movzx_load16_at_index(&mut self, dst: Reg, idx: Reg)
movzx r64, word [idx] — zero-extending u16 load
Sourcepub fn mov_load32_at_index(&mut self, dst: Reg, idx: Reg)
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)
Sourcepub fn mov_load64_at_index(&mut self, dst: Reg, idx: Reg)
pub fn mov_load64_at_index(&mut self, dst: Reg, idx: Reg)
mov r64, qword [idx]
Sourcepub fn mov_store8_at_index(&mut self, idx: Reg, src: Reg)
pub fn mov_store8_at_index(&mut self, idx: Reg, src: Reg)
mov byte [idx], r8
Sourcepub fn mov_store16_at_index(&mut self, idx: Reg, src: Reg)
pub fn mov_store16_at_index(&mut self, idx: Reg, src: Reg)
mov word [idx], r16
Sourcepub fn mov_store32_at_index(&mut self, idx: Reg, src: Reg)
pub fn mov_store32_at_index(&mut self, idx: Reg, src: Reg)
mov dword [idx], r32
Sourcepub fn mov_store64_at_index(&mut self, idx: Reg, src: Reg)
pub fn mov_store64_at_index(&mut self, idx: Reg, src: Reg)
mov qword [idx], r64
Sourcepub fn mov_store8_at_index_imm(&mut self, idx: Reg, imm: u8)
pub fn mov_store8_at_index_imm(&mut self, idx: Reg, imm: u8)
mov byte [idx], imm8
Sourcepub fn mov_store16_at_index_imm(&mut self, idx: Reg, imm: u16)
pub fn mov_store16_at_index_imm(&mut self, idx: Reg, imm: u16)
mov word [idx], imm16
Sourcepub fn mov_store32_at_index_imm(&mut self, idx: Reg, imm: i32)
pub fn mov_store32_at_index_imm(&mut self, idx: Reg, imm: i32)
mov dword [idx], imm32
Sourcepub fn mov_store64_at_index_imm(&mut self, idx: Reg, imm: i32)
pub fn mov_store64_at_index_imm(&mut self, idx: Reg, imm: i32)
mov qword [idx], sign-extended imm32
Sourcepub fn mov_load32_rip_rel(&mut self, dst: Reg, target_va: u64)
pub fn mov_load32_rip_rel(&mut self, dst: Reg, target_va: u64)
mov r32, dword [rip+disp32] (zero-extends to 64-bit)
Sourcepub fn mov_load64_rip_rel(&mut self, dst: Reg, target_va: u64)
pub fn mov_load64_rip_rel(&mut self, dst: Reg, target_va: u64)
mov r64, qword [rip+disp32]
Sourcepub fn mov_store32_rip_rel(&mut self, target_va: u64, src: Reg)
pub fn mov_store32_rip_rel(&mut self, target_va: u64, src: Reg)
mov dword [rip+disp32], r32
Sourcepub fn mov_store64_rip_rel(&mut self, target_va: u64, src: Reg)
pub fn mov_store64_rip_rel(&mut self, target_va: u64, src: Reg)
mov qword [rip+disp32], r64
Sourcepub fn mov_store32_rip_rel_imm(&mut self, target_va: u64, imm: i32)
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.
Sourcepub fn cmp_mem32_rip_rel_r(&mut self, target_va: u64, src: Reg)
pub fn cmp_mem32_rip_rel_r(&mut self, target_va: u64, src: Reg)
cmp dword [rip+disp32], reg32 (sets flags: mem vs reg)
Sourcepub fn add_r64_mem_rip_rel(&mut self, dst: Reg, target_va: u64)
pub fn add_r64_mem_rip_rel(&mut self, dst: Reg, target_va: u64)
add r64, qword [rip+disp32]
Sourcepub fn sub_r64_imm32_patchable(&mut self, dst: Reg, imm: i32)
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.
Sourcepub fn imul_rri32(&mut self, dst: Reg, src: Reg, imm: i32)
pub fn imul_rri32(&mut self, dst: Reg, src: Reg, imm: i32)
imul r32, r32, imm32
Sourcepub fn mul_rdx_rax(&mut self, src: Reg)
pub fn mul_rdx_rax(&mut self, src: Reg)
mul r64 (unsigned RDX:RAX = RAX * src)
Sourcepub fn imul_rdx_rax(&mut self, src: Reg)
pub fn imul_rdx_rax(&mut self, src: Reg)
imul r64 (signed RDX:RAX = RAX * src)
pub fn neg32(&mut self, dst: Reg)
pub fn shift_cl64(&mut self, ext: u8, dst: Reg)
pub fn shift_cl32(&mut self, ext: u8, dst: Reg)
pub fn shl_ri64(&mut self, dst: Reg, imm: u8)
pub fn shr_ri64(&mut self, dst: Reg, imm: u8)
pub fn sar_ri64(&mut self, dst: Reg, imm: u8)
pub fn shl_cl64(&mut self, dst: Reg)
pub fn shr_cl64(&mut self, dst: Reg)
pub fn sar_cl64(&mut self, dst: Reg)
pub fn rol_cl64(&mut self, dst: Reg)
pub fn ror_cl64(&mut self, dst: Reg)
pub fn rol_ri64(&mut self, dst: Reg, imm: u8)
pub fn ror_ri64(&mut self, dst: Reg, imm: u8)
pub fn shl_ri32(&mut self, dst: Reg, imm: u8)
pub fn shr_ri32(&mut self, dst: Reg, imm: u8)
pub fn sar_ri32(&mut self, dst: Reg, imm: u8)
pub fn shl_cl32(&mut self, dst: Reg)
pub fn shr_cl32(&mut self, dst: Reg)
pub fn sar_cl32(&mut self, dst: Reg)
pub fn rol_cl32(&mut self, dst: Reg)
pub fn ror_cl32(&mut self, dst: Reg)
pub fn rol_ri32(&mut self, dst: Reg, imm: u8)
pub fn ror_ri32(&mut self, dst: Reg, imm: u8)
Sourcepub fn movsx_8_64(&mut self, dst: Reg, src: Reg)
pub fn movsx_8_64(&mut self, dst: Reg, src: Reg)
movsx r64, r8 (sign-extend 8→64)
Sourcepub fn movsx_16_64(&mut self, dst: Reg, src: Reg)
pub fn movsx_16_64(&mut self, dst: Reg, src: Reg)
movsx r64, r16 (sign-extend 16→64)
Sourcepub fn movzx_8_64(&mut self, dst: Reg, src: Reg)
pub fn movzx_8_64(&mut self, dst: Reg, src: Reg)
movzx r64, r8 (zero-extend 8→64)
Sourcepub fn movzx_16_64(&mut self, dst: Reg, src: Reg)
pub fn movzx_16_64(&mut self, dst: Reg, src: Reg)
movzx r32, r16 (zero-extends to 64 due to 32-bit operation)
Sourcepub fn movzx_32_64(&mut self, dst: Reg, src: Reg)
pub fn movzx_32_64(&mut self, dst: Reg, src: Reg)
Zero-extend 32→64: mov r32, r32 (implicit zero-extend)
Sourcepub fn popcnt32(&mut self, dst: Reg, src: Reg)
pub fn popcnt32(&mut self, dst: Reg, src: Reg)
popcnt r32, r32 (result zero-extended to 64 bits)
pub fn push(&mut self, reg: Reg)
pub fn pop(&mut self, reg: Reg)
Sourcepub fn push_imm32(&mut self, imm: i32)
pub fn push_imm32(&mut self, imm: i32)
push sign-extended imm32 (5 bytes: 0x68 + imm32).
Sourcepub fn jmp_label(&mut self, label: Label)
pub fn jmp_label(&mut self, label: Label)
jmp to label — uses rel8 for backward jumps within ±127 bytes.
Sourcepub fn jcc_label(&mut self, cc: Cc, label: Label)
pub fn jcc_label(&mut self, cc: Cc, label: Label)
jcc to label — uses rel8 for backward jumps within ±127 bytes.
Sourcepub fn call_label(&mut self, label: Label)
pub fn call_label(&mut self, label: Label)
call label
Sourcepub fn lea_32(&mut self, dst: Reg, base: Reg, disp: i32)
pub fn lea_32(&mut self, dst: Reg, base: Reg, disp: i32)
lea r32, [base + disp] — 32-bit result, zero-extends to 64-bit.
Sourcepub fn lea_sib_scaled_32(
&mut self,
dst: Reg,
base: Reg,
index: Reg,
scale_log2: u8,
)
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
Sourcepub fn label_offset(&self, label: Label) -> Option<usize>
pub fn label_offset(&self, label: Label) -> Option<usize>
Get the resolved native offset for a label (only valid after bind_label).