Slide 1

Slide 1 text

Rustでつくるx86アセンブラ monochrome twitter: @s_isshiki1969 Slack: プログラミング言語処理系が好きな人の集まり https://prog-lang-sys-ja-slack.github.io/wiki/ monoasm: https://github.com/sisshiki1969/monoasm

Slide 2

Slide 2 text

アセンブラ is 何 int main() { return 42; } main: push rbp mov rbp, rsp mov eax, 42 pop rbp ret 55 48 89 e5 b8 2a 00 00 00 5d c3 0f 1f 00 hoge.c hoge.s hoge.o これ アセンブリのテキストファイルを機械語へ変換

Slide 3

Slide 3 text

インラインアセンブラ in Rust let i: u64 = 3; let o: u64; unsafe { asm!( "mov {0}, {1}", "add {0}, {number}", out(reg) o, in(reg) i, number = const 5, ); } 1. asmマクロのある位置に機械語を挿入 2. 変数や値を埋め込むことができる

Slide 4

Slide 4 text

ダイナミックアセンブラ ● 「実行時に機械語を吐くコード」を生成するライブラリ ● メモリ上に機械語を格納するバッファを確保し、実行中にそこへ機械語を 生成していく ● 応用例としてはJITコンパイラなど ● 例:Xbyak(C++、テンプレート)   DynASM(C、プリプロセッサ)   monoasm(Rust、手続きマクロ)

Slide 5

Slide 5 text

手続きマクロ(proc macro) マクロの中身をRustコードへ変換するRustプログラム monoasm!(jit, pushq rbp;) jit.enc_o(80, Reg::from(5));

Slide 6

Slide 6 text

fn hello_world() { let func = hello(); func(()); } fn hello() -> fn(()) -> () { let hello = "hello world!\n"; let mut jit = JitMemory::new(); let label = jit.label(); monoasm!(jit, // prologue pushq rbp; movq rbp, rsp; pushq r15; pushq r14; movq r15, (hello.as_ptr() as u64); movq r14, 13; label: movq rdi, [r15]; movq rax, (test::PUTC as u64); call rax; addq r15, 1; subq r14, 1; cmpq r14, 0; jne label; // epilogue popq r14; popq r15; movq rsp, rbp; popq rbp; ret; ); jit.finalize() }

Slide 7

Slide 7 text

jit.enc_o(80, Reg::from(5)); jit.enc_rexw_mr(0x89, Reg::from(4), Or::reg(Reg::from(5))); jit.emitb(0xe8); jit.save_reloc(fac, 4); jit.emitl(0); jit.enc_rexw_mr(0x89, Reg::from(0), Or::reg(Reg::from(15))); jit.enc_rexw_mr(0x89, Reg::from(0), Or::reg(Reg::from(6))); let imm = fmt.as_ptr() as u64; let rm_op = Or::reg(Reg::from(7)); if imm == 0 { jit.enc_rexw_mr(49, Reg::from(7), Or::reg(Reg::from(7))); } else if imm <= 0xffff_ffff { jit.enc_rexw_mi(0xc7, rm_op); jit.emitl(imm as u32); } else { jit.enc_rexw_o(0xb8, Reg::from(7)); jit.emitq(imm); }; monoasm!が吐くRustコード

Slide 8

Slide 8 text

monoruby ● Rubyっぽい文法 ● 変数は整数のみ、四則演算できる ● if文が使える ● 関数・ローカル変数が使える ● パーサはnomを使用 ● 抽象構文木をアセンブリに変換

Slide 9

Slide 9 text

加算命令のコード生成 R12 R13 3 R14 5 R15 stack top R12 R13 8 R14 5 R15 stack top

Slide 10

Slide 10 text

条件分岐のコード生成

Slide 11

Slide 11 text

monoruby 1.064 s JS(node) 2.035 s C 0.763 s Ruby 10.700 s Benchmark