section .bss curpsp: resw 1 absolute 0 resb 2 ; ret 0 exit resb 2 ; allocation length resb 1 resb 5 ; CP/M entry point ; SS:SP, DS:DX, ES:BX and AX from the program PSPAX: resw 1 PSPSS: resw 1 PSPSP: resw 1 PSPDS: resw 1 PSPDX: resw 1 PSPES: resw 1 PSPBX: resd 1 section .text ; OUT ds PSP segment pspds: xor ax, ax mov ds, ax mov ds, [curpsp] ret int21: push ds ; load program PSP and save userdata push ax call pspds pop word [PSPAX] pop word [PSPDS] mov [PSPSS], ss mov [PSPSP], sp mov [PSPDX], dx mov [PSPES], es mov [PSPBX], bx mov ss, ax mov sp, ( stack+stacksize ) mov al, [PSPAX+1] shl ax, 1 shl ax, 1 call .etbl ; syscall table ; cells: ptr to handler, ptr to sysret dw restart, sret dw getc, sretb dw putc, sret ; set up a return chain and execute it ; first return into handler function ; second return into appropiate sysret .etbl: pop bx add bx, ax push word [cs:bx+2] push word [cs:bx] ret ; sysret handlers ; return ES:BX to user sretd: call pspds jmp sret.l02 ; return BX to user sretw: call pspds mov es, [PSPES] jmp sret.l02 ; return AL to user sretb: push ax call pspds pop ax mov ah, [PSPAX+1] les bx, [PSPBX] jmp sret.l03 ; return without result sret: call pspds .l01: les bx, [PSPBX] .l02: mov ax, [PSPAX] .l03: mov ss, [PSPSS] mov sp, [PSPSP] lds dx, [PSPDX] iret