Skip to main content

Why is my verse so barren of new pride,
So far from variation or quick change ?
Why with the time do I not glance aside  
To new-found methods and to compounds strange ?
 
W. Shakespeare (sonnet LXXVI)

                          STRENGTH IN FORTH
                              part three
                      IS FORTH A LIE-DETECTOR ?

                          ( By C. Janssen )

Yes !  And I will reveal to you,  who is the liar.  FORTH  himself
maybe ?  Wait and see !!  First follow me to Merlin's cave. We are
going to have some magic.  In FORTH Merlin's Cave is known as The
Stack.  A hand points to the entrance of The Stack:  {SP@}.  Let's
see if The Stack is empty.  Use {.S} △ Empty OK.......or not empty
of  course  if some grues were still visiting The  Stack.  If  The
Stack wasn't empty, {.S} will not have altered it anyhow, contrary
to  {.}  .  The  latter  is  stack-destructive,  {.S}  leaves  the
stackitems as it found them. Clear the stack with {SP!} △ OK.
(If you had any trouble with {.S} or more likely with {SP!},  take
a look at EXTRAS).
Check  the  clearing  with our stackscanner  {.S}.  Now  put  some
numbers on the stack: 1 2 3 4 5 6 7 8 △ OK. Use {.S} △ 1 2 3 4 5 6
7 8 OK
.  Repeat {.S} △. You got the same output, I hope. Enter {.}
{.}  {.}  {.} {.} {.} {.} {.} △ 8 7 6 5 4 3 2 1  OK.  This  output
should now have surprised you. Take a good look at both outputs.
{.S}  always  prints out the top stack item to the right  and  the
bottom  to the left.  Using {.} repeatingly as we did will  output
the top stack item left and the bottom right. Enter {.S} again.
FORTH tells you the stack is empty: {.S} scans the items, {.} also
removes them.

THE BIG LIE

