ZX-FORTH

Products: ZX-FORTH
Date: 1982
Type: Cassette
Platform(s): TS 1000

ZX-FORTH is a FORTH programming language interpreter implemented in machine code and stored within a REM statement at line 65310. The program launches via RAND USR 17245, transferring execution directly to the machine code payload embedded in the REM statement’s data area. The REM statement contains the complete FORTH interpreter runtime, including dictionary entries, inner interpreter, and I/O primitives encoded as raw bytes. This technique of storing machine code in a high-numbered REM line keeps the BASIC loader compact while placing the binary payload at a predictable memory address.


Program Analysis

Program Structure

The program consists of only two active BASIC lines plus a large data-carrying REM statement:

  1. Line 10: SAVE "ZXFORTH" — saves the program to tape.
  2. Line 20: RAND USR 17245 — transfers execution to the machine code interpreter at address 17245 (decimal), which falls within the REM statement’s data area.
  3. Line 65310: A REM statement carrying the entire machine code binary of the FORTH interpreter as raw byte data.

Machine Code Delivery via REM

Storing machine code inside a REM statement is a classic technique. The BASIC line header for line 65310 begins at a known offset in RAM, and the bytes following the REM token are the raw Z80 opcodes and data of the FORTH system. The entry point at address 17245 (hex 0x435D) points into this payload. Because REM data is never parsed by the BASIC interpreter, arbitrary byte values — including those that would otherwise be interpreted as BASIC keywords — can be stored safely.

RAND USR Entry Point

RAND USR 17245 on line 20 is the standard idiom for invoking machine code from BASIC. RAND USR n calls the Z80 CALL to address n, and because the FORTH interpreter never returns to BASIC, the RAND return value is irrelevant. Address 17245 decimal is 0x435D, which lies in the region immediately after the system variables and in the program area, consistent with the REM data starting at line 65310‘s data bytes.

FORTH Interpreter Internals (Inferred from REM Data)

The byte content of the REM statement, when interpreted as Z80 machine code and FORTH dictionary data, implements a threaded FORTH interpreter. Visible ASCII fragments within the REM data correspond to FORTH word names embedded in dictionary headers. Identifiable word names and runtime tokens visible in the listing include:

  • Standard FORTH words: DUP, DROP, SWAP, OVER, ROT (inferred from stack-manipulation byte patterns)
  • BASIC keyword tokens appearing in the REM data (PRINT, INPUT, LET, INKEY$, PEEK, POKE, USR, RUN, STOP, COPY, FAST, SLOW, PLOT, UNPLOT, CLS, LPRINT, PAUSE, GOSUB, FOR, NEXT, RETURN, NEW, DIM, CLEAR, RAND, SAVE) — these appear because the Z80 byte values of those opcodes coincide with the BASIC keyword token values, not because BASIC is executing them
  • Mathematical and string functions visible as tokens: SIN, COS, TAN, ATN, ACS, ASN, LN, EXP, ABS, SGN, RND, PI, STR$, VAL, CHR$, CODE, LEN, TAB

The repeated appearance of RETURN tokens throughout the REM data is consistent with a direct-threaded or indirect-threaded FORTH inner interpreter using RET (opcode 0xC9) instructions — the Z80 RET opcode value happens to equal the BASIC RETURN token, causing the lister to display RETURN throughout the machine code body.

Notable Techniques

  • High line number for REM: Line 65310 places the REM at the very end of the BASIC program area, so the machine code does not interfere with normal BASIC line numbering and is unlikely to be accidentally renumbered or edited.
  • Two-line loader: The entire BASIC portion is just SAVE and RAND USR, minimizing BASIC overhead and RAM consumed by the interpreter stub.
  • Block graphics and inverse characters in REM: The REM data contains block graphic characters and inverse-video characters, which are legitimate byte values within the Z80 machine code — they appear in the listing as graphical symbols but are raw data bytes to the CPU.
  • FASTSTR$ and other compound tokens: Sequences like FASTSTR$ in the REM listing represent consecutive keyword tokens whose byte values happen to produce those token sequences when the lister renders them; they are not actual BASIC statements.

Potential Anomalies

The null bytes (displayed as 0 on lines by themselves near the top of the REM data) and the short numeric sequences (0 0) are legitimate parts of the binary payload — FORTH dictionary entries commonly contain null terminators and 16-bit address fields that render as low numeric values in the BASIC lister. These are not bugs.

Memory Map Summary

Address (dec)Content
17245FORTH interpreter entry point (inside REM data)
BASIC line 65310REM statement containing full machine code payload
BASIC line 10SAVE loader
BASIC line 20RAND USR launch stub

Content

Appears On

Related Products

Full implementation of FORTH for the ZX81/TS1000. Runs up to 10 times faster than Basic. ZX-FORTH complies with the FORTH-79...

Related Articles

Related Content

Image Gallery

