|
18 | 18 |
|
19 | 19 | ## Note |
20 | 20 |
|
21 | | -Support for every single instruction is **NOT** planned. |
22 | | -Nor will there be any passes for optimization. |
| 21 | +`dasm` has a goal of acting as a lightweight, simple instructions for compilers. |
23 | 22 |
|
24 | | -This has a simple goal of assembling instructions for compilers. |
25 | | -If you want a fully featured library, please refer to [`Iced`](https://github.com/icedland/iced) |
| 23 | +If you want a higher-level library or something more comprehensive, there's other great solutions like [`Iced`](https://github.com/icedland/iced) or [`dynasm-rs`](https://github.com/CensoredUsername/dynasm-rs). |
26 | 24 |
|
27 | 25 | ## How it works |
28 | 26 |
|
29 | 27 | Code generation doesn't have to be hard. This just provides explicit functions for generating instructions. |
30 | | -No abstractions for the sake of safety or optimization which add complexity. If you just want to write assembly, this is for you. |
31 | | - |
32 | | -**This library has tiered abstraction levels.** |
33 | | - |
34 | | -### Raw |
35 | | - |
36 | | -This gives you access to the "raw" bytes from an instruction given untagged numeric arguments. |
37 | | -Despite how it sounds, it is pretty nice to use on its own. |
| 28 | +No abstractions through macros, or some DSL you need to learn. Just functions. |
38 | 29 |
|
39 | 30 | **Example** |
40 | 31 |
|
41 | 32 | ```rust |
| 33 | +use dasm::tier::raw::amd64::*; |
| 34 | + |
42 | 35 | let rax = 0; |
43 | 36 | let rsi = 6; // Argument 2 |
44 | 37 | let rdi = 7; // Argument 1 |
45 | 38 |
|
46 | 39 | let asm = [ |
47 | | - &dasm::tier::raw::amd64::mov_r64_r64(rax, rdi) as &[u8], |
48 | | - &dasm::tier::raw::amd64::add_r64_r64(rax, rsi), |
49 | | - &dasm::tier::raw::amd64::ret() |
| 40 | + &mov_r64_r64(rax, rdi) as &[u8], |
| 41 | + &add_r64_r64(rax, rsi), |
| 42 | + &ret() |
50 | 43 | ].concat(); |
51 | 44 |
|
52 | | -// A helper for making memory executable is included. |
| 45 | +// Allocate an executable memory block |
53 | 46 | let mmapped = dasm::mmap::Mmap::exec(&asm) |
54 | 47 | .expect("Failed to mmap"); |
55 | 48 |
|
56 | | -// Simply cast the bytes to the function you just made. |
| 49 | +// Simply cast that memory into a function to call it. |
57 | 50 | let adder: extern "C" fn(x: u64, y: u64) -> u64 = unsafe { std::mem::transmute(mmapped.as_ptr()) }; |
58 | 51 | assert_eq!(adder(5, 200), 205); |
59 | 52 | ``` |
60 | 53 |
|
61 | | -There's also an example showcasing a tiny AOT compiled lisp at [`examples/tinylisp`](https://github.com/DvvCz/dasm/tree/master/examples/tinylisp). |
62 | | - |
63 | | -## Other Tiers |
| 54 | +*There's also an example showcasing a tiny AOT compiled lisp at [`examples/tinylisp`](https://github.com/DvvCz/dasm/tree/master/examples/tinylisp).* |
64 | 55 |
|
65 | | -At the moment, other tiers are not implemented as I plan out how these abstractions would go. |
66 | | - |
67 | | -Hopefully they'd involve abstracting away overloads with tagged enums and cross architecture compatibility. |
68 | 56 |
|
69 | 57 | ## Why |
70 | 58 |
|
71 | | -I felt the need for an assembler. |
72 | | - |
73 | | -LLVM was out of the question due to its size and difficult integration to Rust. |
74 | | - |
75 | | -I struggled to work with Cranelift due to its complexity for the sake of safety and performance. |
76 | | - |
77 | | -But sometimes, you don't care about safety or performance. You just want a simple solution to get it done. |
| 59 | +All of the other solutions are either too big for my usecase (`LLVM`), too complex (`Cranelift`) or have too many abstractions. |
| 60 | +Sometimes, you don't need all of that - you just need to write some assembly. |
| 61 | +That's what `dasm` is for. |
78 | 62 |
|
79 | | -That's what `dasm` is supposed to be. |
| 63 | +*Of course - No shade to any other library. Anyone can use the tool they prefer.* |
0 commit comments