Enter  {SP@}  {.}  △ 326368 OK.(The number may  differ  with  your
FORTH).  As told before {SP@} points to the actual entrance of the
stack i.e.  the top. The stack was empty, so 326328 is the address
of  the bottom.  Enter {SP0} {DUP} {.} △ 326684 OK .  This  is  an
address too.  I duped it,  because I need to fetch something  from
that address. Fetching items from addresses is accomplished by {@}
which word curious enough is called 'fetch'. Which item is hiding
at address 326684 ? Enter {@} {.} △ 326368 OK. The same number as
we managed to get from {SP@} when the stack was empty.  At address
{SP0} is stored the address of {SP@} when the stack is empty, i.e.
the bottom-address. Enter a number:  123 △ OK.  Let's go through  
all that stuff again: {SP@} {.} and {SP0} {DUP} {.} {@} {.}.   The
respective output was:  326364 326684 326368.  Not good enough for
the Guiness Book of Records ?  The output of {SP@} is 4 LESS  this
time as it was the first time,  yet we put a number ON the  stack.
Have  you ever seen a stack growing lower after you put  something
on  it ?
Is FORTH confused ?  (FORTH confused..? Never !). Let's enter more
numbers to give him another chance: 456 789 △ OK. Next {SP@} {.} △
326356  OK.  He  did it again !!  The stack  grew  downwards,  not
upwards.  And how is {SP0} doing ?  Try it. {SP0} {@} {.} △ 326368
OK
.  At least that one is stable.  What mystery crossed our paths-
of-life by now ?  The traditional spells won't help us here, we'd
better  read  in FORTH's dictionary and find  a  modern  computer-
spell.  Here  are some:  {.S} {DEPTH} {OVER} {DROP}  {SWAP}  {DUP}
{ROT}  {ROLL}  {PICK}.  Perhaps we can unravel  the  mystery  now.
{DEPTH}  seems  an interesting one.  What's  going  downwards,  is
somehow  related  to depth.  Enter {DEPTH} △  3  OK.  That's  most
helpful,  isn't it ?  Now wait, we put three numbers on the stack,
and maybe {DEPTH} knew.  Type 234 △ OK.  Now {DEPTH} △ 4  OK.  One
more time:  watch, {DUP} {DEPTH} △ 5 OK. (Why five ?). See it with
{.S}.  We'll  doublecheck the action of {DEPTH} with  {DROP}.  The
word  {DROP} removes the top stack item and never tells  where  it
went.  In one go {DROP} {DEPTH} △ 4 OK.  Hit !! {DEPTH} knew !! So
it  must  have its stackconnections ?   Right you  are.  The  word
outputs  the  number of items on the stack.  And  FORTH  calls  it
'depth',  not  'height'.  Thus,  I  must have given  you  a  wrong
impression of the stack,  writing things as top of stack,  putting
numbers on etc.  Am I that liar then ?  FORTH may suggest that  to
you,  but  I  am  not !    I gave you the conventional idea  of  a
stack,  as a stack in real life should be: a pile whereupon we can
put  things  and  where we can take  things  from.  But  inside  a
computer  real  (human) life doesn't come  in  account.  Inside  a
computer a region of memory is set apart. The word {SP0} gives you
the address, where you can fetch the address of the stack's start.
The word {SP@} supplies the address where FORTH can find the TOS.
Depending  on what  stackactions  take place, the address supplied
varies, increasing and decreasing incessantly.
To  put it more computerlike:  {SP@} gives you the address of  the
most accessible stackitem.  So if you {DROP} an item,  there isn't
really made any move:  the Stack Pointer got a new address, that's
all.  If you then put an item on,  you simply overwrites the  item
you  thought you removed.  Enter {.S} 123 456 789 234 OK.  We  now
{SP@} .  We got the address of the TOS. Let's find out what really
is on that address:  {@} {.} 234 OK.  Marvellous,  isn't it ?  And
what about clearing the stack with {SP!} ?  Well, you then replace
the  {SP@}-value  with  the  address  stored  at  {SP0}.   Try  to
understand the following:  :  CLST SP0 @ SP@ !  ;  . Understanding
that will be easier when you know that {!} is the opposite of {@}.
{!}  is  called 'store',  simply because it stores values  at  the
desired address.  1234 {SP@} {!} will store the number 1234 at the
current address of {SP@}. Think of all the possibilities you  have
with  those seven simple words;  {.S} {SP0} {SP@}  {SP!}  {@}  {!}
{DEPTH}. You have complete control  of the stack. With the help of
some other words like {+} and {-} you can (dis)organize the  stack
to  your  free  will.

STACKMANIPULATION

But you better use the  stackmanipulators which are ready  for use
provided  by  the system itself.  You already  know  some:  {DUP},
{SWAP},  {DROP}.  And  others  are:  {OVER}  {ROT}  {PICK}  {ROLL}
{?DUP}.   Some more may  be in your FORTH.  Such as {-ROT}  {TUCK}
{NIP}  etc.  At  the  end  is  a  table  with  stacknotations  and
descriptions of a number of stackoperators.
Why do we need such a lot of stackoperators ?  Well, to change the
order  of the items on the stack.  Did you try to solve the  sixth
exercise of part 2 without the use of a stackoperator ? Tcheeee..!
Take this for instance:  3X^2 - 5X +  4,  a  quadratic expression.
Now you have to calculate  this formula  for  various values of X.
Of course you  can  adapt the calculation  to  each separate value
of X.  If,  for  example  our little X has the value 2, the result
could be found as follows: 2  2  * 3 * 2 5 * -4 + .    This can be
improved  upon  by  using  stackoperators  in such  a way that the
X-value needs to  be  typed only once:

                      STACK CONTENTS
2                     2             ( This is the chosen X-value )
DUP DUP 3             2 2 2 3       ( 3 is on top                )
* *                   2 12          ( 3*2 (6); 6 TOS ; 6*2 (12)  )
SWAP 5                12 2 5        ( First swap 2 12,then 5 TOS )
*                     12 10         ( 5*2 (10), 10 now TOS       )
- 4                   2 4           ( 12-10 (2), then 4 TOS      )
+                     6             ( 2+4 (6), 6 TOS             )
.                     Empty         ( Print TOS on display       )

