nx_pe_compile_win_write.nx
buildroot/runtime/nx_pe_compile_win_write.nx
about
nx_pe_compile_win_write.nx -- W3b-3: a compiled organ's OWN sys_write reaches WriteFile.
Composes W3b-1 (proven GetStdHandle+WriteFile MS-x64 ABI) with W3b-2 (keystone-as-linker thunk
redirect). The nxc2-COMPILED `main` calls a NishiLang shim `nx_win_write(fd, buf, n)`; the keystone
redirects that call to a synthesized thunk that performs the FULL kernel32 console write -- with
fd/buf/n flowing from the compiled code's SysV registers into the MS-x64 call. So an organ that
writes `nx_win_write(1, "...", N)` in NishiLang prints "..." natively on Windows. No compiler edits.
shim entry (overwritten): jmp <thunk> ; E9 rel32
thunk (appended .text; SysV in rdi=fd[ignored, stdout], rsi=buf, rdx=n):
sub rsp, 0x38 ; shadow(0x20)+arg5+&written+saved-n; keeps 16-byte align at call
mov [rsp+0x30], rdx ; save n (rdx is MS-x64 VOLATILE -> clobbered by GetStdHandle)
mov ecx, -11 ; STD_OUTPUT_HANDLE
call [rip+GetStdHandle] ; rax=handle; rsi(buf) survives (rsi is MS-x64 NON-volatile)
mov rcx, rax ; arg1 handle
mov rdx, rsi ; arg2 buf
mov r8, [rsp+0x30] ; arg3 n
lea r9, [rsp+0x28] ; arg4 &bytesWritten (stack scratch)
mov qword [rsp+0x20], 0 ; arg5 lpOverlapped = NULL
call [rip+WriteFile] ; rax = BOOL
add rsp, 0x38
ret ; back to the SysV caller (rsi/rdi are SysV-volatile, fine)
NO-FALSE-GREEN: source `{ let w = nx_win_write(1, "NISHI-W3B3\n", N); return w + 92 }`. The `+92`
forces a real `call` (not a tail-call jmp) and keeps the call live (not DCE'd). The string lives in
the COMPILED program's .rodata and is passed via rsi; the count N is passed via rdx. POS prints
"NISHI-W3B3\n" (11). LEN-CONTROL passes N=5 -> prints only "NISHI" (5 bytes) => the count flows from
the compiled call into WriteFile's r8. Tamper (corrupt WriteFile import name) => no output / fail.
PIPELINE (build WSL sovereign, run native): src.nx
-> ./_offc/nx_compile_x86_native.elf <src> > /tmp/nxwin.s
-> ./_offc/nx_sov_build_run.elf nx_pe_compile_win_write (reads /tmp/nxwin.s)
-> _offc/nx_win_compiled_write.exe -> run native on Windows 11.
HONEST SCOPE: stdout only (fd ignored; STD_OUTPUT hardcoded), one shim name (nx_win_write). Next:
fd->handle mapping (stderr), a shim-name->import table for read/open/close, then nx_syscalls' own
sys_write lowers here so any I/O organ compiles native. Replicates keystone assemble (reuses
axc_pass; no shared-assembler edit). lineage_id: substrate_pe_compile_win_write_v1
dependencies 3 imports · 0 importers
imports: nx_syscalls.nxnxasm_x86.nxnx_pe_writer.nx
imported by: nobody (leaf or entry point)
call flow from main pre-order; caps 40 nodes / depth 6 declared; ↻ = already shown
structs
| none |
consts
| 44 | const NXW_CODE_CAP: i64 = 1048576 |
| 45 | const NXW_FILE_SIZE: i64 = 0x800 // headers + .text + .rdata + .idata (W3b-1 3-import layout) |
| 46 | const NXW_STUB_LEN: i64 = 18 // entry stub: sub rsp,0x28;call main;mov ecx,eax;call ExitProcess;int3 |
| 47 | const NXW_THUNK_LEN: i64 = 56 // GetStdHandle+WriteFile returning thunk |
| 48 | const NXW_TEXT_CAP: i64 = 0x200 // one .text file chunk (stub + compiled code + thunk) |
| 49 | const NXW_RVA_TEXT: i64 = 0x1000 |
| 50 | const NXW_RVA_RDATA: i64 = 0x2000 |
| 51 | const NXW_RVA_IDATA: i64 = 0x3000 |
| 52 | const NXW_FOFF_TEXT: i64 = 0x200 |
| 53 | const NXW_FOFF_RDATA:i64 = 0x400 |
| 54 | const NXW_FOFF_IDATA:i64 = 0x600 |
| 55 | const NXW_IAT_GSH: i64 = 0x3048 // IAT GetStdHandle RVA (W3b-1 layout) |
| 56 | const NXW_IAT_WF: i64 = 0x3050 // IAT WriteFile RVA |
| 57 | const NXW_IAT_EXIT: i64 = 0x3058 // IAT ExitProcess RVA |
functions
| 60 | func nxw_assemble(src: *u8, n: i64, out: *u8, out_cap: i64, p_main: *i64, p_shim: *i64) -> i64 |
| 99 | func nxw_emit_pe(buf: *u8, code: *u8, code_len: i64, main_off: i64, shim_off: i64) -> i64 |
| 206 | func main() -> i64 |