summaryrefslogtreecommitdiff
path: root/source/blog/regmap.md
blob: e792398445181d130cdefa5e57f0ab963ebb3371 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
# regmap

an april fools prank but make it March. [the README says it best](https://github.com/iximeow/regmap#regmap):

> `regmap` handles this design oversight by allowing users to memory-map the processor's general-purpose registers (GPR).

and

> # why
> because it's funny

but more seriously, [`regmap`'s emulation](https://github.com/iximeow/regmap/blob/no-gods-no-/src/regmap.rs#L442-L746) of x86 was a first draft of how i might want to describe instruction semantics like i eventually did in [`yaxpeax-core`](https://github.com/iximeow/yaxpeax-core/blob/no-gods-no-/src/arch/x86_64/semantic.rs#L266). this is where i discovered that `do_binop` and its approach, as well as `conditional_loc_write` as it eventually was written in `yaxpeax-core`, don't work as well with dead code elimination (circa 2021 Rust) as i'd wanted.

and anyway, sometimes i forget that `regmap` made it possible to write this [disorienting mess of a program](https://github.com/iximeow/regmap/blob/no-gods-no-/examples/hello_world.rs):
```
use regmap::registers::*;

fn main() {
    unsafe { regmap::map_registers(); }

    println!("rsp: {:x}", RSP.load());
    RSP.sub_assign(8);
    RIP.store(lol as u64);
}

fn lol() {
    println!("very good");
    RSP.sub_assign(8);
    RDI.store(1);
    RSI.store(1234);
    RIP.store(lol_args as u64);
}

fn lol_args(a1: u64, a2: u64) {
    println!("a1: {}, a2: {}", a1, a2);
    println!("goodbye!");
    std::process::exit(0);
}
```
which, you guessed it (?), prints out
```
rsp: 0xwhatever
very good
a1: 1, at: 1234
goodbye!
```