If X's value is 7,  only that first 2 on top has to  change,   the
rest  remains the same.  The result now being 11.  ( As  I'm  very
smart,  I wouldn't bother at all.  The result for each value of  X
can  be obtained by adding that last 4 to the value of X.  Try  it
!).  The advantage of this is that everything, except the value of
X can be made into a colondefinition.
: QUAD   DUP DUP 3 * * ( n -- )
         SWAP 5 * - 4 + . ;
It works like this: 4 QUAD △ 8 OK  9 QUAD △ 13 OK.
Here  is a list of useful stackmanipulations,  which  require  two
words:

STACK BEFORE        STACK AFTER       WORDS USED
1 2                 1 1 2             OVER SWAP
1 2                 2 1 2             SWAP OVER
1 2                 2 1 1             SWAP DUP
1 2                 1 2 1 1           OVER DUP
1 2 3               2 1 3             ROT SWAP
1 2 3               3 2 1             SWAP ROT
Try them out at the keyboard. And use {.S}, as {.} will respond on
1 2 {OVER} {SWAP} with 2 1 1. Do you remember why ?

32-BIT STACKS

I  made a promise to spend a few words on 32-bit  stacks.  As  you
might have noticed,  I let FORTH output numbers which won't fit on
a 16-bit stack:  326684,  326364. Remember that the highest number
that fit into 16 bits is 65536.  All FORTHs for Atari ST I know of
are nearly Standard-83. So nearly....because of their 32-bit stack
and aberrant method of mass-storage. There may be two main reasons
why  you  choose for a 32-bit stack.  The 68000 MP  is  internally
organised to work on 32-bit size and secondly the addressbus is 24
bits width.  This implies that working with a 32-bit stack is  far
more easier handling addresses to reach into the full potential of
memory-space.  On the 'outside' - you,  the user -  numberhandling
has  grown  less complicated.  You have no longer to  worry  about
single  and  double length numbers.  All numbers  ranging  from  -
2147483648  to +2147483647 inclusive (unsigned 0  -  4294967295  )
will  comfortably  fit  on  the  32-bit  stack,   without  further
requirments. It is even possible, that a double length number set
is included in your FORTH, double now being 64 bits.
On the other hand the 68000 MP allows operations on  bytes,  words
and longwords,  8, 16 and 32 bit resp. The implication can be that
a wide variety of all kinds of operators is defined in a FORTH.
Your manual should supply a so called GLOSSARY,  a description  of
all  the words your FORTH can work with.  There you will find  the
extend  and exact stacknotation of your system.   
One  more remark I'll bring up here.  It might have  crossed  your
mind,  that  numberhandling  in  FORTH has  certain  rather  tight
limits. Don't get disappointed,  that you can't    handle enormous
numbers in FORTH.  Remember the following.    Astronomy deals with
big  numbers,  don't  you think ?  Well,  FORTH was  designed  for
astronomical  purposes  !  We  humans intend  to  scale  down  big
numbers.   We   don't  say:   that  star  is  at  a  distance   of
30480000000000000 km,  or 3,259 lightyear,  but at 1 (lovely  one)
parsec. That's more convenient to the limits of our imagination.
It saves time too !!

A FAIRY_TALE

Well, once upon a time there were double-length numbers. You could
easily recognize them at their size of 32 bits.  The stack had  to
be warned if you wanted to put a d.l.-number on.  The number had
to be marked: 1203457., e.g. a dot had to terminate the number. So
12. was a d.l. number, as was 1234., 23143567. and 0. Some  FORTHs
allow more d.l.-markers (e.g. , ; : ) and the place in the  number
is free.
There was (is) only one d.l. arithmetic operator: {D+}. To add two
numbers,  there were several possibilities:  1) add 2 s.l. numbers
2) add 2 d.l. numbers 3) add 1 s.l number to 1 d.l. number.
Ad 1. put 2 s.l. numbers on the stack and use {+}: 4 5 {+}.
Ad 2. put 2 d.l. numbers on the stack and use {D+}: 78960. 341234.
{D+}.
Ad 3. put 1 s.l. number on the stack and 1 d.l. number ? Wrong !!
      That won't work.  If even only one number of a  series  you    
      wanted to add is of d.l.-format,  all numbers have to be  in
      that format.  So,  234 124536.  {+} or 234 123546. {D+} will
      give a false result. This will work: 234. 123546. {D+}.
