code wiki / (root) / crt0.nx

crt0.nx source

↩ module page · 56 lines · 2412 B

1// crt0.nx -- sovereign `_start` stub for NishiLang programs. 2// 3// Replaces the libc/crt0 that C programs silently link against. 4// The Linux kernel hands us a stack laid out like: 5// 6// sp ------------------------> argc (i64) 7// sp + 8 --------------------> argv[0] (*u8, program name) 8// sp + 16 -------------------> argv[1] (*u8, first real arg) 9// ... 10// sp + 8 + argc*8 -----------> NULL 11// ... envp[0], ..., NULL, auxv... 12// 13// We translate that into the (argc, argv) signature parse.nx expects 14// for main() -- a0 = argc, a1 = argv -- then call main. On return, 15// exit(a0) via the SYS_exit (93) syscall. 16// 17// This file defines `_start` only as source TEXT because NishiLang 18// doesn't yet have a way to declare symbols at specific file offsets 19// or pin a function's emission order. Drivers emit this text at the 20// head of their assembled output so it lands at the ELF entry point. 21// 22// Usage (see runtime/nxc.nx): 23// emit_start_stub(asm_buf) 24// // ... emit user's functions ... 25// assemble(asm_buf, ...) 26// write_elf(code, code_len, fd) 27 28// Canonical nx_-prefixed import per family convention. Was 29// "outbuf.nx" which transitively pulled in syscalls.nx (no nx_ 30// prefix) -- duplicated sys_* symbols against nx_syscalls.nx 31// that the rest of the self-host chain uses. Result: link-time 32// "symbol sys_ioctl already defined" failure on every nxc.elf 33// rebuild (2026-05-16 bug class). Fixed by importing nx_outbuf.nx 34// (the canonical nx_-prefixed variant) which imports nx_syscalls.nx. 35import "nx_outbuf.nx" 36 37// Inject the 5-instruction `_start` prologue + epilogue into `o`. 38// Expected layout after assembly: 39// 0x10078: ld a0, 0(sp) ; 0x00013503 40// 0x1007C: addi a1, sp, 8 ; 0x00810593 41// 0x10080: call main ; 0x???????ef (patched by nxasm) 42// 0x10088: li a7, 93 ; 0x05D00893 43// 0x1008C: ecall ; 0x00000073 44// 45// Total: 20 bytes (call is JAL = 4 bytes). Entry point stays at 0x10078. 46func emit_crt0_start(o: *OutBuf) -> i64 { 47 out_str(o, "\n .text\n") 48 out_str(o, " .globl _start\n") 49 out_str(o, "_start:\n") 50 out_str(o, " ld a0, 0(sp)\n") 51 out_str(o, " addi a1, sp, 8\n") 52 out_str(o, " call main\n") 53 out_str(o, " li a7, 93\n") 54 out_str(o, " ecall\n") 55 return 0 56}