; kern_wasm.asm ; ; Open Watcom WASM/MASM-syntax port of the old TASM IDEAL kern.asm. ; Intended for 16-bit DOS large memory model builds on Linux with Open Watcom v2. ; ; Keep kern.asm as the historical TASM source and use this file for the ; reproducible Open Watcom build. .286 .model large .data enterIPX dd 0 .code public _IPXinit public _IPXopen_socket public _IPXclose_socket public _IPXlisten public _xmemmove public _Net_Call public _C32_LoadNios_Probe public _C32_GetFunc_Probe public _C32_CallVersion_Nios_Probe public _C32_MapLock_Probe public _C32_NCP87_Raw_Probe public _Net_Call_VLM_Raw _IPXinit proc far push bp mov bp, sp push ds push si push di mov ax, 7A00h int 2Fh cmp al, 0FFh jne ipxinit_done mov cx, @data mov ds, cx mov word ptr enterIPX, di mov ax, es mov word ptr enterIPX+2, ax mov al, 1 ipxinit_done: mov ah, 0 pop di pop si pop ds pop bp ret _IPXinit endp _xmemmove proc far push bp mov bp, sp ; far procedure stack layout, large model: ; [bp+0] old bp ; [bp+2] return offset ; [bp+4] return segment ; [bp+6] z offset ; [bp+8] z segment ; [bp+10] q offset ; [bp+12] q segment ; [bp+14] nmbr cli mov cx, [bp+14] or cx, cx jz xmem_done push ds push si push di pushf lds si, dword ptr [bp+10] les di, dword ptr [bp+6] cmp di, si jl xmem_forward std dec cx add di, cx add si, cx inc cx jmp xmem_copy xmem_forward: cld xmem_copy: rep movsb popf pop di pop si pop ds xmem_done: pop bp sti ret _xmemmove endp _IPXopen_socket proc far push bp mov bp, sp push ds push si push di ; int IPXopen_socket(UI sock, int live) mov ax, [bp+8] ; live mov dx, [bp+6] ; sock mov bx, @data mov ds, bx mov bx, 0 call dword ptr enterIPX cmp al, 0FFh jne ipxopen_not_already mov ax, -1 ; socket already open jmp ipxopen_done ipxopen_not_already: cmp al, 0FEh jne ipxopen_ok mov ax, -2 ; socket table full jmp ipxopen_done ipxopen_ok: mov ax, dx ipxopen_done: pop di pop si pop ds pop bp ret _IPXopen_socket endp _IPXclose_socket proc far push bp mov bp, sp push ds push si push di ; void IPXclose_socket(UI sock) mov dx, [bp+6] mov bx, @data mov ds, bx mov bx, 1 call dword ptr enterIPX pop di pop si pop ds pop bp ret _IPXclose_socket endp _IPXlisten proc far push bp mov bp, sp push ds push si push di ; int IPXlisten(ECB *ecb) les si, dword ptr [bp+6] mov bx, @data mov ds, bx mov bx, 4 call dword ptr enterIPX pop di pop si pop ds pop bp mov ah, 0 ret _IPXlisten endp _Net_Call proc far push bp mov bp, sp ; int Net_Call(UI func, void *req, void *repl) ; [bp+6] func ; [bp+8] req offset ; [bp+10] req segment ; [bp+12] repl offset ; [bp+14] repl segment mov ax, [bp+6] push ds push si push di pushf lds si, dword ptr [bp+8] les di, dword ptr [bp+12] int 21h popf pop di pop si pop ds pop bp mov ah, 0 ret _Net_Call endp ; int Net_Call_VLM_Raw(UI ax, UI bx, UI cx, UI dx, ; void *req, void *repl, ; UI p1, UI p2, UI p3) ; ; Experimental VLM entry caller. ; INT 2F AX=7A20 returns ES:BX = VLM entry if AX == 0000. ; ; Register setup for VLM entry: ; AX, BX, CX, DX from function args ; DS:SI = req ; ES:DI = repl ; ; Extra stack args pushed before calling VLM entry: ; p3, p2, p1 ; ; For NWCREQUEST/VLM test: ; AX=function ; BX=numReqFrags ; CX=connid ; DX=numReplyFrags ; DS:SI=reqFragList ; ES:DI=replyFragList ; p1=6, p2=20h, p3=0 _Net_Call_VLM_Raw proc far push bp mov bp, sp sub sp, 4 push ds push si push di push es mov ax, 7A20h xor bx, bx int 2Fh or ax, ax jz vlm_raw_found mov ax, 88FFh jmp short vlm_raw_done vlm_raw_found: ; save VLM entry ES:BX in stack locals mov [bp-4], bx mov ax, es mov [bp-2], ax ; load caller-requested registers mov ax, [bp+6] mov bx, [bp+8] mov cx, [bp+10] mov dx, [bp+12] lds si, dword ptr [bp+14] les di, dword ptr [bp+18] push word ptr [bp+26] push word ptr [bp+24] push word ptr [bp+22] call dword ptr [bp-4] vlm_raw_done: pop es pop di pop si pop ds mov sp, bp pop bp ret _Net_Call_VLM_Raw endp ; int C32_LoadNios_Probe(UI axfunc, void *outbuf) ; ; 16-bit object, but captures 32-bit ESI and ECX using manual 386 opcodes. ; This keeps the OMF/linker in 16-bit mode while still reading Client32/NIOS ; values returned by: ; INT 2F AX=D8C1 ; ; outbuf: ; +00 word AX after INT 2F ; +02 dword ESI after INT 2F ; +06 dword ECX after INT 2F ; +0A word BX ; +0C word CX low ; +0E word DX ; +10 word SI low ; +12 word DS ; +14 word ES _C32_LoadNios_Probe proc far push bp mov bp, sp push ds push es push si push di ; xor ecx, ecx db 66h, 33h, 0C9h ; xor esi, esi db 66h, 33h, 0F6h mov ax, [bp+6] int 2Fh push ds push es push si push cx push bx push dx push ax les di, dword ptr [bp+8] ; restore AX result into AX and store word at out+0 pop ax mov es:[di+0], ax ; Store ESI dword at es:[di+2]. ; Encoding: ES override + operand-size prefix + MOV r/m32,r32 ; mov es:[di+02], esi = 26 66 89 75 02 db 26h, 66h, 89h, 75h, 02h ; Store ECX dword at es:[di+6]. ; mov es:[di+06], ecx = 26 66 89 4Dh 06 db 26h, 66h, 89h, 4Dh, 06h pop dx pop bx pop cx mov es:[di+10], bx mov es:[di+12], cx mov es:[di+14], dx pop ax ; saved SI mov es:[di+16], ax pop ax ; saved ES pop bx ; saved DS mov es:[di+18], bx mov es:[di+20], ax pop di pop si pop es pop ds pop bp xor ah, ah ret _C32_LoadNios_Probe endp ; int C32_GetFunc_Probe(char *name, void *outbuf) ; ; 16-bit OMF Client32 function resolver probe. ; This mimics C32BEGINUSE for one function name: ; INT 2F AX=D8C1 ; save ESI as far pointer to __Nios+8 function resolver ; push name segment ; push name offset ; push 0 ; push 0 ; call far [ESI] ; add sp,8 ; ; outbuf: ; +00 word load AX from INT2F ; +02 dword ESI from INT2F ; +06 dword ECX from INT2F ; +0A word resolver return AX ; +0C word resolver return DX ; +0E word BX ; +10 word CX _C32_GetFunc_Probe proc far push bp mov bp, sp sub sp, 4 push ds push es push si push di ; clear ECX/ESI db 66h, 33h, 0C9h db 66h, 33h, 0F6h mov ax, 0D8C1h int 2Fh ; save ESI dword to [bp-4] db 66h, 89h, 76h, 0FCh push ax ; save load AX ; call resolver only if AX == 0 or ax, ax jne c32get_store_fail push word ptr [bp+8] ; name segment push word ptr [bp+6] ; name offset push 0 push 0 call dword ptr [bp-4] add sp, 8 jmp short c32get_store c32get_store_fail: xor dx, dx xor ax, ax c32get_store: push dx push ax les di, dword ptr [bp+10] pop ax ; resolver AX pop dx ; resolver DX pop bx ; load AX saved in BX temporarily mov es:[di+0], bx ; Store ESI dword at out+2: ES override + operand prefix db 26h, 66h, 89h, 75h, 02h ; Store ECX dword at out+6 db 26h, 66h, 89h, 4Dh, 06h mov es:[di+10], ax mov es:[di+12], dx mov es:[di+14], bx mov es:[di+16], cx pop di pop si pop es pop ds mov sp, bp pop bp xor ah, ah ret _C32_GetFunc_Probe endp ; int C32_CallVersion_Nios_Probe(void *outbuf) ; ; 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 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, 12 push ds push es push si push di pushf ; clear ECX/ESI db 66h, 33h, 0C9h db 66h, 33h, 0F6h mov ax, 0D8C1h int 2Fh ; 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 for output or ax, ax jne c32ver_fail push cs push offset c32ver_name push 0 push 0 call dword ptr [bp-4] add sp, 8 ; resolver returns DX:AX function pointer mov [bp-12], ax mov [bp-10], dx or ax, dx je c32ver_fail ; 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 c32ver_store c32ver_fail: xor dx, dx xor ax, ax pushf push dx push ax c32ver_store: les di, dword ptr [bp+6] pop ax ; call AX pop dx ; call DX pop bx ; flags pop cx ; load AX mov es:[di+0], cx mov cx, word ptr [bp-4] mov es:[di+2], cx mov cx, word ptr [bp-2] mov es:[di+4], cx mov cx, word ptr [bp-8] mov es:[di+6], cx mov cx, word ptr [bp-6] mov es:[di+8], cx 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 pop si pop es pop ds mov sp, bp pop bp xor ah, ah ret c32ver_name db 'CLIENT32GetVersion',0 _C32_CallVersion_Nios_Probe endp ; int C32_MapLock_Probe(void *ptr, UI len, void *outbuf) ; ; Probe d32wrap.o __MapLockFlat / __UnlockFlat: ; INT 2F AX=D8C1 ; ESI resolver returned by D8C1 is used with command 2 and 3: ; push len_hi ; push len_lo ; push seg ; push off ; push 0 ; push 2 ; call ESI ; returns flat DX:AX ; ; push len_hi ; push len_lo ; push flat_hi ; push flat_lo ; push 0 ; push 3 ; call ESI ; unlock ; ; outbuf: ; +00 load AX ; +02 ESI off ; +04 ESI seg ; +06 map AX low ; +08 map DX high ; +0A unlock AX ; +0C unlock DX _C32_MapLock_Probe proc far push bp mov bp, sp sub sp, 8 push ds push es push si push di ; clear ECX/ESI db 66h, 33h, 0C9h db 66h, 33h, 0F6h mov ax, 0D8C1h int 2Fh ; save ESI resolver at [bp-4] db 66h, 89h, 76h, 0FCh push ax ; load AX or ax, ax jne mapflat_fail ; MapLockFlat(ptr, len) push 0 push word ptr [bp+10] ; len push word ptr [bp+8] ; ptr seg push word ptr [bp+6] ; ptr off push 0 push 2 call dword ptr [bp-4] add sp, 0cH ; save mapped flat DX:AX at [bp-8] mov word ptr [bp-8], ax mov word ptr [bp-6], dx ; UnlockFlat(flat, len) push 0 push word ptr [bp+10] ; len push dx push ax push 0 push 3 call dword ptr [bp-4] add sp, 0cH jmp short mapflat_store mapflat_fail: xor dx, dx xor ax, ax mov word ptr [bp-8], ax mov word ptr [bp-6], dx mapflat_store: les di, dword ptr [bp+12] mov bx, ax ; unlock AX mov cx, dx ; unlock DX pop ax ; load AX mov es:[di+0], ax mov ax, word ptr [bp-4] mov es:[di+2], ax mov ax, word ptr [bp-2] mov es:[di+4], ax mov ax, word ptr [bp-8] mov es:[di+6], ax mov ax, word ptr [bp-6] mov es:[di+8], ax mov es:[di+10], bx mov es:[di+12], cx pop di pop si pop es pop ds mov sp, bp pop bp xor ah, ah ret _C32_MapLock_Probe endp ; int C32_NCP87_Raw_Probe(UI connLo, UI connHi, ; void *hdr, UI hdrLen, ; void *path, UI pathLen, ; void *rep0, UI rep0Len, ; void *rep1, UI rep1Len, ; void *outbuf) ; ; Specialized raw Client32 NCP87/S6 request probe. ; Reproduces d32wrap.o _COMPATNcpRequestReply mechanics: ; - INT 2F AX=D8C1 ; - resolve COMPATNcpRequestReply via ESI resolver ; - MapLockFlat each fragment data buffer ; - build flat 8-byte frag tables ; - MapLockFlat frag tables and actualReplyLen ; - call ECX NIOS trampoline with command 8 and COMPATNcpRequestReply pointer ; - unlock mappings ; ; outbuf: ; +00 load AX ; +02 resolver off ; +04 resolver seg ; +06 trampoline off ; +08 trampoline seg ; +0A function off ; +0C function seg ; +0E ret AX ; +10 ret DX ; +12 actualReplyLen low ; +14 actualReplyLen high _C32_NCP87_Raw_Probe proc far push bp mov bp, sp sub sp, 100 push ds push es push si push di ; clear ESI/ECX db 66h, 33h, 0F6h db 66h, 33h, 0C9h mov ax, 0D8C1h int 2Fh ; save resolver ESI at [bp-84] db 66h, 89h, 76h, 0ACh ; save trampoline ECX at [bp-88] db 66h, 89h, 4Eh, 0A8h mov [bp-2], ax ; load AX or ax, ax jne c32raw_fail ; resolve "COMPATNcpRequestReply" push cs push offset c32raw_name push 0 push 0 call dword ptr [bp-84] add sp, 8 mov [bp-92], ax mov [bp-90], dx or ax, dx jne c32raw_have_func jmp c32raw_fail c32raw_have_func: ; actualReplyLen local at [bp-52] mov word ptr [bp-52], 0 mov word ptr [bp-50], 0 ; Map hdr data -> [bp-56] push 0 push word ptr [bp+0eH] push word ptr [bp+0cH] push word ptr [bp+0aH] push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-56], ax mov [bp-54], dx ; Map path data -> [bp-60] push 0 push word ptr [bp+14H] push word ptr [bp+12H] push word ptr [bp+10H] push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-60], ax mov [bp-58], dx ; Map reply0 -> [bp-64] push 0 push word ptr [bp+1aH] push word ptr [bp+18H] push word ptr [bp+16H] push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-64], ax mov [bp-62], dx ; Map reply1 -> [bp-68] push 0 push word ptr [bp+20H] push word ptr [bp+1eH] push word ptr [bp+1cH] push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-68], ax mov [bp-66], dx ; Build req flat table at [bp-32], two entries: ; entry = flatptr dword + len dword mov ax, [bp-56] mov [bp-32], ax mov ax, [bp-54] mov [bp-30], ax mov ax, [bp+0eH] mov [bp-28], ax mov word ptr [bp-26], 0 mov ax, [bp-60] mov [bp-24], ax mov ax, [bp-58] mov [bp-22], ax mov ax, [bp+14H] mov [bp-20], ax mov word ptr [bp-18], 0 ; Build reply flat table at [bp-48] mov ax, [bp-64] mov [bp-48], ax mov ax, [bp-62] mov [bp-46], ax mov ax, [bp+1aH] mov [bp-44], ax mov word ptr [bp-42], 0 mov ax, [bp-68] mov [bp-40], ax mov ax, [bp-66] mov [bp-38], ax mov ax, [bp+20H] mov [bp-36], ax mov word ptr [bp-34], 0 ; Map req table [bp-32] len 16 -> [bp-72] push 0 push 10H push ss lea ax, -32[bp] push ax push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-72], ax mov [bp-70], dx ; Map reply table [bp-48] len 16 -> [bp-76] push 0 push 10H push ss lea ax, -48[bp] push ax push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-76], ax mov [bp-74], dx ; Map actualReplyLen [bp-52] len 4 -> [bp-80] push 0 push 4 push ss lea ax, -52[bp] push ax push 0 push 2 call dword ptr [bp-84] add sp, 0cH mov [bp-80], ax mov [bp-78], dx ; Call NIOS trampoline command 8 with COMPATNcpRequestReply pointer. push word ptr [bp-78] ; actual flat hi push word ptr [bp-80] ; actual flat lo push word ptr [bp-74] ; reply table flat hi push word ptr [bp-76] ; reply table flat lo push 0 push 2 ; num reply frags push word ptr [bp-70] ; req table flat hi push word ptr [bp-72] ; req table flat lo push 0 push 2 ; num req frags push 0 push 57H ; NCP function 87 push 0 push 0 push word ptr [bp+8] ; conn high push word ptr [bp+6] ; conn low push 0 push 8 push word ptr [bp-90] ; function seg push word ptr [bp-92] ; function off call dword ptr [bp-88] add sp, 28H mov [bp-96], ax mov [bp-94], dx ; unlock mapped actual/table/data. Ignore returns. push 0 push 4 push word ptr [bp-78] push word ptr [bp-80] push 0 push 3 call dword ptr [bp-84] add sp, 0cH push 0 push 10H push word ptr [bp-74] push word ptr [bp-76] push 0 push 3 call dword ptr [bp-84] add sp, 0cH push 0 push 10H push word ptr [bp-70] push word ptr [bp-72] push 0 push 3 call dword ptr [bp-84] add sp, 0cH push 0 push word ptr [bp+20H] push word ptr [bp-66] push word ptr [bp-68] push 0 push 3 call dword ptr [bp-84] add sp, 0cH push 0 push word ptr [bp+1aH] push word ptr [bp-62] push word ptr [bp-64] push 0 push 3 call dword ptr [bp-84] add sp, 0cH push 0 push word ptr [bp+14H] push word ptr [bp-58] push word ptr [bp-60] push 0 push 3 call dword ptr [bp-84] add sp, 0cH push 0 push word ptr [bp+0eH] push word ptr [bp-54] push word ptr [bp-56] push 0 push 3 call dword ptr [bp-84] add sp, 0cH jmp short c32raw_store c32raw_fail: mov word ptr [bp-92], 0 mov word ptr [bp-90], 0 mov word ptr [bp-96], 0FFFFH mov word ptr [bp-94], 0FFFFH mov word ptr [bp-52], 0 mov word ptr [bp-50], 0 c32raw_store: les di, dword ptr [bp+22H] mov ax, [bp-2] mov es:[di+0], ax mov ax, [bp-84] mov es:[di+2], ax mov ax, [bp-82] mov es:[di+4], ax mov ax, [bp-88] mov es:[di+6], ax mov ax, [bp-86] mov es:[di+8], ax mov ax, [bp-92] mov es:[di+10], ax mov ax, [bp-90] mov es:[di+12], ax mov ax, [bp-96] mov es:[di+14], ax mov ax, [bp-94] mov es:[di+16], ax mov ax, [bp-52] mov es:[di+18], ax mov ax, [bp-50] mov es:[di+20], ax pop di pop si pop es pop ds mov sp, bp pop bp xor ah, ah ret c32raw_name db 'COMPATNcpRequestReply',0 _C32_NCP87_Raw_Probe endp end