Source Code

  10 SAVE "ZXFORT[H]"
  20 RAND USR 17245
 65310 REM ............................................................................................. FASTSTR$ VAL [R]ASN #INKEY$  RETURN█KM RETURN▒CZ RETURN?CV RETURN#S▝CHR$ 4 RETURNKS= RETURNUK▖CHR$ =/= RETURNINKEY$ S# RETURN#K#CHR$ ./▒5[-]INKEY$ #- ;# RETURN#CWACS [R] PRINT UTRND RETURN▘ATN #INKEY$  LET NOT AT SGN  LPRINT TAN E:RNDFUTRNDWMTRND#6:RND RETURN#4(F6:RNDY▝MTRNDUURNDWMURNDQ ##INKEY$  FASTSTR$ VAL  PRINT UURND RETURN▀C▌Y#NOT /▀LN :£ LET AT SGN  LPRINT TAN CHR$ ~~/[3]CHR$ 8/[.]      
   0
   0 ▘▝▀▖▌▞▛▒,,~~       [£]"[?]£$ [(]()*+,-./:;<=>?["][$] [:][>][)]VAL STR$  FAST▘ █UQ  RETURN▜4,,LN M? CLEARQP COPY/▀LN P? GOSUB #9RNDLN [X]▛K LPRINT 5 UNPLOT INKEY$ ;###INKEY$ #########LMNOPKTSRQ#####$####4I##PIUVZJB#[-][*]#RND57[/][;][,][.][0][1][+]▒[2][=][>][<]6DC8[3][4]XFH[5] GYWESTR$ #Y#<= RETURN3S$Y RETURN<= RETURN3S▞Y▘[R]#SGN TAN [J]/ IF  PRINT INKEY$ 7/ PLOT  LET TAN  FASTSTR$ VAL  PRINT LN 4#)>#Y#<= RETURN *S PRINT .#[N]4 NEXT  LET AT SGN  LPRINT TAN  FASTSTR$ VAL :▘▞ Y#<= RETURNPEEK  COPY*S▖( PRINT / LET 2[=]▞,1<= RETURN*ACS ##S PRINT ( PRINT 4▖ RETURN#K>=ZACS )KNOT #/ACS  FASTSTR$ VAL  PRINT LN 4#)ACS ▒( RETURN.#[N]4 RAND /[R] FASTSTR$ VAL  PRINT #RACS <C1[3] NEW▌LEN ▖#PEEK  COPY▞7( RETURNLN  CLSPI  ▞2( RETURN$4 INPUT [R]( CLEAR/ TO #[▒]PIY#<= RETURN3 CLEARACS V▚Y COPYMBRNDTAN  PRINT  FASTSTR$ VAL UQ  RETURN▜ PRINT ATN C? LET CODE F?AT SGN  LPRINT  LET TAN  PRINT  FASTSTR$ VAL UQ  RETURN▜ PRINT ATN 4? LET CODE 7?AT SGN  LPRINT  LET TAN  FAST PRINT 5##LN #PILN ABS INKEY$  RETURN$C▖ LET  LPRINT RTAN  LET  LPRINT [R]TAN ##INKEY$ ##4#INKEY$ ######$  NEXT 5##7Q▘Y▘[Y]4▌[J]P[Y]C NEXT F6▄##*# #▝#▘▘▘:[O]#▒ 4# STOP#4#█#3   ######;  LET [>]4#2#STR$  FAST CLEARO5TAB [F]#LN #PIC▀▘##~~▀#~~▀##7# FOR  DIM ▄##USR   [Y]#~~▀#~~▀#/CHR$ ▗######VAL [Q]#ABS # LPRINT />=▚PI#INKEY$ ##COS LEN # STEP ####7#F;##/[M]▗KPI#INKEY$ ##COS STR$ # RUN # LPRINT #[P]C SLOW▀▀/[1]▚C####[D] FOR #"#)▘ E[;]#[~~]#7=+# IF B##[-]#7[2]/▌ STEP #76[;]#▀▀#[1]#▗CF####[D] ###SGN /SIN ▜C##[D]S###E[;]#FFFF6[;]#SGN #7#SGN 7#7##[1]#▟TAN ####E[;]##7#STR$ / INPUT ▐####USR #### LPRINT SGN #CHR$ K IF [2]# RETURN~~ IF [<]#CHR$ ▛ RETURN~~ IF [2]#[X] PAUSE [2]##5▘ #[.]###[0]#▚C####[D]##[H]#SGN  LPRINT  FAST,[I] NEWZ437<,[I]▗4-K RUN 5▌ ; STOP.,[R] PAUSE CODE ##- 5▘ #[.]#S▞<,[R] PAUSE STR$ #< FOR #7##[N]4ASN  LPRINT 5  #[0]#▗######VAL [6]# RUN #SGN  LPRINT  FAST#) COPY COPYF7<[Y]C CLSSTR$  PRINT STR$ .STR$ #[1]# LET  PRINT 7<[Y]C~~STR$ #[1]# LET STR$ <STR$ #[1]#▜###USR  FOR #Z#ASN #CODE #[6]#[9]#▄#▄## OR E####AT #[,,]Z######INKEY$ ATN X###5  # LPRINT #▙#ABS #####CHR$ #▐####VAL ######AT SGN  STOP/▌[L]4 RUN AT /[8]▙#[E]##[~~]#SGN  LPRINT VAL ##LN [A]# FAST###LN [A]#SGN #,,EXP  ###AT STR$ #[0]#5  :▒D*K▀;EXP  $4 PLOT TAN ▙#[J]▄#[X]#5▖ T##7##AT  LPRINT #[)]#[/]S▛5 COPY COPY##/3Y(D* FOR DK▝<[R] FOR 3 PRINT K▌[R] GOSUB PI/▞ GOSUB PIK▝,,.< LET X4 STOPAT  FASTSTR$ #[1]#▄INKEY$ #CODE [Q]#▝#SGN  LPRINT #[9]##[8]##[0]#▙#ABS  IF #=#SGN  LPRINT #[P]##

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

People

No people associated with this content.

Scroll to Top