From Sam Supplement Issue 51:
FORTH FOR THE SAM!!!
The Supplement is now publishing a version of the Forth language for the Sam. Written by John Avis the program is a fully working Forth language available on the Supplement Software label.
The package comprises of two discs, one containing 2 versions of Forth (with or without the Sam ROM), and the other discs containing text files which can be printed out to form the manual.
SamForth is a version of the Forth language designed for the SAM computer. It is not Fig-Forth, Forth-79, or Forth-83, but anyone who has knowledge of these versions should be able to cope with SamForth.
If you already know Forth you can turn to the section of these notes entitled Non-standard words and special SAM words.
SamForth normally uses pages 3-6 of SAM's memory as its program area, and pages 7 & 8 to store source. The SAM ROM is paged in as required.
Sometimes if you use the
PALETTE command to obtain a multi-coloured screen, flickering can occur as the SAM ROM is paged in and out. This can be rectified by using version B in which the SAM ROM remains paged in all the time, but the downside is we lose 16 KiB of working RAM.
As it stands SamForth will load automatically. You just insert the Forth disc and press F9.
Inevitably, you will not find every command here that you may want. But one of the beauties of Forth is that you can define your own commands, and if you wish to save them in a customised version, you can do so.
Details of Forth words
This word is mainly used internally by SamForth. It takes a number and places it on the Forth stack. It could be used in machine code as follows:
HEX CD C, FIND LIT , 4000 ,
This routine, if executed, would place the number 16384 (4000 in Hex) on the Forth stack.
This word is also used internally by SamForth to execute Forth words, but it could be used to call a block of machine code.
The above sequence would execute machine code starting at address 20000.
Used internally by SamForth in words such as
ELSE. As the name
BRANCH suggests it is used to force the program to branch to a particular address. It could be useful if you wished to design you own control commands.
HEX CD C, FIND BRANCH , MY-CODE ,
This would make a branch to MY-CODE.
BRANCH, but it will only branch if the Forth stack contains a zero. The zero could be the result of a condition test which returns false or zero.
HEX CD C, FIND 0BRANCH , MY-CODE , FREDS-CODE ,
A branch will be made to MY-CODE if the Forth stack contains a zero, otherwise it will continue with FREDS-CODE.
Exchanges the top two entries on the Forth stack. Top of stack becomes 2nd on stack, and second on stack becomes top of stack.
2 3 SWAP . . will print 2 3. If there were no
2 3 . . would print 3 2.
Duplicates top entry on the Forth stack.
2 DUP . . will print 2 2.
Removes the top entry from the Forth stack and discards it.
Is used internally by Forth interpreter to interpret source code in the input buffer, or in the source code area.
Another internal word. Used by the Forth interpreter to find the execution address of a Forth word. It returns a zero if the word cannot be found. Used by the Forth word
Multiplies the top two unsigned numbers on the Forth stack and places their product on top of the stack as an unsigned double precision number.
4 16384 U* D. will print 65536.
Adds the top two single precision numbers on the stack and places their sum as a single precision number on top of the stack.
2 2 + . will print 4.
Adds the top two double precision numbers on the stack and places their sum as a double precision number at the top of the stack.
65536 65536 D+ D. will give 131072.
Prints an unsigned double number.
Subtracts the top number on the stack from the second number on the stack and leaves the answer on top of the stack.
44 33 - . will print 11.
Negates single precision number at the top of the stack.
2 MINUS . will produce -2.
Negates the double precision number at the top of the stack. We can use it to make the following definition:
: D- DMINUS D+ ;
131072 65536 D- D. will show 65536.
This word is used by Forth to convert ASCII characters in the input buffer or source code area into double precision numbers. If the number is below 65536 the forth interpreter will convert it into a single precision number.
We can use
NUMBER to define a word that will input numbers during a program.
: INPUT QUERY 13 WORD DUP 1 + DUP DUP 1- C@ 13 SWAP C! NUMBER DROP ;
INPUT will take number characters from the input buffer and convert them into a double precision number which is placed on the stack. If a single precision number is required the word DROP should be included, with no brackets around it. If you want double precision numbers omit the word
Will output an ASCII character to the screen, printer or other output device.
65 EMIT will output an "A" to the screen.
Will output the unsigned single precision number on the top of the stack to the current output device. The numbers are in the range 0 - 65535.
Will divide the second single precision number on the stack by the top single precision number and leave the modulus (remainder) as second on the stack and the quotient on the top of the stack.
10 3 /MOD . . will show 3 1.
Clears the screen.
CONSTANT, etc., to create new Forth words.
On its own,
CREATE NEWWORD will create a Forth word with no parameter field. It can be used to make a machine code definition. See also
Causes a "carriage return". Printing will re-commence at the left-most column one line down.
List all the words currently in the Forth dictionary.
Selects number base 10.
Selects number base 16.
When working in number bases other than 10 or 16 the above two words allow an easy return to a more normal way of working.
Places a number in the range 0 - 255 into the next vacant address in the Forth dictionary. Can be used to make machine code definitions.
Places a number in the range 0 - 65535 into the next two vacant addresses in the Forth dictionary.
Reserves addresses in the Forth dictionary.
10 ALLOT reserves 10 addresses. These can be reclaimed with
Use negative numbers with care as you could overwrite your Forth definitions.
Place the number 0 - 65535 held second on the stack into the address held on top of the stack.
20000 50000 ! is the Forth equivalent to the BASIC
! but places numbers in the range 0 - 255 held second on the stack in the address held o n top of the stack.
12 16384 C! is the Forth equivalent to the BASIC
Take a number in the range 0 - 65535 from the address held on the top of the stack, and place that number on the top of the stack.
16384 @ U. equals the BASIC
PRINT DPEEK 16384.
@ but takes a number in the range 0 - 255 from the address at the top of the stack and places that number at the top of the stack.
16384 C@ U. equals the BASIC
PRINT PEEK 16384.
Places the number of the next vacant address in the Forth dictionary on the Forth stack.
Places the address of the name field of the last Forth word in the dictionary on the stack.
The colon indicates that the first word folowing it is the name of a new word to be created, and the Forth words following it are to be compiled as its definition and not executed immediately. The semi-colon marks the end of the compilation.
: FOUR 4 . ;
The example definition will print the number "4" whenever FOUR is entered.
DO LOOP DO +LOOP I
LOOP loop is similar to the BASIC
: TESTLOOP 30 0 DO I . LOOP ;
The definition TESTLOOP will print out the numbers from 0 - 29. Note that 30 is not printed.
I places the index number in the
LOOP on the Forth stack.
+LOOP is similar to a BASIC
NEXT loop using
: TESTLOOP2 30 0 DO I . 2 +LOOP ;
This definition will print out the numbers 0 - 28 in steps of 2. Steps can be negative.
Multiplies two single precision integers at the top of the stack and places their product on the stack as a single precision number.
2 2 * . will give the answer 4.
Prints a string of characters to the screen or other output device. It takes two parameters, the start address of the characters and the number of characters.
16384 10 TYPE will print the 10 characters occupying memory locations 16384 to 16393.
If the entry on the top of the stack is equal to the entry second on the stack they are replaced with "1" on the top of the stack. If they are not equal a "0" replaces them on the stack.
Will divide the second entry on the stack by the top entry and replace them with the quotient on the top of the stack.
10 5 / . will give the answer 2.
If you try and divide by zero you will get the error message "Division by zero".
Divides the second entry on the stack by the top entry and replaces them with the modulus (remainder) on the top of the stack.
11 5 MOD . will give the remainder 1.
A control loop. The code between
UNTIL will be repeatedly executed until
UNTIL finds a non-zero at the top of the stack.
: 30TIMES 0 BEGIN DUP . 1 + DUP 30 = UNTIL DROP ;
Will print the numbers 0 - 29. The loop keeps executing until the count reaches 30 when
= (see above) will place a "1" on the Forth stack. If you end the loop with
0 UNTIL the loop will repeat forever, or until you press SHIFT+F1 to force a break.
BEGIN WHILE REPEAT
Another control loop. The code between
REPEAT is repeatedly executed while the condition before
WHILE remains true. When it becomes false a jump is made to the code after
: 50TIMES 0 BEGIN DUP . 1 + DUP 50 < WHILE ." and " REPEAT DROP ;
This definition will print the numbers 0 to 49 with an "and" in between. When the count reaches 50 the condition becomes false and a jump is made to the word
When the second on the stack is less than the top of the stack a true flag (1) replaces them on the top of the stack. When the second on the stack is greater than the top of the stack a false flag (0) replaces them on the top of the stack.
1 3 <will give a true flag (1).
3 1 <will give a false flag (0).
1 1 <will give a false flag (0).
When the second on the stack is greater than the top of the stack a true flag (1) replaces them on the stack. When the second on the stack is less than the top of the stack a false flag (0) replaces them on the stack.
1 3 >will give a false flag (0).
3 1 >will give a true flag (1).
1 1 >will give a false flag (0).
Transfers the 2nd entry on the Z80 stack to the top of the Forth stack. Use with care. Note that the 2nd entry is transfered because the top entry on the Z80 stack is the return address for the command
Is the reverse of
R>. The top entry on the Forth stack is transferred to the second entry on the Z80 stack.
Waits for a keypress and places the ASCII code of the key on the top of the Forth stack.
A stack command, not the same as the BASIC
OVER. The second entry on the stack is copied to the top of the stack.
4 5 OVER . . . will produce 4 5 4.
A stack command. The third entry on the stack is moved up to become the top entry on the stack.
4 5 6 ROT . . . will produce 4 6 5.
A stack command. The top 2 entries on the stack are duplicated.
4 5 DUP . . . will give 5 4 5 4.
It is the equivalent of using
Places the address of the pad on the top of the stack. See the definition of INPUT under
IF ELSE THEN ENDIF
If the condition before the
IF is true the code between
ELSE is executed and a jump is made to the code after
THEN. If the condition is false the code after the
ELSE is executed.
When there is no
ELSE, the code between
THEN is executed, otherwise a jump is made to the code after
ENDIF is just a different name for
: ?ONE 1 = IF ." One " ELSE ."Not One" THEN ; : RIGHT 2 = IF 33 3 1 BEEP THEN ;
In the above examples, if "1" is on the stack "One" is written; if any other number is on the stack "Not One" is printed. In the second example if "2" is on the stack a beep is sounded, otherwise nothing happens.
Used to define new defining words, that is, words that define other words.
: ARRAY <BUILDS 2 * ALLOT ( defining action) DOES> SWAP 2 * + ( runtime action) ; 10 ARRAY INDEX 25 8 INDEX ! 8 INDEX @ . ( will give 25)
The example defines a defining word ARRAY, which in turn defines an array called INDEX with 10 slots. The code between
and DOES> is what ARRAY will use when it defines the required word. In defining INDEX it takes the parameter 10 and multiplies it by two to
ALLOT 20 addresses, two for each number to be placed in the array.
The code after
DOES> is the runtime action. The parameters 25 (the number to be stored) and 8 (the slot into which the number is to be stored) are on the stack when INDEX is called.
DOES> places the start address of the array on the stack. This is SWAPped so that 8 is on the top of the stack. The 8 is multiplied by 2 and added to the start address to give the address where 25 is to be stored. The store address is on top of the stack and the 25 to be stored second on the stack. The word "!" stores 25 in the store address. The final example reads the contents of the 8th store address and places them on the stack.
Is a defining word already in the vocabulary. It is used to define variables.
VARIABLE SUM will define a variable called SUM.
! is used to write to a variable, and
@ is used to read a variable.
4 SUM ! SUM @ . will print 4.
We could have defined
: MYVAR <BUILDS 2 ALLOT DOES> ;
Is a defining word used to define constants.
4 CONSTANT FOUR creates a constant called FOUR. Whenever FOUR is executed the number 4 is placed on the stack. Again we could have defined it using
: MYCONS <BUILDS 2 ALLOT DOES> @ ;
Moves blocks of code from one memory location to another.
It takes 3 parameters: source address, destination address, length of code.
16384 32768 10 CMOVE will move the 10 bytes of code at 16384 to 32768.
A length of zero will do nothing.
Operates on the bits of the top two numbers on the stack, removes them and leaves the result:
- 1 and 1 give 1
- 1 and 0 give 0
- 0 and 0 give 0
Operates on the bits of the top two numbers on the stack, removes them and leaves the result:
- 1 and 1 give 1
- 1 and 0 give 1
- 0 and 0 give 0
Operates on the bits of the top two numbers on the stack, removes them and leaves the result:
- 1 and 1 give 0
- 1 and 0 give 1
- 0 and 0 give 0
Operates on the top number on the stack. If it is 1
NOT replaces it with a 0, and if it is a zero
NOT replaces it with a 1.
Is the same as
: TEST DUP 11 < SWAP 0 > AND IF ." YES" ELSE ." NO" THEN ;
The above example tests numbers to see if they are in the range 1 - 10.
Although testing multiple conditions is a common use of these operators in Forth, they can be useful in other ways, which is why a good book on Forth would be an asset.
FORGET FRED will clear the user dictionary from and including FRED and all words following FRED to the end of the dictionary.
The original documentation reads:
Protects words in the dictionary from
FIND FRED FENCEwill protect all words up to and including FRED.
If you now try to do
FORGET FREDyou will get the error message "Inside Fence".
FENCE is a variable that holds the limit address, so the example code should be
FIND FRED FENCE !. Beside, the said error is not implemented— "Break" is shown instead. This have been finished in ForthCoupe.
Divides unsigned double precision number second on stack by unsigned single precsion number at the top of the stack. It leaves two single precision numbers, the modulus or remainder at second on stack and the quotient at the top of the stack.
Numbers are already formatted by the word NUMBER, but if you want some special format with - signs, commas, or decimal points you must use the words below. They operate on a double precision number.
Initiates number formatting.
Finishes formatted output and leaves the address of the string at second on stack and the length on top of the stack ready for TYPE to print it out.
Generates an ASCII character for each digit in formatted output.
Applies # above until the number is formatted.
Used in formatted output to hold a character such as a decimal point or currency sign in the pad.
Used in formatted output to hold a "-" sign if the number is negative.
: LP <# # # ( two characters for pence) ASCII . HOLD ( insert decimal point) #S ( now the rest of the number as pounds) ASCII L HOLD ( now the pound sign is printed) #> TYPE ;
Note that the number is formatted backwards. "L" has been used for a pounds sign which my printer doesn't want to print.
If the number on the top of the stack is negative it is replaced by a true flag (1), otherwise a false flag (0).
n PICK copies the nth entry on the stack to the top of the stack.
n ROLL moves the nth entry on the stack to the top of the stack.
Non-standard words and special SAM words
These words save and load a compiled dictionary. Their parameter is the name of the file.
DSAVE FILE will save a compiled dictionary called FILE.FD and
DLOAD FILE will reload it, overwriting any dictionary already in memory.
These load and save blocks of memory.
32768 80 BSAVE DATA will save to the file DATA.FC the 80 bytes of memory starting from address 32768, but
50000 BLOAD DATA will reload the file to address 50000.
See also under
INVERSE BRIGHT CSIZE SOUND FLASH BRIGHT PEN PAPER MODE CLS
These are the Forth equivalents of the BASIC commands, but remember that the parameters precede the command.
2 PAPER 15 PEN
This is the Forth version of the BASIC command
OVER, but it is written
OVERP to avoid confusion with the Forth stack command
This tabulates printed output across the screen.
9 TAB 18 TAB 27 TAB will move the print position to columns 9, 18 and 27 respectively.
This command calls the SAM ROM routine. (see the technical manual).
32768 3 BLITZ will execute the 3 commands starting at address 32768.
Is a defining word which defines an array to hold your
3 100 100 10 3 100 100 20 8 BLITZ$ CIRCLES
The first 8 numbers are the paramenters needed by the
BLITZ command. The last parameter "8" is the number of
BLITZ parameters and is used to set up the array.
Now by using the command
CIRCLES you can draw two circles one 10 pixels in diameter, and the other 20 pixels in diameter, around the co-ordinates 100,100.
BLITZ parameters reproduced from SAM's Technical Manual are:
PLOT: 1 followed by x,y co-ordinates
DRAW TO: 2 followed by x,y co-ordinates
CIRCLE: 3 followed by x,y and the radius
OVER: 4 followed by 0-3
PEN: 5 followed by 0-17
CLS: 6 followed by 0-1
PAUSE: 7 followed by 0-255
The Forth equivalent of the BASIC
15 15 SCREEN will return the code of the ASCII character or UDG at print position 15 row 15 column.
Creates a user defined character replacing any of the existing characters from code 32 to 255.
It takes 9 parameters. The first 8 represent the dot patterns and the 9th is the character code.
24 24 255 60 60 36 36 144 UDGDEF converts character 144 into a silly little figure of a man.
This is the SAM ROM routine JROLS (see Technical Manual). The parameters are:
- Wrap: 0 for no wrap, -1 for wrap.
- Number of pixels to move by.
- Direction to move: 1=left, 2=up, 3=right, 4=down.
- Length of block in pixels.
- Width of block in pixels.
- X plot position.
- Y plot position.
This routine can be used to define Forth equivalents of the BASIC commands
This command has no parameters but "switches off" the sound chip.
SVC@ SVC! SV@ SV!
These are similar to the standard Forth words
!, but they operate on the SAM system variables in page 0. The address of the system variable as shown in the Technical Manual should be used.
HEX 5A40 SVC@ . DECIMAL will read the SAM system variable "MODE". Although Forth uses the SAM ROM it is paged out much of the time. The above commands will also access page 1 with addresses within the range 32768 - 49151.
This command changes the default disc drive.
3 DRIVE will change to Master DOS RAM disc (if you are using that system - Forth will also run under SAM DOS) and
1 DRIVE will revert to the floppy drive 1.
PLOT DRAW DRAWBY
These are similar to their BASIC equivalents except that
DRAW is the equivalent of
DRAW TO and uses ab solute co-ordinates, and plot position 0 0 is at the top left of the screen.
DRAWBY uses relative co-ordinates like the BASIC
0 0 PLOT 255 0 DRAW 255 170 DRAW 0 170 DRAW 0 0 DRAW will draw a line around the screen, using relative co-ordinates.
0 0 PLOT 255 0 DRAWBY 0 170 DRAWBY -255 0 DRAWBY 0 -170 DRAWBY will draw a line around the screen using absolute co-ordinates.
Sets the permanent screen colours. The parameters are paper code and pen code.
9 15 COLOUR produces blue paper and bright white pen, provided the
PALETTE has been left in its default state.
Puts the character code of the character following the command on the stack.
ASCII A puts the number 65 on the stack which is the character code for a capital A.
Will print out a Forth error message.
1 ERROR will print "Stack empty".
Is similar to the standard Forth word
KEY but it does not wait for a key to be pressed.
Resets the system but does not clear the source code area.
Finds the execution address of the word which follows it.
FIND VLIST EXECUTE would do the same as writing
Accepts input text as far as a delimiter and puts it into
PAD. It puts the start address of the text on the stack and the length of the text into the first address of the
42 WORD will accept text until a "*" is encountered,
Define the following word:
: COUNT DUP 1 + SWAP C@ ;
QUERY 42 WORD and enter "1234*56".
Follow this immediately by
The following will be printed: "1234". If you enter the command
PAD C@ . there will be a "4" printed on the screen. The "4" represents the number of characters entered before the delimiter.
If, however, you type in
PAD 1 + 7 TYPE you will find your your original entry of "1234*56" is printed. The whole entry is transfered to the
PAD, but the number of characters WORD has accepted is indicated by the number in the first address of
PAD and can be used by words such as
Clears input buffer and accepts character input until
RETURN is pressed. It can be edited in the normal way. A word to accept string input could be defined as follows:
: INPUT$ QUERY 13 WORD 1 + SWAP PAD C@ CMOVE ;
The parameter is the address of the area of memory or string variable in which you wish to hold the inputs.
VARIABLE HOLDATA 8 ALLOT defines an area of memory 10 bytes long in which you can hold your input.
HOLDATA INPUT$ and type in "DOG & CAT". Now type
HOLDATA 10 TYPE and you will print out "DOG & CAT", which is now held in HOLDATA.
This is similar to
QUERY but does not clear the input buffer enabling the text to be edited. Move the text into
PAD starting at the second address of
PAD before calling
Puts the address of
PAD on the stack.
Prints to screen the directory of the current drive.
Returns to SAM BASIC. Come back to Forth by typing
GOTO WARM or by typing SHIFT+F7.
C@ but they address the screen. Address 0 is at the top left hand corner.
Prints a string. It can only be used in compile mode.
: EXAMPLE ." This is an EXAMPLE" ;
Uses the SAM's sound chip. It takes 3 parameters: note, octave, length.
- B: 5
- C: 33
- C#: 60
- D: 85
- D#: 109
- E: 132
- F: 153
- F#: 173
- G: 192
- G#: 210
- A: 227
- A#: 293
Middle "C" is in the third octave so
33 3 1 BEEP will produce middle "C".
More details are to be found in the Technical Manual.
Similar to the BASIC
15 0 AT (the equivalent to the BASIC
AT 15,0) will move the print position on the screen to row 15 column 0.
Changes print output.
1 LINKwill print to the bottom of the screen.
2 LINKwill print to the normal screen.
3 LINKwill redirect ouput to the printer.
251 LINKwill allow control codes to be sent to the printer.
When Forth returns to input mode it will return you automatically to its normal mode of printing. Thus to print a
VLIST on the printer all you need input is
3 LINK VLIST.
Forth normally operates using pages 3, 4, 5 and 6. It pages in the SAM ROM as required.
10 PAGE will page in pages 10 & 11 at address 32768. Pages 10 & 11 will remain paged in until the next
PAGE command. The
PAGE command gives you considerable control over your computer, but it also give you a greater opportunity to crash. If your Forth dictionary extends beyond 32768, be very careful how you use this command. You can page out the code you are executing. Make sure that all definitions that use PAGE are situated below 32768, and it is a good habit to restore page 5 as soon as you can in a definition.
10 PAGE 50000 C@ 5 PAGE
PAGE command affects the use of
BSAVE. When a page other than page 5 is paged in at address 32768, files with a start address of less than 32768 will be loaded into, or saved from, pages 3, 4, 5, or 6 as usual. Where the file has a start address of 32768 or above, it will be loaded into, or saved from, the page that is currently paged in at 32768.
These are similar to
!, but operate on ports rather than memory.
252 IN will print the number of the page paged in at 32768.
Terminates a colon definition without inserting an assembler command
RET (code 201, C9 in hex) allowing the user to continue the definition in machine code. Terminate the definition with either
201 C, or use the word
Resumes a colon definition terminated by
;CODE allowing the user to continue in Forth after the machine code sequence.
Requires the numer base as a parameter.
2 BASE will select binary. It is advisable to return to normal by using the words
Notes on numbers
If a number which is input is less than 65536 Forth treat it as a single precision number, if it is greater than 65535 it is treated as a double precision number. If you wish to have a double precision number which is less than 65536 you must enter it as
65535 0 or
Grabs an area of the screen and places it in the buffer area of screen memory starting at address 57345 with the screen paged into areas C & D. the parameters are x-co-ordinate, y-co-ordinate, length, width. It may be easier to use
Defines a special Forth word to hold your
GRAB bed data. The parameters are x-co-ordinate, y-co-ordinate, length, width.
10 20 50 40 GRAB$ FORTHWORD
You can call your FORTHWORD whatever you wish.
In the screen modes 3 & 4 will put a block of data on the screen at the given co-ordinates. The data can be a block that has been grabbed using
The parameters are x-co-ord, y-co-ord, data address, method of placing.
The method of placing is as follows:
- 0= overwrite with
- 1= XOR with existing data.
- 2= OR with existing data.
- 3= AND with existing data.
- 4= overwrite with no
INVERSE(faster than 0).
If you use
GRAB the address of data will be 57345. It is difficult to use other addresses as
GRAB will look for them on pages 0 - 2 which are paged in as the command operates.
Is designed to operate on the data you have stored as a Forth word using
GRAB$. The parameters are x-co-ord, y-co-ord, method of placing.
30 3 1 FORTHWORD PUT$
Will fill the area of memory containing the co-ordinates with the 16*16 pixel pattern at the given address.
The parameters are address, x-co-ord, y-co-ord.
If the address is zero the area will be filled with the current
4 PEN 0 100 100 FILL will fill the are enclosing co-ordinates 100,100 with
PEN colour 4.
We can define a word to fill in with the pen colour (the parameters are x-coord, y-coord, pen colour):
: PFILL PEN 0 ROT ROT FILL ;
Switches the scroll message at the bottom of the screen on or off.
1 ?SCROLL enables the message and is the equivalent of the BASIC
0 ?SCROLL disables the message and is the equivalent of the BASIC
This command takes four parameters: colour, colour, palette entry and y-coordinate.
The colour parameters must be within the range 0 - 127. If the two colours are different you will get a flashing effect, if they are the same you get no flashing.
If the y-coordinate is non-zero it is the y-coordinate to alter the palette at.
PALETTE command to alter the paint pots can be defined as follows:
: SIMPAL SWAP DUP ROT 0 PALETTE ;
That word takes two parameters: colour, palette entry.
Expands the Forth core dictionary to include user definitions allowing you to customize the Forth. Having called the command
HERE U. will give you the length of code to save.
Type SAM and return to basic mode. Then save your expanded Forth with
SAVE "MY FORTH" CODE 65536,length, where length is the length given by
Then alter line 20 of the BASIC interface program to load "MY FORTH" instead of "CODE". Save the BASIC interface under another name.
SAVE "ANOTHERNAME" LINE 1
If you save to another disc, remember to copy the small code file called "PAGE" to the new disc.
The Forth editor stores source code as a continuous block usually in page 7 of SAM's memory. The address of the start of the block, usually 32768, is to be found in system variable "ST" (source top) at address 437. The end address of the source can be found in system variable "SE" (source end) at address 482.
Each line of source ends with code 13. This code is ignored by the interpreter.
A 15-line window is provided into the continuous block of code similar to a standard Forth screen. This window is used to create, edit and delete source code.
The start address of the current window is to be found in the system variable "LISTS" at address 506, and the end of the current window can be found in system variable "ELIST" at address 508.
Before entering any source we need to clear the source memory. We do this by using the command
T makes the current window start at the start of source.
CLEAR clears the source area from the top of the current window to the end of the source code block. In practice it makes the end address of the source code equal to the start address of the current window. We can now begin to enter our source code. We do this with the command
NEWL creates 15 blank lines numbered 1-15. We enter the source code by typing the required line number and pressing the EDIT key - not the return key. If we type in "1" and press EDIT the words "1 EDIT" will appear on the screen. We can then enter our source code into the input line. Press RETURN and our source code appears in line 1 of the window. To enter source in line 2 type "2" and press the EDIT key and so on for each of the lines.
If we have made an error, say in line 4, we type in "4" and press EDIT and our line of source appears in the input line at the bottom of the screen where we can amend it as desired.
Input Line Keys
- DELETE deletes the characters to the left of the cursor.
- SHIFT+DELETE deletes the character to the right of the cursor.
- The left and right arrow keys move the cursor to the left and right in the input line.
- The up cursor key move the cursor to the start of the input line.
- The down cursor key moves the cursor to the end of the input line.
- F2 blanks the input line.
- F0 toggles insert mode on or off. When SamForth is first entered the insert mode defaults to "ON".
- F3 blanks the input line from the cursor to the end of the line.
- SHIFT+F1 will force a break in the Forth program.
When we have filled the current window we can enter the command
NEWL once more and we have the next window of blank lines.
More Editor Commands
D takes as its parameter a line number.
2 D will delete line 2. Line 3 will become the new line 2, line 4 the new line 3 and so on. The new line 15 will be the former first line of the next window if there is one. If there is not the current window will end at line 14.
S also takes a line number as its parameter.
2 S will insert a new line after line 2. This new blank line will be line 3, the old line 3 will become line 4 and line 15 will become the first line of the next window.
2 3 DEL will delete line 2 and the 2 following lines. Line 5 will become line 2.
2 3 INS will insert 3 lines after line 2. Line 2 will become line 5.
3 E will erase the source in line 3 but not delete the line.
1 2 C will copy line 1 to line 2 and also into the PAD.
3 R will replace line 3 with the text held in the PAD.
3 H will hold line 3 in the
PAD for future use.
P is used interally by other editor commands, but if you enter
P followed at once by a line of source, e.g.
P THIS IS A LINE OF SOURCE, that line will be entered as a new source line at the end of the source block.
L lists the current window on the screen or to the printer.
N will list the next 15-line window (if there is one).
B will list the previous 15-line window (if there is one).
3 UP will move the source up 3 lines. 3 lines will be lost from the top and 3 gained at the bottom.
3 DN will move the source down 3 lines. 3 lines will be gained at the top, and 3 lines lost at the bottom.
FROM will move the start of the list. If you have defined a word called FRED, the command
FROM FRED L will list the current window from the word
FRED. It actually lists from the first occurence of !#FRED!#, which will normally be its definition.
F is a shorter version of
FROM, but unlike
FROM does not justify the line in which the required word was found. You can do this with the command
LIST will list source, one definition at a time, pausing at the end of each definition. Pressing any key except SPACE will continue the listing. Pressing SPACE will terminate the listing.
LIST does not list using the 15-line window and does not display any line numbers. It is preferable to use
LIST when printing source. When printing, LIST does not pause after each definition.
FROM indicates the start of a current window or list,
TO indicates the end of a listing.
FROM FRED TO FREDA LIST will run a list from FRED up to but not including FREDA.
This word makes the end of source the end of the current list.
3 LINK T ES LIST will list the whole of your source to the printer.
SAVE will save source to disc.
T ES SAVE PROG will save the whole of your source to disc with the name PROG. The program will save the file to disc as PROG.FS. ("FS" means "Forth Source") Get into the habit of using the commands
T ES before you save a whole source program. If you just do a
SAVE PROG you may be saving only the current window. This may seem like a bind but it does enable you to save parts of your sour code. See below.
Always remember this is Forth. If a command is not there then define it yourself. If you use it often, use
EXPAND to include it in your customized version.
A command to save the whole of source:
: TSAVE T ES SAVE ;
A command to clear the whole source area and load in new source:
: TCLOAD T CLEAR LOAD ;
LOAD has two functions.
It is used first to load source code from disc.
T LOAD PROG will load the source to the beginning of the source area. If the command
T is not used it will load to the end of the current list.
It is used secondly to compile the source code into Forth.
T ES LOAD will compile the whole of your source.
It is possible to compile, list or save a part of your source.
FROM FRED TO FREDA LOAD will only compile the source from the word FRED up to but not including FREDA.
FROM FRED TO FREDA SAVE PART will save the same part of source to disc under the name PART.FS.
If the compilation of your source ends with an error message using
WHERE will list your source from where the error occurred using a graphics character to flag up the offending word.
It is possible to give the editor impossible commands, and when this happens it will make nonsense of the listing. Regain control by entering the commands
SamForth error report
1 - Stack empty
This message appears when you have insufficient data on the stack for the application you are running. Possibly the most common error.
KEY 65 = IF EMIT THEN
What happens here is that having tested your input to see whether it is "A" (ASCII code 65), you no longer have 65 on the stack to
You should write it as
KEY DUP 65 = IF EMIT ELSE DROP THEN
You input your data, duplicate it, test the entry on the top of the stack. If it is 65 you print it, otherwise you discard it.
2 - Stack full
Your application generates too many unused parameters.
256 32 DO I LOOP
I is placing the index number of the loop on the stack and doing nothing with it.
256 32 DO I EMIT LOOP
Will print the character set and leave the stack as it found it.
3 - Undefined word
You are trying to use a word you have not yet defined, or you have mistyped a word.
4 - Colon definitions only
Some words such as
WHILE#!, #!REPEAT and
." can only be used within colon definitions, and not in immediate mode.
5 - Division by zero
Division by zero does not seem to be allowed on any computer. It usually arises in a calculation. Use
IF to make sure it does not happen.
DUP 0 = IF DROP ELSE / THEN
6 - Return stack full
You have put too many parameters on the Return or Z80 stack. Unlikely to occur unless you make excessive use of ">R"
7 - Inside fence
You have attempted to
FORGET a word in the core dictionary, or one you have protected using the command
8 - Break
You have pressed the break keys (SHIFT+F1). Handy if your Forth program has gone into an indefinite loop, or is awaiting an impossible result from a calculation.
9 - Incomplete form
You have used a command like
DO without a
LOOP or a
+LOOP, or a
BEGIN without an
10 - Not found
Occurs when you have used the editor commands
TO followed by a word that cannot be found in the source.
11 - Editor error
You have tried to edit a line that does not exist.
Every time there is an error report, a warm restart occurs, and the Forth stack is cleared.
Machine Code Notes
Each SamForth definition is called using the assembler instruction
CALL (code 205, or CD in hex). Each definition must end in a
RET (code 201 or C9 in hex).
The Forth interpreter does this for you in the normal definitions, but if you want to write definitions in machine code the following notes will be useful.
The Forth words
CREATE can be used for machine code definitions.
CREATE STARS1 6 C, 10 C, 197 C, 62 C, 42 C, 207 C, 193 C, 16 C, -7 C, 201 C,
This definition will print 10 stars.
In Z80 mnenomics:
LD B,10 ; Number of stars to print LOOP PUSH BC ; Preserve B register LD A, 42 ; ASCII code for asterisk RST 8 ; Print asterisk POP BC ; Restore B register DJNZ LOOP ; Decrement B register ; If <>0 jump back to "LOOP" RET
We can use
;CODE in a similar way. The definition STARS2 does the same as STARS1.
: STARS2 ;CODE 6 C, 10 C, 197 C, 62 C, 42 C, 207 C, 193 C, 16 C, -7 C, 201 C,
When we use
;CODE in this way the definition must end with a
RET (code 201, C9 in hex).
We can also use
CODE: to include machine code within a normal definition. STARS3 does the same as STARS1 and STARS2.
: STARS3 10 0 DO ;CODE 62 C, 42 C, 207 C, CODE: LOOP ;
In the last example the final
RET is inserted by the Forth interpreter in the normal way by executing the word
|RST 8||Output to screen, or printer, the character whose ASCII code is in the
|RST 16 (10h)||Push the
|RST 24 (18h)||Pop from the Forth stack into the
|RST 32 (20h)||Put the
|RST 40 (28h)||Place top of Forth stack in
|RST 48 (30h)||Cause warm restart with error report. Error number in the
|1805 (070Dh)||Call a routine in the SAM ROM. The address of the SAM routine must be in the
Useful Calls in SamForth-B
The Forth words below provide the execution address of the Forth stack routines.
Enter them into machine code this way:
205 C, PUSH-HL ,.
||Pop from the Forth stack into the
||Place top of Forth stack in
The stack routines only affect the
To call a SAM routine we use the indirect call using
JSVIN at address 259 (103h).
It is used in the examples above to call the SAM print routine at address 16.
205 C, 259 , SAM-ADDRESS-TO-CALL ,
The parameters in the other registers are those required by the SAM routine.
SamForth variables start at 400 (190h). SamForth-B variables start at 16692 (4134h). The list is identical for both versions, excepting two variables not used by SamForth-B.
|Name||SamForth address||SamForth-B address||Description|
|FLAGS||400 (190h)||16692 (4134h)||Various flags to control the system.|
|LASTK||401 (191h)||16693 (4135h)||ASCII code of last key pressed.|
|BORD||402 (192h)||16694 (4136h)||Current border colour.|
|FRAMES1||403 (193h)||16695 (4137h)||Counts television picture frames into a double number.|
|FRAMES2||405 (195h)||16697 (4139h)||Counts television picture frames into a double number.|
|YCORD||407 (197h)||16699 (413bh)||Last Y position plotted or drawn.|
|XCORD||408 (198h)||16700 (413ch)||Last X position plotted or drawn.|
|RSTACK||410 (19ah)||16702 (413eh)||Address of return stack (Z80 stack).|
|STP||412 (19ch)||16704 (4140h)||Stack pointer to Forth stack.|
|STACK||414 (19eh)||16706 (4142h)||Start of Forth stack.|
|STKEND||416 (1a0h)||16708 (4144h)||End of Forth stack.|
|SAMERR||418 (1a2h)||16710 (4146h)||Holds SAM error number. Not used by SamForth-B, but used by the error trapping code of its BASIC loader.|
|NMI||419 (1a3h)|||Address to jump to when NMI button pressed. Not used by SamForth-B.|
|CLATE||421 (1a5h)||16713 (4149h)||Address of last Forth word in dictionary at cold start.|
|CHERE||423 (1a7h)||16715 (414bh)||Next vacant address in dictionary at cold start.|
|LATEST||425 (1a9h)||16717 (414dh)||Address of last Forth word in dictionary.|
|HERE||427 (1abh)||16719 (414fh)||Next vacant address in dictionary.|
|BASE||429 (1adh)||16721 (4151h)||Current number base.|
|FENCE||431 (1afh)||16723 (4153h)||Address below which
|TIB||433 (1b1h)||16725 (4155h)||Start address of the Terminal Input Buffer.|
|PAD||435 (1b3h)||16727 (4157h)||Start address of the temporary data holding area.|
|ST||437 (1b5h)||16729 (4159h)||Start address of source, usually 32768. The page holding the source file is paged in at C & D.|
|TEMPSTK||439 (1b7h)|||Used as temporary stack store.|
|RAMPAGE||441 (1b9h)||16733 (415dh)||Page number where source file will be held. Defaults to page 7.|
|ERRSP||442 (1bah)||16734 (415eh)||Address at which return stack is set upon an error.|
|CORESTORE||444 (1bch)||16736 (4160h)||Next vacant address in dictionary at cold start. [Not used.
|STATE||446 (1beh)||16738 (4162h)||Flag showing compile or immediate mode.|
|LENGTH||447 (1bfh)||16739 (4163h)||Used to test for the length of a word being looked for in the dictionary.|
|LENG||448 (1c0h)||16740 (4164h)||Used to test for the length of a word being looked for in the dictionary.|
|IP||449 (1c1h)||16741 (4165h)||Address of interpreter pointer within source being compiled.|
|DUBFLAG||451 (1c3h)||16743 (4167h)||Flag indicating double number.|
|BASTACK||452 (1c4h)||16744 (4168h)||Holds stack pointer from SAM BASIC.|
|EDITS||454 (1c6h)||16746 (416ah)||Start address of source to be edited.|
|NUMBIT||456 (1c8h)||16748 (416ch)||Temporary store used during number output.|
|PART1||458 (1cah)||16750 (416eh)||Temporary addresses used during number input.|
|PART2||460 (1cch)||16752 (4170h)||Temporary addresses used during number input.|
|ENDF||462 (1ceh)||16754 (4172h)||Temporary store used during number output.|
|NEGA||464 (1d0h)||16756 (4174h)||Flag for negative number during number output.|
|TEMP1||466 (1d2h)||16758 (4176h)||Temporary store for
|TEMP2||468 (1d4h)||16760 (4178h)||Temporary store for
|IL1||470 (1d6h)||16762 (417ah)||Length of input line before cursor.|
|IL2||471 (1d7h)||16763 (417bh)||Length of input line after cursor.|
|ETIB||472 (1d8h)||16764 (417ch)||End address of Terminal Input Buffer.|
|IFLAG||474 (1dah)||16766 (417eh)||Flag indicating that characters may be inserted into the input line and existing input is not over written.|
|LDFLG||475 (1dbh)||16767 (417fh)||Flag showing that source is being compiled.|
|ERRHLD||476 (1dch)||16768 (4180h)||Address of interpreter pointer position when an error occurred during source compilation.|
|SVBLK||478 (1deh)||16770 (4182h)||Flag used during
|SLEN||480 (1e0h)||16772 (4184h)||Length of source to be saved.|
|SE||482 (1e2h)||16774 (4186h)||End address of source.|
|SADD||484 (1e4h)||16776 (4188h)||Address from where source will be
|HLDS||486 (1e6h)||16778 (418ah)||Temporary store during number formatting.|
|PAIRS||488 (1e8h)||16780 (418ch)||Flags to indicate whether pairs such as
|PAGENO||490 (1eah)||16782 (418eh)||Holds number of page paged in at 32768 in sections C & D.|
|CUR||492 (1ech)||16784 (4190h)||Address of cursor in input buffer.|
|SMODE||494 (1eeh)||16786 (4192h)||Indicates SAM screen mode 1, 2, 3 or 4.|
||496 (1f0h)||16788 (4194h)||Not used.|
||498 (1f2h)||16790 (4196h)||Not used.|
||500 (1f4h)||16792 (4198h)||Not used.|
|LEN2||502 (1f6h)||16794 (419ah)||Used to increase or decrease length of source during editing.|
|LEN1||504 (1f8h)||16796 (419ch)||Used to increase or decrease length of source during editing.|
|LISTS||506 (1fah)||16798 (419eh)||Start address of source list on screen, or of source to be
|ELIST||508 (1fch)||16800 (41a0h)||End address of source list on screen or source to be
|BLONG||510 (1feh)||16802 (41a2h)||Used during source editing.|
|ENDLINE||512 (200h)||16804 (41a4h)||Used during source editing.|
I publish this documentation in order to make it easier to use and preserve it for the future. Also the original SamForth disks can be downloaded.
The original documentation files of SamForth have 64-character lines without line endings (the Tasword Two format, that also Outwrite can use). I extracted them from the MGT disk images, with the help of Edwin Blink's SAM Diskimage manager. (it's written for Windows 95/98 but works fine on Debian with the help of Wine). Then I joined the files and converted them to plain text with the help of
mv BDOC DOCB cat DOC* | dd cbs=64 conv=unblock > samforth_doc.txt
Finally I included the code examples (that were provided in their own files) and edited the result with Vim. I also corrected all typos I found.
The structure and order of the contents has not been changed, excepting: data lists have been converted to tables; the two variables lists have been combined to a single table.