From 0eb8b9538c68048bc24520719ea4fa69b1509030 Mon Sep 17 00:00:00 2001 From: kitty Date: Fri, 30 Jan 2026 21:25:04 +1100 Subject: more primitives, notably PARSE, untested --- jefs.s | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ readme.md | 5 ++++- 2 files changed, 73 insertions(+), 1 deletion(-) diff --git a/jefs.s b/jefs.s index a53b8d4..c0b1b82 100644 --- a/jefs.s +++ b/jefs.s @@ -68,18 +68,87 @@ _start: mov rax, __NR_exit syscall +defword "bye", bye, 0 + mov rdi, 0 + mov rax, __NR_exit + syscall + ret ; will not be reached + defword "@", fetch, 0 pspop r11 mov r12, qword [r11] pspush r12 ret +defword "c@", cfetch, 0 + pspop r11 + xor r12, r12 + mov r12b, [r11] + pspush r12 + ret + defword "!", store, 0 pspop r11 pspop r12 mov qword [r11], r12 ret +defword "c!", cstore, 0 + pspop r11 + pspop r12 + mov [r11], r12b + ret + +; stage 1 parser. very rudimentary, does not recognise numbers, +; only recognises newlines and spaces as whitespace. +; since it will only parse a little bit of the init file +; there won't be any error checking either. +defword "parse", parse, 0 + mov r13, qword [to_in] + add r13, initfile + mov r12b, byte [r13] + +.wsloop: ; skip initial ws + cmp r12b, 0x20 + je .wsloop_cont + cmp r12b, 0x0a + jne .wordloop_start +.wsloop_cont: + inc r13 + mov r12b, byte [r13] + jmp .wsloop + +.wordloop_start: + push r13 ; keep start address of this word for later + mov r11, 1 ; W: word length count +.wordloop: + cmp r12b, 0x20 + je .wordloop_end + cmp r12b, 0x0a + je .wordloop_end + + inc r11 + inc r13 + mov r12b, byte [r13] + jmp .wordloop + +.wordloop_end: + sub r13, initfile + mov qword [to_in], r13 + pop r13 + pspush r13 ; c-addr + pspush r11 ; u + ret + +defword "find", find, 0 + ret + +; stage 1 interpreter, just reads from initfile +defword "interpret", interpret, 0 + ret + +defvar ">in", to_in, 0, initfile + initfile: incbin "jefs.fs" initlen equ $ - initfile diff --git a/readme.md b/readme.md index e01353b..97ed56a 100644 --- a/readme.md +++ b/readme.md @@ -28,7 +28,7 @@ there are a set of 'virtual registers' (see moving forth part 1) - W, the working register, is r11. - X, the secondary working register, is r12. -- IP, the instruction pointer, is r13. (this will only be needed if we switch to DTC, otherwise this can be Y, a third general purpose register) +- Y, the tertiary working register, is r13. - SP, the working stack pointer, is r14. - RSP, the return stack pointer, is rsp. @@ -57,8 +57,11 @@ but obviously we need *something* to bootstrap from. - `:` (` -- `): compile a word from the current input source - `;` (` -- `): stop compiling the current word - `parse` (` -- c-addr u`): parse a word from the *forth init* (see footnote) +- `find` (`c-addr u -- ?lfa flag`) +- `interpret`: the stage 1 interpreter - `latest`: a variable, the latest defined word - `state`: a variable, determines current mode (interp./compiling) +- `>in`: a variable, offset from start of forth init on `parse`: i don't want to deal with file access and stuff from the kernel. so this word will be Upgraded in the forth init to read from a file. -- cgit v1.2.3