To check the result {.} won't work on d.l. format either. The d.l.
equivalent of {.} is {D.}. Using a 32-bit stack, all these kludgey
things are over and out. (Except with multiplication and division.
Examine  the exact stacknotation for information about the kind of
numbers an operator expects on the stack).
To subtract two d.l.-numbers you had to write a word of your  own.
Here it is: : D- DNEGATE D+ ; . (Remember one of the excersises of
part  two  ?).  {DNEGATE} is of course  the  d.l.  counterpart  of
{NEGATE}, as {DABS} is of {ABS}. To manipulate d.l.-numbers on the
stack there are special words:  {2DUP}, {2DROP}, {2OVER}, {2SWAP},
{2ROT}. They accomplish the same task as {DUP}, {DROP} etc. do, on
d.l.-numbers. They can also work  on a combination  of  two  s.l.-
numbers.

SERIOUS AGAIN

These  five  are  of interest for  32-bit  stacks  too.  Let's  be
practical. Enter 123 345 567 789 {2SWAP} .S △ 567 789 123 345 OK.
Pay serious attention to how the swapping is performed. At least 4
items have to be on the stack for {2SWAP} and {2OVER}.  {2DROP} is
less  demanding:  at least two,  as is {2DUP}.  {2ROT} expects  at
least six items. Play dropping and swapping and duping and rotting
(hmmm) to get used to those operators.  Be aware,  that the  exact
action  of  these {2....} depends on the kind  of  stackitems they
operate upon.
We are going to enter the twilightzone of mixed operators.
These operators are all related to multiplication and/or division.
For example {UM*} is a mixed operator.  The stacknotation is ( uw1
uw2  -- lproduct ).  The two operands may not exceed the  unsigned
16-bit range,  while the result of the multiplication is a  32-bit
number.  In working with mixed operators,  consult your manual for
the exact use.  Most Mixed operators are declared mixed by use  of
the character 'M' in the composition of the name of the  word,  as
{UM*} for instance.

WHAT ABOUT FORTH's RELATIONS

One  group of operators I must review:  the relational  and  logic
ones.  Relational  operator....the  word sounds as if  it  cost  a
fortune.  But  if I name one and only one you will  recognize  one
when you see 'm.  Here it is: {=}. And here are more: {<} {>} {<>}
{0=} {0<} {0>}.  These operators always test if a relation  exists
between  at  least  two  items on  top  of  the  stack.  They  are

frequently used in conjunction with conditional loops as {IF..ELSE
..THEN}.  I  won't  give any example of this use.  I would have to
explain to  you,  how to use conditional loops.  I'll better  wait
till then. Some of these operators test the relation of the TOS to
zero:  {0=),  {0<} etc.  Let's have some fun: clear the stack, and
put a number on, 8 △ OK. Now enter {0=} △ OK. You asked FORTH if 8
equals 0.  Look up FORTH's answer with {.S}.  You will find a 0 on
the  stack.  The result of the testing was false (0).  If you  now
{0=}  again,  followed by {.S},  you will find a -1, denoting  the
testing (  0 = 0 ? ) was true.  Well,  I told  you in part two: -1
denotes TRUE in computerlogic. Be  careful,  FORTH  considers  all
numbers to be true (-2,  3, 12345, -124578 ), except the number 0,
which is always false.  Enter {SP!} 8 6 {<} △ OK.  How do you read
such an expression ?  You probably know this from BASIC:  IF 8 < 6
THEN  GOTO 120 or IF ATARI > COMMODORE THEN LIVE =  GOOD.  In  the
first  example 8 is compared to 6 to test if 8 is smaller than  6,
which is not (false=0). The second example is to show that live is
still worth living.  So,  in 8 6 {<} you do NOT compare 8 and 6 to
test if 6 is smaller than 8. Think of 8 6 {<} as 8 {<} 6. This aid
counts  also  for  other  relational,   logical  and  arithmetical
operators.  Two relational operators do not leave a true or  false
result on the stack:  {MIN} and {MAX}.  The first compares the two
numbers on top of stack and leaves the smaller, the other one acts
similarly,  but  leaves  the higher number.  Both words  are  most
frequently  used  to set the low and high limits  in  such  events
as  DO-LOOP-  and  conditional-loopconstructions.  I'll  give  one
example in advance. : LOOPY  10 MIN 0 DO CR ." I'm going loopy !!"
LOOP  ."  Phhhheeeeeeew...!!!" ;  We made a  new  word  LOOPY.  It
executes as follows. 5 LOOPY △
I'm going loopy !!
I'm going loopy !!
I'm going loopy !!
I'm going loopy !!
I'm going loopy !! Phhhheeeeeeew...!!! OK
Again, but with a higher number. 100 LOOPY △ . Our psychological
most interesting sentence is now printed out...no,  not a  hundred
times,  but  only  10.  All due to the fantastic  job  {MIN}  did,
keeping my enthusiasm  within certain limits. Notice, how the text
was typed between {."} and {"}.

