Threading
The Forth program will be stored as a list of subroutine calls, for example:
dat lit ; push 1111A more compact representation would be to store addresses in both the a-field and b-field. Unfortunately this would be at the expense of more complex flow control:
dat 1111
dat lit ; push 1234
dat 1234
dat plus ; add TOS to 2OS
dat udot ; display TOS
dat lit, 1111I'm open to suggestions how the interpreter can use the compact representation without causing too many difficulties.
dat lit, 1234
dat plus, udot
Instruction Set
Ins | Description |
---|---|
- | subtract TOS from 2OS |
+ | add TOS to 2OS |
* | multiply TOS by 2OS |
U. | print TOS as an unsigned number |
SPACE | print a space |
DUP | copy TOS |
DROP | remove TOS |
ABS | replace TOS with its absolute value |
NEGATE | replace TOS with -TOS |
! | 2OS is stored at the address in TOS |
+! | 2OS is added to the address in TOS |
@ | fetch the value at the address in TOS |
= | TRUE if TOS=2OS, else FALSE |
SWAP | exchange TOS with 2OS |
DEPTH | number of elements on stack |
BEGIN | start of BEGIN .. UNTIL structure |
UNTIL | if TRUE, return to matching BEGIN |
DO | start of DO .. LOOP structure |
LOOP | inc counter, jump to DO if below limit |
Signed vs Unsigned
Unfortunately numbers in Forth are signed and numbers in Redcode are unsigned. This affects a number of instructions, including division and comparison. Would it be worth the extra code to support unsigned numbers in Redcode Forth?
Example Code
The following example interprets +, U. and literals. New instructions can easily be added in Redcode. Support for calling new instuctions written in Forth needs to be added:
org next
stack dat 0, 0
; LIT - place the next value on the stack
lit mov.b }ip, <stack
jmp next
; + - remove 2OS and TOS and put their sum on stack
plus add.b >stack, @stack
jmp next
; U. - remove and display TOS as an unsigned number
udot mov.b @stack, <stack
div #10, >stack
mod #10, @stack
add #48, @stack
add #1, udcount
jmn udot, <stack
add #1, stack
udloop sts >stack, 0
udcount djn udloop, #0
sts.a #32, 0
jmp next
; --------------------------------
next
ip jmp @prog, }ip
; --------------------------------
prog
dat lit ; push 1111
dat 1111
dat lit ; push 1234
dat 1234
dat plus ; add TOS to 2OS
dat udot ; display TOS
end
1 comment:
You can drop DO and a few others. In the past two decades, Moore has focused entirely on making the most minimal Forth system possible, a sort of anti-ANSI crusade.
Look at the instruction set for Machine Forth and VentureForth. Machine might be the closer fit for you, half of Venture is for message passing between cores.
Post a Comment