diff options
| author | user <user@clank> | 2026-07-16 00:37:09 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-07-16 00:37:09 +0200 |
| commit | 2538b138946128cc5ff473e14ba9bde564aef2e9 (patch) | |
| tree | 26b9680b11c2c22b05154ed5166923d0e3fa8d97 | |
| parent | wip: sys_read + serial console shell (read-store bug under investigation) (diff) | |
| download | gbos-2538b138946128cc5ff473e14ba9bde564aef2e9.tar.gz gbos-2538b138946128cc5ff473e14ba9bde564aef2e9.tar.xz gbos-2538b138946128cc5ff473e14ba9bde564aef2e9.zip | |
shell working: fix syscall ABI (trap clobbers HL) + document
- root cause of the read/echo corruption: SyscallTrap uses HL to index the
dispatch table, so HL is clobbered across a syscall; the shell then wrote its
buffer pointer's garbage into the $0000-$7FFF MBC register region, corrupting
the mapper. fix: userland saves HL around sys_read (push/pop).
- shell now runs commands end to end: $ hello -> hello world!, $ worker ->
worker!, $ foo -> ?
- README: document that syscalls clobber BC/DE/HL (return in A, B for wait);
add read + shell to the syscall table.
Diffstat (limited to '')
| -rw-r--r-- | README.md | 24 | ||||
| -rw-r--r-- | src/programs.asm | 6 |
2 files changed, 27 insertions, 3 deletions
@@ -41,7 +41,10 @@ $FFEF-$FFF2 HRAM bank shadows + switch target ## Syscall ABI -User loads `C` = syscall number, args in `DE`/`B`, then `rst $30`. Return in `A`. +User loads `C` = syscall number, args in `DE`/`B`/`HL`, then `rst $30`. +Return in `A` (and `B` for `wait`). **The trap clobbers `BC`/`DE`/`HL`** (it uses +`HL` to index the dispatch table), so userland must save any pointer it needs +across a syscall (`push hl` / `pop hl`). Libc syscall stubs handle this for C. | # | name | status | |---|---------|--------| @@ -52,7 +55,24 @@ User loads `C` = syscall number, args in `DE`/`B`, then `rst $30`. Return in `A` | 7 | wait | ✅ blocks; reaps a zombie child → `A`=pid `B`=code | | 8 | getpid | ✅ | | 11| yield | ✅ cooperative switch | -| 2,4,5,9,10 | read/open/close/kill/brk | ⛔ `ENOSYS` | +| 2 | read | ✅ blocking console input (1 byte) via external-clock serial | +| 4,5,9,10 | open/close/kill/brk | ⛔ `ENOSYS` | + +### The shell (PROG_SH) + +init `exec`s a tiny shell: **prompt → read a line (with echo) → match a command +→ `fork`+`exec`+`wait`**. Commands live in a table (`worker`, `hello`). Runs +entirely over the headless serial console: + +``` +$ hello +hello world! +$ worker +worker! +$ foo +? +$ +``` ### Process lifecycle (exit / wait / reaping) diff --git a/src/programs.asm b/src/programs.asm index df2b98d..d4ae89f 100644 --- a/src/programs.asm +++ b/src/programs.asm @@ -59,8 +59,10 @@ ProgSh: ; read a line into SH_LINEBUF, echoing as we go ld hl, SH_LINEBUF .rd + push hl ; syscalls clobber HL (trap uses it to dispatch) ld c, SYS_READ rst $30 ; A = input byte + pop hl cp $0D jr z, .eol cp $0A @@ -70,7 +72,9 @@ ProgSh: ld [$FF01], a ; echo the char straight to serial ld a, $81 ld [$FF02], a - jr .rd + ld a, l + cp LOW(SH_LINEBUF) + SH_MAXLINE - 1 + jr c, .rd ; keep reading unless the buffer is full .eol ld [hl], 0 ; NUL-terminate |