NOR TO BE NAND NOT TO BE

You  do know logical operators,  don't you ?  Such tiny  words  as
{NOT}, {OR},  {AND},  {XOR}. All this logic isn't as frightning as
most  people  think.  The temptation to show you that logic  is  a
very exciting world,  tickles my brains.  Two more logic operators
are {EQV} and {IMP}.  But they are not frequently used.  You never
will  encounter {NOR} or {NAND},  in a  computerlanguage.  But  in
electronics nand is very popular.  It is (theoratically)  possible
to exclusively wire a computer with NAND-gates. I should remember,
that some issue later on is dedicated to logic.
Now let's go in binary. We did it once before: 2 BASE ! △ OK.
FORTH accepts only 2 figures in binary: 1 and 0 !! Try it: 8 △ 8?.
The  questionmark shows that FORTH has completely forgotten  about
the  other figures.  So 1 and 0 !!  All logic needs 2  parameters,
at least,  except {NOT},  which needs only one.  This even applies
for "hardware logic" !!
Enter 1111 1100 {AND} {.S} △ 1100 OK. What happened ? Let's put it
right up.    1111                0000        1111
             1100 {AND} and more 1100 {AND}  1111 {AND}
             1100                0000        1111

You  know  1  and 0 as binary figures.  But also  as  TRUE(1)  and
FALSE(0).  At  the very moment you use a mathematical operator  in
binary base,  FORTH treats 1 and 0 as figures,  which  constituate
numbers,  which  count quantities.  At the very moment you  use  a
logical function,  FORTH considers 1 and 0 as TRUE and FALSE,  not
forming numbers, as EACH 1 and EACH 0 is taken apart, not counting
quantities, but signalling qualities ( TRUE and FALSE ).
Also, a bit can only be 1 or 0.  And..yes an electric wire can  be
set  on  (1) or off (0) current.  So here it all  comes  together:
electronics,  logic and binary base.  Two simple(!!!) elements  as
TRUE  and FALSE,  1 and 0,  ON and OFF rule the whole business  of
computers.  So,  if  you are getting angry or bored  reading  this
words,  true, blame your computer for on(c)e and turn it off; it's
all voltage !!
Back  to the examples.  The first one:  1111 1100.  The four  ones
signalling  (flagging)  four times TRUE,  the two  ones-two  nulls
flagging  two times TRUE,  two times FALSE.  Now {AND}  takes  the
rightmost of 1111 and the rightmost of 1100,  1 and 0.  With  this
TRUE-FALSE  parameters  the {AND}-function gives FALSE  (0)  as  a

result. The leftmosts  of 1111 and 1100,  both 1 (=TRUE),  have  a
TRUE after {AND}ing them, like this: 1111
                                     1100 {AND}
                                     1100 .
