code wiki / (root) / nx_x86_64_test.nx

nx_x86_64_test.nx source

↩ module page · 67 lines · 2332 B

1// nx_x86_64_test.nx -- foundation smoke for the x86_64 emit library. 2// 3// Hand-sequences nx_x86_64 primitives to build a write+exit program 4// asm file, prints it to stdout. The companion bash wrapper then 5// assembles + links + runs the produced binary natively on x86_64. 6// 7// Two layers verified by this smoke: 8// 1. Each emit primitive produces the expected asm text (this file). 9// 2. The asm assembles + runs natively (bench/nx_x86_64_smoke.sh). 10// 11// The hand-built asm is the canonical "hello world" + sys_exit(0). 12 13import "syscalls.nx" 14import "nx_outbuf.nx" 15import "nx_x86_64.nx" 16 17func main() -> i64 { 18 let o: *OutBuf = out_new(4096) 19 20 let main_name: *u8 = "main" as *u8 21 let _start_name: *u8 = "_start" as *u8 22 let msg_label: *u8 = ".Lhello" as *u8 23 let msg: *u8 = "x86 native hello via nx_x86_64\n" as *u8 24 let msg_len: i64 = 31 25 26 // Header comment. 27 out_str(o, "# Emitted by nx_x86_64.nx (foundation session 1)\n") 28 out_str(o, " .intel_syntax noprefix\n") 29 out_str(o, " .att_syntax prefix\n") 30 31 // _start: call main; mov rax, 60; mov rdi, 0; syscall 32 x86_emit_function_start(o, _start_name) 33 out_str(o, " call main\n") 34 x86_emit_movabsq(o, "rax" as *u8, NX_X64_SYS_EXIT) 35 x86_emit_movabsq(o, "rdi" as *u8, 0) 36 x86_emit_syscall(o) 37 x86_emit_function_end(o, _start_name) 38 39 // main: write(1, .Lhello, len); ret 40 x86_emit_function_start(o, main_name) 41 x86_emit_prologue(o, 16) 42 x86_emit_syscall_imm(o, NX_X64_SYS_WRITE, 3, 43 1, 0, msg_len, 0, 0, 0) 44 // patch rsi to the leaq result (overwrites the movabsq above) 45 // -- for V1 simplicity, just emit a second leaq + redo the 46 // syscall. Cleaner pattern in session 2. 47 x86_emit_leaq_rip(o, msg_label, "rsi" as *u8) 48 x86_emit_movabsq(o, "rdi" as *u8, 1) 49 x86_emit_movabsq(o, "rdx" as *u8, msg_len) 50 x86_emit_movabsq(o, "rax" as *u8, NX_X64_SYS_WRITE) 51 x86_emit_syscall(o) 52 // Return 0. 53 x86_emit_movabsq(o, "rax" as *u8, 0) 54 x86_emit_epilogue(o) 55 x86_emit_function_end(o, main_name) 56 57 // .rodata: .Lhello:.asciz "..." 58 x86_emit_section_rodata(o) 59 x86_emit_label(o, msg_label) 60 x86_emit_asciz(o, msg, msg_len) 61 62 x86_emit_gnu_stack_note(o) 63 64 // Write the buffer to stdout. 65 sys_write(1, o.buf, o.pos) 66 return 0 67}