diff options
| author | kitty <nepeta@canaglie.net> | 2026-01-30 21:25:04 +1100 |
|---|---|---|
| committer | kitty <nepeta@canaglie.net> | 2026-01-30 21:25:04 +1100 |
| commit | 0eb8b9538c68048bc24520719ea4fa69b1509030 (patch) | |
| tree | f7668b04b06ed3fbedc2ab27c95c4da53ee66467 | |
| parent | b618fbabca4660203ea4801ddc1b4fb38ca5347e (diff) | |
more primitives, notably PARSE, untested
| -rw-r--r-- | jefs.s | 69 | ||||
| -rw-r--r-- | readme.md | 5 |
2 files changed, 73 insertions, 1 deletions
@@ -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 @@ -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. |
