#jit #assembler #dynasm #dynasmrt #dynasm-rs

nightly macro dynasm

A plugin for assembling code at runtime. Combined with the runtime crate dynasmrt it can be used to write JIT compilers easily.

21 unstable releases (5 breaking)

✓ Uses Rust 2018 edition

0.5.1 Sep 15, 2019
0.4.0 Aug 26, 2019
0.3.2 Apr 11, 2019
0.3.1 Mar 5, 2019
0.0.6 Oct 27, 2016

#2 in Emulators

Download history 66/week @ 2019-06-02 128/week @ 2019-06-09 86/week @ 2019-06-16 209/week @ 2019-06-23 138/week @ 2019-06-30 163/week @ 2019-07-07 74/week @ 2019-07-14 135/week @ 2019-07-21 660/week @ 2019-07-28 668/week @ 2019-08-04 166/week @ 2019-08-11 464/week @ 2019-08-18 578/week @ 2019-08-25 801/week @ 2019-09-01 783/week @ 2019-09-08

1,644 downloads per month
Used in 8 crates (4 directly)

MPL-2.0 license

780KB
16K SLoC

A Dynamic assembler written in Rust for Rust.

The purpose of this tool is to ease the creation of programs that require run-time assembling.

It is currently in beta, meaning that everything is operational, but some APIs might change in the future.

Build Status

#dynasm-rs on irc.mozilla.org

Features

  • Fully integrated in the rust toolchain, no other tools necessary.
  • The assembly is optimized into a series of Vec.push and Vec.extend statements.
  • Errors are almost all diagnosed at compile time in a clear fashion.
  • Write the to be generated assembly inline in nasm-like syntax using a simple macro.

Documentation

Documentation can be found here.

Support

  • Supports the x64/x86 instruction sets in long and protected mode with every AMD/Intel/VIA extension except for AVX-512.
  • Supports the aarch64 instruction set up to ARMv8.4 except for SVE instructions.

Example

#![feature(plugin)]
#![plugin(dynasm)]

#[macro_use]
extern crate dynasmrt;

use dynasmrt::{DynasmApi, DynasmLabelApi};

use std::{io, slice, mem};
use std::io::Write;

fn main() {
    let mut ops = dynasmrt::x64::Assembler::new().unwrap();
    let string = "Hello World!";

    dynasm!(ops
        ; ->hello:
        ; .bytes string.as_bytes()
    );

    let hello = ops.offset();
    dynasm!(ops
        ; lea rcx, [->hello]
        ; xor edx, edx
        ; mov dl, BYTE string.len() as _
        ; mov rax, QWORD print as _
        ; sub rsp, BYTE 0x28
        ; call rax
        ; add rsp, BYTE 0x28
        ; ret
    );

    let buf = ops.finalize().unwrap();

    let hello_fn: extern "win64" fn() -> bool = unsafe {
        mem::transmute(buf.ptr(hello))
    };

    assert!(
        hello_fn()
    );
}

pub extern "win64" fn print(buffer: *const u8, length: u64) -> bool {
    io::stdout().write_all(unsafe {
        slice::from_raw_parts(buffer, length as usize)
    }).is_ok()
}

Background

This project is heavily inspired by Dynasm

License

Mozilla Public License, v. 2.0, see LICENSE

Copyright 2016 CensoredUsername

Guaranteed to be working compiler versions

This project used to be a compiler plugin, so for old compilers, here's a list of which version of dynasm was guaranteed to work with which compiler. As the project has since transitioned to be a proc macro, this is not relevant for modern versions of the compiler.

  • v0.2.0: rustc 1.27.0-nightly (ac3c2288f 2018-04-18)
  • v0.2.1: rustc 1.28.0-nightly (a1d4a9503 2018-05-20)
  • v0.2.3: rustc 1.31.0-nightly (96cafc53c 2018-10-09)

Dependencies

~0.8–1MB
~24K SLoC