The  second  example shows,  that {AND}ing FALSE and  FALSE  gives
FALSE  as  a  result.  From  here off  we  can  derive  so  called
Truthtables.  You  can find them in the manual of ST-BASIC and  in
most computerbooks. Just remember, that 1111 1100 {+} is something
quit different from 1111 1100 {AND}. Try it out !!
Also try out the functions of {OR} and {XOR},as done for {AND}.
And  don't forget to experiment in other numberbases.  And try  to
see some logic in the magic.
Logical   operators  are  frequently  used  in  conjunction   with
conditional loops,  as relational operators are.  In that context,
notice  that  {0=} has resemblance to {NOT}.  But they are used in
a different way.  E.g.  .....{DEPTH} {0=} IF.....has a significant
meaning,  as  {DEPTH} outputs a number.  But .....{SP@} {SP0}  {>}
{NOT} IF.....easily reads as 'if the value of {SP@} is NOT higher
than the value of {SP0)',as the use of {0=} in this case does not.
A special word on {NOT}.  {NOT} outputs in 32-bit,  so 1111 {NOT},
will give 11111111111111111111111111110000 and 1111111 {NOT}. will
give 11111111111111111111111110000000.  See, the {NOT}ting is done
bit by bit at the rightmost side.  All logical operators work  bit
by  bit.  The most exotic and less understood operator  is  {XOR}.
Sometimes also called {EOR} in BASIC.  One application of {XOR} is
to  determine the sign of the product of two numbers.  A  negative
number has its leftmost bit set to one.  The {XOR} of two  numbers
of the same sign (i.e.  whose leftmost bits are both 0 or both  1)
will be a number with a zero leftmost bit,  indicating a  positive
number.  With  two numbers of the opposite sign,  the  {XOR}  will
result in a 1 leftmost bit, showing the result to be negative. The
value of the result has in this context no meaning.
The last logical operator is {TOGGLE}.  It is somewhat like  {XOR}
in this, that it exclusive-ors the low order byte of the top stack
number with the byte,  whose address is second on the  stack;  the
result  is  placed at this address.  It is  used  in  byte-masking
operations,  as to change particular bits. Here is a definition of
{TOGGLE} in FORTH-assembler, merely for the sake of demonstration.
Watch the EOR mnemonic !  Here it is: CODE TOGGLE SP )+ D0 MOVE SP
)+ A0 AMOVE BYTE D0 A0 EOR C;
This part three tends to grow to heaven,  but I'd like to stay  on
earth for some while.

Next  time  we're going to discuss loops.  We  now  have  mastered
enough  of  the  stack's  mysteries  to  successfully  jump   from
stackiness to loopiness.  Whatever that may be.................

                            Till we meet in heaven.

SUMMARY

To  get  the full of arithmetic  in  FORTH-style,  FORTH  supplies
several words to manipulate the order of items on the stack.  They
also serve to rearrange the order of parameters in the way a  word
expects them to be. These words are called stackoperators.
To  test  stackvalues on quantitative conditions  there  are  many
operators, called relative operators.
To  test  if a condition is TRUE or FALSE we can use  the  logical
operators.
Both relative and logical operators are often used in  combination
with   conditional   loops   as   IF..ELSE..THEN,    BEGIN..UNTIL,
BEGIN..WHILE..REPEAT and CASE-structures.
I shuddered to think of the discussion on 16- and 32- bit  stacks.
The use of 32-bit stacks allows an easier way of numberhandling,as
I learned, for most common arithmetic.
It  isn't  possible to list all arithmetic  and  other  operators,
which appear in the many ST-FORTHs,  commercial as well as  public
domain.

Please  now load the next part of this course,  which  is  called
"Forth Course IIIb"!

Disclaimer
The text of the articles is identical to the originals like they appeared in old ST NEWS issues. Please take into consideration that the author(s) was (were) a lot younger and less responsible back then. So bad jokes, bad English, youthful arrogance, insults, bravura, over-crediting and tastelessness should be taken with at least a grain of salt. Any contact and/or payment information, as well as deadlines/release dates of any kind should be regarded as outdated. Due to the fact that these pages are not actually contained in an Atari executable here, references to scroll texts, featured demo screens and hidden articles may also be irrelevant.