From 0a77a11e17f697bf797655c4ae87b927432b1f88 Mon Sep 17 00:00:00 2001 From: user Date: Thu, 16 Jul 2026 00:04:09 +0200 Subject: kernel: implement exec() - sys_exec(B=program id): look up ProgramTable, point PROC_ROMB at the program's ROM text bank, map it into $4000-$7FFF, reset stack, jp to entry (no return) - programs.asm: two demo programs (ping/pong) ORG'd at the SAME $4000 in banks 2 and 3 - proves execution is driven purely by PROC_ROMB - demo: init forks; parent execs PROG_PING (bank2, '1'), child execs PROG_PONG (bank3, '2') -> '1212...', 2000/2000 balanced, zero garbage - README: document exec + text-in-ROM model --- README.md | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) (limited to 'README.md') diff --git a/README.md b/README.md index 2d2946c..3f6aab0 100644 --- a/README.md +++ b/README.md @@ -48,9 +48,27 @@ User loads `C` = syscall number, args in `DE`/`B`, then `rst $30`. Return in `A` | 0 | exit | ✅ marks zombie, reschedules | | 1 | fork | ✅ copies the 8 KiB bank, child returns 0 | | 3 | write | ✅ `DE`=buf `B`=len → serial console | +| 6 | exec | ✅ `B`=program id → maps ROM text bank, jumps in | | 8 | getpid | ✅ | | 11| yield | ✅ cooperative switch | -| 2,4,5,6,7,9,10 | read/open/close/exec/wait/kill/brk | ⛔ `ENOSYS` | +| 2,4,5,7,9,10 | read/open/close/wait/kill/brk | ⛔ `ENOSYS` | + +### exec (`sys_exec`, src/proc.asm + programs.asm) + +Where the text-in-ROM model pays off. Programs are linked to run from the ROMX +window (`$4000-$7FFF`) and stored in their own ROM banks (`programs.asm`). +`exec(B=program id)`: + +1. looks up `ProgramTable[B]` = (ROM bank, entry), +2. sets `PROC_ROMB` and maps the bank live into `$4000-$7FFF`, +3. resets the stack to the top of the task's (already mapped) cart-RAM bank, +4. `jp`s to the entry — it never returns. + +Proof it's really bank-driven: both demo programs are ORG'd at the **same** +address `$4000` in **different** banks (02 and 03). The parent `exec`s +`PROG_PING`, the child `exec`s `PROG_PONG`, and the output `1212...` (2000/2000, +zero garbage) can only happen if each process executes its own bank via +`PROC_ROMB`. A fuller exec would also copy `.data` from ROM and zero `.bss`. ### fork (`sys_fork`, src/proc.asm) @@ -112,7 +130,8 @@ A real gbos would render to VRAM; serial is the zero-VRAM debug channel. ## Roadmap - [x] `fork`: copy parent's 8 KiB RAM bank → free bank, child returns 0 -- [ ] `exec`: point `PROC_ROMB` at a flashed program, reset RAM-bank layout +- [x] `exec`: point `PROC_ROMB` at a program in a ROM bank, reset stack, enter +- [ ] `exec` refinement: copy `.data` from ROM + zero `.bss` for RW globals - [ ] Preemptive scheduling: real context save in `TimerISR` → `hSwitchTo` - [ ] Use the `$D000-$DFFF` u-area (SVBK) for per-process kernel state / kstack - [ ] `brk`/heap allocator inside the task bank (heap up, stack down, collision = ENOMEM) -- cgit v1.3.1-sl0p