section .bss curpsp: resw 1 absolute 0 resb 2 ; ret 0 exit resb 2 ; allocation length resb 1 resb 5 ; CP/M entry point ; saved userdata PSPAX: resw 1 ; SS:SP PSPSP: resw 1 PSPSS: resw 1 ; DS:DX PSPDX: resw 1 PSPDS: resw 1 ; ES:BX PSPBX: resw 1 PSPES: resw 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 ; 0-7 dw restart, sret dw getc, sretb dw putc, sret dw err, sret ; reader input dw err, sret ; punch outout dw err, sret ; list output dw conio, sret ; direct console i/o dw err, sret ; 8-f dw err, sret dw err, sret ; print string dw err, sret ; read into buffer dw err, sret ; console status dw err, sret ; return version num dw err, sret ; reset disks dw err, sret ; select disk dw err, sret ; open file ; 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 err: mov ah, 0xFF ret ; sysret handlers ; return ES:BX to user sretd: mov ds, [ss:curpsp] jmp sret.l02 ; return BX to user sretw: mov ds, [ss:curpsp] mov es, [PSPES] jmp sret.l02 ; return AL to user sretb: mov ds, [ss:curpsp] mov ah, [PSPAX+1] les bx, [PSPBX] jmp sret.l03 ; return without result sret: mov ds, [ss:curpsp] .l01: les bx, [PSPBX] .l02: mov ax, [PSPAX] .l03: mov ss, [PSPSS] mov sp, [PSPSP] lds dx, [PSPDX] iret