From 7f4dd3b4298a2f0aae9a6715082e3b9407105800 Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sat, 23 May 2026 17:48:55 +0200 Subject: [PATCH] tests --- kern.h | 2 +- kern_wasm.asm | 93 +++++++++++++++++++++++++++++++-------------------- nwtests.c | 43 ++++++++++++------------ 3 files changed, 79 insertions(+), 59 deletions(-) diff --git a/kern.h b/kern.h index d07ca87..e218f1b 100644 --- a/kern.h +++ b/kern.h @@ -15,7 +15,7 @@ extern void KERN_CALL xmemmove(void *ziel, void *quelle, UI anz); extern int KERN_CALL Net_Call(UI func, void *req, void *repl); extern int KERN_CALL C32_LoadNios_Probe(UI axfunc, void *outbuf); extern int KERN_CALL C32_GetFunc_Probe(char *name, void *outbuf); -extern int KERN_CALL C32_CallName0_Probe(char *name, void *outbuf); +extern int KERN_CALL C32_CallVersion_Nios_Probe(void *outbuf); extern int KERN_CALL Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx, void *req, void *repl, UI p1, UI p2, UI p3); diff --git a/kern_wasm.asm b/kern_wasm.asm index a8af853..fbb8c8d 100644 --- a/kern_wasm.asm +++ b/kern_wasm.asm @@ -22,7 +22,7 @@ public _xmemmove public _Net_Call public _C32_LoadNios_Probe public _C32_GetFunc_Probe -public _C32_CallName0_Probe +public _C32_CallVersion_Nios_Probe public _Net_Call_VLM_Raw _IPXinit proc far @@ -467,26 +467,34 @@ c32get_store: _C32_GetFunc_Probe endp -; int C32_CallName0_Probe(char *name, void *outbuf) +; int C32_CallVersion_Nios_Probe(void *outbuf) ; -; Resolve Client32 function by name via NIOS resolver returned by D8C1, -; then call resolved function with zero arguments. -; -; This is safe for CLIENT32GetVersion. Do not use for functions needing args. +; Safe Client32 version call using the exact d32wrap convention: +; 1) INT 2F AX=D8C1 +; 2) use ESI resolver to resolve "CLIENT32GetVersion" +; 3) call ECX trampoline, not the function pointer directly: +; push 0 +; push 0 +; push fn_seg +; push fn_off +; call ECX +; add sp,8 ; ; outbuf: ; +00 load AX -; +02 resolver ptr off -; +04 resolver ptr seg -; +06 resolved fn off -; +08 resolved fn seg -; +0A call return AX -; +0C call return DX -; +0E call return FLAGS -_C32_CallName0_Probe proc far +; +02 resolver off +; +04 resolver seg +; +06 trampoline off +; +08 trampoline seg +; +0A fn off +; +0C fn seg +; +0E call AX +; +10 call DX +; +12 flags +_C32_CallVersion_Nios_Probe proc far push bp mov bp, sp - sub sp, 8 + sub sp, 12 push ds push es @@ -501,47 +509,51 @@ _C32_CallName0_Probe proc far mov ax, 0D8C1h int 2Fh - ; save resolver ESI at [bp-4] + ; save ESI resolver at [bp-4] db 66h, 89h, 76h, 0FCh + ; save ECX trampoline at [bp-8] + db 66h, 89h, 4Eh, 0F8h - push ax ; load AX - + push ax ; load AX for output or ax, ax - jne c32call_store_fail + jne c32ver_fail - ; resolve function name: - ; push name segment, name offset, 0, 0; call resolver; add sp,8 - push word ptr [bp+8] - push word ptr [bp+6] + push cs + push offset c32ver_name push 0 push 0 call dword ptr [bp-4] add sp, 8 - ; save resolved function pointer DX:AX at [bp-8] - mov word ptr [bp-8], ax - mov word ptr [bp-6], dx + ; resolver returns DX:AX function pointer + mov [bp-12], ax + mov [bp-10], dx or ax, dx - je c32call_store_fail2 + je c32ver_fail - ; call resolved function with zero args + ; d32wrap _CLIENT32GetVersion convention: + push 0 + push 0 + push word ptr [bp-10] + push word ptr [bp-12] call dword ptr [bp-8] + add sp, 8 + pushf push dx push ax - jmp short c32call_store + jmp short c32ver_store -c32call_store_fail2: +c32ver_fail: xor dx, dx xor ax, ax -c32call_store_fail: pushf push dx push ax -c32call_store: - les di, dword ptr [bp+10] +c32ver_store: + les di, dword ptr [bp+6] pop ax ; call AX pop dx ; call DX @@ -557,9 +569,13 @@ c32call_store: mov es:[di+6], cx mov cx, word ptr [bp-6] mov es:[di+8], cx - mov es:[di+10], ax - mov es:[di+12], dx - mov es:[di+14], bx + mov cx, word ptr [bp-12] + mov es:[di+10], cx + mov cx, word ptr [bp-10] + mov es:[di+12], cx + mov es:[di+14], ax + mov es:[di+16], dx + mov es:[di+18], bx popf pop di @@ -570,7 +586,10 @@ c32call_store: pop bp xor ah, ah ret -_C32_CallName0_Probe endp + +c32ver_name db 'CLIENT32GetVersion',0 + +_C32_CallVersion_Nios_Probe endp end diff --git a/nwtests.c b/nwtests.c index 97bf43d..c5dfb8b 100644 --- a/nwtests.c +++ b/nwtests.c @@ -1218,42 +1218,43 @@ static int tests_c32getfunc(void) } -static int tests_c32callver(void) +static int tests_c32callver2(void) { uint8 out[32]; uint16 load_ax; uint16 res_off, res_seg; + uint16 tramp_off, tramp_seg; uint16 fn_off, fn_seg; uint16 call_ax, call_dx, flags; memset(out, 0, sizeof(out)); - fprintf(stdout, "TEST C32CALLVER\n"); - fprintf(stdout, "Resolve and call CLIENT32GetVersion with zero args\n\n"); + fprintf(stdout, "TEST C32CALLVER2\n"); + fprintf(stdout, "Call CLIENT32GetVersion through ECX NIOS trampoline\n\n"); - C32_CallName0_Probe("CLIENT32GetVersion", out); + C32_CallVersion_Nios_Probe(out); - load_ax = tests_get_word_lh(out + 0); - res_off = tests_get_word_lh(out + 2); - res_seg = tests_get_word_lh(out + 4); - fn_off = tests_get_word_lh(out + 6); - fn_seg = tests_get_word_lh(out + 8); - call_ax = tests_get_word_lh(out + 10); - call_dx = tests_get_word_lh(out + 12); - flags = tests_get_word_lh(out + 14); + load_ax = tests_get_word_lh(out + 0); + res_off = tests_get_word_lh(out + 2); + res_seg = tests_get_word_lh(out + 4); + tramp_off = tests_get_word_lh(out + 6); + tramp_seg = tests_get_word_lh(out + 8); + fn_off = tests_get_word_lh(out + 10); + fn_seg = tests_get_word_lh(out + 12); + call_ax = tests_get_word_lh(out + 14); + call_dx = tests_get_word_lh(out + 16); + flags = tests_get_word_lh(out + 18); fprintf(stdout, "Load AX=%04X\n", load_ax); - fprintf(stdout, "Resolver=%04X:%04X\n", res_seg, res_off); + fprintf(stdout, "Resolver=%04X:%04X Trampoline=%04X:%04X\n", + res_seg, res_off, tramp_seg, tramp_off); fprintf(stdout, "Function=%04X:%04X\n", fn_seg, fn_off); fprintf(stdout, "Call returned DX:AX=%04X:%04X FLAGS=%04X\n", call_dx, call_ax, flags); - tests_dump_bytes("RAW:", out, 16); - - if (fn_off || fn_seg) - fprintf(stdout, "\nFunction pointer resolved.\n"); - if (call_ax || call_dx) - fprintf(stdout, "Call returned non-zero version value.\n"); + tests_dump_bytes("RAW:", out, 20); + if (load_ax == 0 && (fn_off || fn_seg)) + fprintf(stdout, "\nNIOS trampoline path resolved successfully.\n"); return(0); } @@ -1273,8 +1274,8 @@ int func_tests(int argc, char *argv[], int mode) if (tests_same_arg(argv[1], "C32GETFUNC")) return tests_c32getfunc(); - if (tests_same_arg(argv[1], "C32CALLVER")) - return tests_c32callver(); + if (tests_same_arg(argv[1], "C32CALLVER2")) + return tests_c32callver2(); if (tests_same_arg(argv[1], "NWREQ87")) return tests_nwreq87(argc, argv);