Skip to main content
© Deekay

For the things we have to learn before we can do them, we learn 
by doing them.

     Aristotle

                            STRENGTH IN FORTH                             
                                part two

                           THE GREEK CONNECTION

Last time I left you on the stack, with nothing to do. But we did 
some arithmetic,  remember ?  We solved 3 5 + .  This time we are 
going to do some more of that.  (That's why I would have left you 
on  the stack anyway !).  In FORTH arithmetic is a matter  of  to 
stack or not to stack....and numbers of course.  It is  therefore 
essential  to  study  thoroughly the stack's  magic  and  FORTH's 
numbers.

NUMBER & BUMPER

Now for the numbers. If you aren't acquainted with the basic (sic 
!)  ins  and  outs of binary and  hexadecimal  representation  of 
numbers both inside and outside a computer,  I suggest you to buy 
a  book on that stuff.  It would be tiresome to get  through  all 
that  here  and now.  So I assume at least you  know  enough,  to 
understand the following explication.
A  computer  does  it  in  binary;  all  ones  and  nulls.  Thus, 
computer's  maths are in binary as well.  Numbers are  stored  in 
binary.  To  store  numbers you need some place  to  store  them: 
locations,    memorylocations.   A   computer   can   find   each 
location by its address.
The  smallest piece of memory used to store numbers is  called  a 
byte. (Of course you may write, if you think you know better; but 
it will cost you a life-time working to pay the back-postage ).
A byte consists of 8 bits.  Each bit can have the value of either 
1 or 0. If you should write down all possible combinations of 0's 
and 1's that fit into a byte, you would have a collection of 256
numbers, ranging from 0 to 255 inclusive.

THE GREAT DECEPTION

Meanwhile,  did you notice that a bit can be 0 or 1, i.e positive    
(= 1), or not-positive (= 0), but NOT NEGATIVE. Handling positive 
numbers  may  well be a natural way-of-life for  a  computer.  To 
handle negative numbers,  we need to mislead the computer. We can 
deceive it by the two's- complement arithmetrick.  Now,  FORTH is 
16-bit oriented.  In unsigned 16-bit arithmetic the lowest number 
you might represent is zero. In binary: 0000000000000000. And the 
highest appears in binary as 1111111111111111,  which is 65535 in 
decimal. In this constellation there are 65536 numbers. Now watch 
the  trick !!  Consider what happens,  if I add 1 to the  highest 
number(65535).

                      1111111111111111
                    + 0000000000000001
                   (1)0000000000000000

As  I have only 16 bits,  the 1 in the 17th place  is  lost.  The 
remaining 16 bits are stored as the value zero.  IF WE ADD A 1 TO 
A  NUMBER AND THE RESULT IS 0,  WE THEN CAN EASILY INTERPRET  THE 
ORIGINAL NUMBER (I.E.  1111111111111111) AS THE VALUE -1.
 In this 
way the computer is mislead to think 16 positive bits is -1.  So, 
if 16 bits are positive (= TRUE),  a number is interpreted as -1. 
Now  it will be clear to you,  why in computerlogic TRUE  is  -1; 
because all bits are TRUE ! Keep that in mind: 16-bit numbers can 
be  thought  of  as either signed  or  unsigned  numbers.  Signed 
numbers  range from -32768 up to 32767.  Unsigned  numbers  range 
from 0 up to 65535. All numbers are integers.
To learn how to ride on horseback, you have to sit on...and ride. 
To use FORTH, you need to know how it works, to know how it works 
you need to use FORTH.  We are going to use FORTH,  to see if  we 
were  right about FORTH's numberhandling.
Just enter:  -1 {DUP} {.} {U.}  -1 65535OK. Let's trace back and 
see what happened.
1.  -1 TOS 2.  DUP (means duplicate value TOS) 3.  . (outputs the 
number TOS) 4. U.  (outputs the number TOS).
The stack shows: -1
                 -1

Now {.} removes the value TOS and prints it as a signed number.
The stack shows: -1
{U.} removes the value TOS and prints it as a unsigned number.
That's where the U stands for: Unsigned.
For  further elucidations on this subject we need to examine  the 
binary form of -1 and 65535.  We can (I can,  you can't)  achieve 
our goal by making a new word by defining a colondefinition.  The 
name 'colondefinition' is quite obvious. The first character is a 
colon.  Here it is.  :  B.  BASE C@ 2 BASE C! SWAP U. BASE C! ;  
OK.
As  a colon is a FORTH-word,  seperate it by a space  from  other 
words.  Semi-colon  always ends a  colondefinition.  Perhaps  you 
didn't realize,  but all numbers till now were output in  decimal 
base,  FORTH's  default base.  You can easily change  that  base, 
simply by storing a new basevalue in the word {BASE}. In the word 
{B.} that was done through the sequence ..2 BASE C!..
Do it now.  2 {BASE} C!  OK. Now FORTH is in binary base. Again, 
changing to octal base. 1000 {BASE} C!  OK. Why on earth 1000 ?
Because  we were in binary and 1000 is eight in binary.  Back  to 
decimal again.  Well said, but how to type ten in octal ? Believe 
me, it is 12. So 12 {BASE} C!  OK. The rest of {B.} is set up to 
return  to decimal from binary.  There is one word  of  interest: 
{SWAP}. {SWAP} exchanges the two top stack values. Type 3 5  OK
The stack shows: 5
                                3
Type  {SWAP}  OK.  Type {.}  3OK.  It is not much like  {.}  to 
print  out  the  second  top stack  item,  so  {SWAP}  must  have 
exchanged  our  two  little numbers,  5  becoming  second  and  3 
becoming TOS. Let's try {B.} (say bee-dot). (One rainy day I will 
teach how to define a Dolly-Dot-word, you bet.)
Type -1 {DUP} {B.} {.}  1111111111111111 -1OK.  Type 65535 {DUP} 
{B.} {U.}  1111111111111111 65535OK.
See,  in binary there isn't any difference between -1 and  65535. 
It is {.} and {U.} that makes a different OUTPUT.
And my Greek connection Aristotle proved he was right in what  he 
was saying about learning things by doing them.
With  {B.}  you  may examine in which  way  FORTH  stores  16-bit 
numbers  internally.  With  {.} and {U.} you may have a  look  at 
their  signed and unsigned visual shapes.  (If you own a  non-83-
standard FORTH,  it may be that the stackwidth is not 16-bit, but 
32-bit. All what was said and all what is to be said about 16-bit
applies equally for the numbers and operators designed for a  32-
bit stack. We'll make further remarks on 32-bit stacks in part 3)

Most arithmetic in FORTH is very simple.  Because you always deal 
with  integers  of  a  fixed  range.  FORTH  supplies  sufficient 
operators  to do all sorts of maths.  Sometimes you will have  to 
write an operator yourself. I will give examples in this course . 
There  is  still  more to tell about numbers.  But  for  now  the 
subject is closed.  We will examine the operators.  All operators 
to be spoken of in the next few lines,  work on 16-bits  integers 
only.  Sixteen-bit  numbers are referred to as  single-length  or 
single-precision numbers.  I prefer single-length:  short s.l. So 
we discuss s.l.-operators.

FAMILYPORTRAIT

We've met one member of the clan,  {+}.  You already know him, so 
say  hello.  Let's  proceed with {-}  (say:  minus).  Minus  acts 
similar  to  the tax-official,  it subtracts.  It takes  the  two 
numbers TOS,  subtracts and places the result back TOS.  Type 345 
344 {-} {.} 
1OK.  Mind,  the  number to be subtracted must be highest on  the 
stack.
Next to Minus is {*} (say:  star).  Star's job is to multiply the 
two numbers highest on the stack and place the product back.  Pay 
special attention to Star,  because it is likely to produce large 
numbers,  which may exceed the 16-bit range.  Type 37 3 {*} {.}  
111OK.
The  fourth clanmember is {/} (say:  slash).  Slash was  born  to 
divide, so he does. Whithout compassion: nothing remains.
Enter e.g. 83 4 {/} {.}  20OK. The remainder (3) is lost.
Slash' twin brother is {MOD} (say: mod). Mod ignores the quotient 
and saves the remainder only. So 83 4 {MOD} {.}  3OK.
The  combination of Slash and Mod gives you and a quotient and  a 
remainder. It is written as {/MOD} and pronounced slashmod. Enter 
83  4  {/MOD} {.} {.}  20 3OK .  The result is not 20.3  or  the 
like, as {/MOD} puts the quotient and the remainder as two 16-bit 
numbers on the stack.
Star and Slash both have a specialised nephew {2*} and {2/} (say: 
twostar - twoslash).  These are very fast operators.  As dividing 
and multiplying by two are most common in use, FORTH's demand for
speed  is due to their birth.  Mind the difference between 2  {*} 
and {2*}, as in writing (space), as well as in speed.

STARSLASH, THE MENACE

Some  lines ago I warned you when you use {*},  to be careful  to 
stay  within the sixteen-bit range.  Now here I present  you  the 
menace  of the clan.  The next operator isn't quite loyal to  the 
Sixteenbitclan. It has a miscellaneous character. You write it as 
{*/} and pronounce it as starslash.  This is how it  acts.  Enter 
please  113 768 {*} 8 {/} {.}  and that's not the right  answer. 
Now enter 113 768 8 {*/} {.}  10973OK.  And that's  right.  What 
happened ?  In the first example the result of 113 768 {*} didn't 
fit into 16 bits (113 x 768 = 87784).  In the second example  the 
result of the multiplication-part of the operator {*/} is as long 
as  32 bits !  This intermediate result is then divided by 8  and 
the final result is put TOS as a s.l.-number.  (In 32 bits signed 
numbers can range from -2147483648 to +2147483647 inclusive.)
The input on the stack for use by {*/} is always the two  numbers 
to be multiplied first, followed by the divider.
Starslash  does  not supply a remainder,  as  does  {*/MOD}.  The 
latter gives you everything:  speed, 32-bits intermediate result, 
quotient and remainder.  I will discuss more fundamental  aspects 
of  these two words together with the subject  of  floating-point 
and scaling.
The  family-portrait  of  our  Sixteenbitters  shows  still  some 
unknown  faces.  Here are {NEGATE} and {ABS}.  They both  perform 
exactly  that kind of action,  you expect them to do  from  their 
name.  {NEGATE} changes the sign of a number,  {ABS} returns  the 
absolute  value of a number.  E.g.  18 {NEGATE} {.}   -18OK  -18 
{NEGATE} {.}  18OK;        .
-18 {ABS} {.}  18OK 18 {ABS} {.}  18OK.  Look carefully at  the 
output  of  the  examples.   Two  pairs  of  words  seem  to   be 
superfluous:  {1-} {1+} and {2-} {2+}.  You may look upon them in 
the  same  way  as  {2*}  and  {2/}.  They  perform  very  common 
stackactions  and  as putting numbers on the  stack  is  somewhat 
slowing down FORTH's speed (He thinks,  though),  these words are 
especially designed for speed.  So 1 {+} is slower than {1+}. Not 

noticeable  when  the plussing is done one time,  but  the  time-
saving aspect of {1+} becomes substantial if the operation has to 
be carried out thousands and thousands of times.

UNSPOKEN

I  owe  you  some  explanation.  I didn't  want  to  disturb  the 
procedure  of what was to be explained about 16-bit  numbers  too 
much,  so  two  words were unspoken off:  {C@} and  {C!}  in  the 
definition of {B.}.
For  now this will do.  {C@} extracts a byte value from the  word 
{BASE}  and  put  that value TOS.  Which  value  depends  on  the 
numberbase FORTH is working in: a 2 in binary, a 10 in decimal, a 
16 in hexadecimal base. {C!} is the opposite of {C@}: it stores a 
byte-value into a word.  So 5 {BASE} {C!} will put the value of 5 
into the word {BASE}. The value has to be TOS.
I  invited  you  to define the word  {B.}.  If  you  accepted  my 
invitation  the definition was put in the  dictionary.  But....if 
you  disconnect    the powersupply or reset your  machine  you'll 
have to reload FORTH.  You will then discover, that our {B.}-word 
has disappeared from the dictionary.  If you want it back, you'll 

have  to  define it anew.  There is of course a way  to  preserve 
self-defined   words  on  disc.   Wait  for  the  editor  to   be 
explained.......

Next  time we will discuss the stack's magic.  Two spells I  gave 
already:  {DUP} and {SWAP}.  But there are some more. And we will 
have a look at FORTH relational and logical operators  too....and 
seeing  things double right now ?  We will discuss  double-length 
arithmetic as well. Keep smiling !!

SUMMARY

  FORTH's arithmetic takes place on the stack.  FORTH supplies  a 
lot of arithmetic operators with specific functions.  Numbers are 
16-bits (or 32-bits) long and integer.  Single-length or  single-
precision  arithmetic  deals  with  16-bits  numbers.   The  s.l. 
arithmetic  operators  are  designed  to  work  on  s.l.  numbers 
exclusively:  a  list  is  provided in this  part  two.  In  s.l. 
arithmetic signed numbers range from -32768 to +32767  inclusive. 
In  unsigned form s.l.  numbers range from 0 to 65535  inclusive. 
Exceeding these limits will give unreliable results.  All signed
numbers are in two's complement form.
On  32-bit  stacks there is no distinction  between  single-  and 
double-length numbers.  REMEMBER
Two's  complement    - The two's complement of a  number  is  the 
                     exact equal absolute value but with opposite 
                     sign.
Integer            -  An integer is a number with  no  fractional                      
parts. E.g. 123, 2, -365 are integers.
Numberbase         - A number is a complex symbol.  In daily life                     
                       we use decimal base.  Ten is the base.  To
                       compose a number there are two main points 
                       to observe: the value of a figure, and the
                       place of that figure in  the  number.  The
                       place  is  calculated from right  (=0)  to 
                       left. An example. Number 23456. The  6 has
                       a value of six and place  0.  The  decimal
                       value of 6 is now 6 * 10^0. Now 10^0=1. So
                       the 6 in place 0 is worth six. As for  the
                       5. The decimal value of the 5 is 5 * 10^1=
                       5*10=50. The 4: 4*10^2=4*100=400,  the  3:
                       3*10^3=3*1000=3000.    In   place  0   the 
                       basenumber is raised to the power of 0, in
                       place 1 to the power of 1, in place  2  to
                       the power of 2 etc.  etc.  When you choose
                       another base, the one thing to  change  in
                       the example above is the 10.
                       E.g. we choose base 8,  octal base.  The 6
                       is 6*8^0=6*1=6.  The 5:  5*8^1=5*8=40. The 
                       4: 4*8^2=4*64=256 etc. etc. You may change
                       to whatever base you like, the calculation
                       remains the same.  The  most  common bases
                       used are decimal,  binary and hexadecimal.
Dolly   Dots   -   A  worldfamous  (in  Holland,  though)  female 
                       popgroup.
Colondefinition    - A colondefinition is the most common way  of
                    defining  new  words.  The  word  {:}  always 
                    opens the definition, followed by a space and
                    the  name of the new word.  Then other  words 
                    follow to define the action of the new word.
                    The last word always is {;}.
Aristotle - Greek philosofer (4th cent.  b.C.).  The quotation is  
to be found in 'Nicomachean Ethics'.

_________________________________________________________________ 
|  word  |      stackaction         |   description             |
|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|   +    | (n1\n2 -- sum: n1+n2)    | Add                       |
|   -    | (n1\n2 -- dif: n1-n2)    | Subtract                  |
|   *    | (n1\n2 -- prd: n1*n2)    | Multiply                  |
|   /    | (n1\n2 -- quo: n1/n2)    | Divide (integer)          |
|  MOD   | (n1\n2 -- remainder )    | Remainder of n1/n2        |
| /MOD   | (n1\n2 -- rem\quo   )    | Leave quotient with       |
|        |                          | remainder beneath         |
|  */    | (n1\n2\n3 -- n1*n2/n3)   | Intermediate product n1*n2| 
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
_________________________________________________________________
|  word  |      stacknotation       |   description             |
|¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|        |                          | is stored as 32-bit number|
| */MOD  |(n1\n2\n3 -- rem\n1*n2/n3)| As */ but also leaves     |
|        |                          | remainder beneath         |
| NEGATE |    (n1 -- -n1)           | Change sign               |
|  ABS   |    (n1 -- |n1|)          | Absolute value            |
|  1+    |    (n1 -- n2)            | Add 1 to top stack item   |
|  1-    |    (n1 -- n2)            | Subtract 1 from top stack |
|        |                          | item                      |
|  2+    |    (n1 -- n2)            | Add 2 to top stack item   |
|  2-    |    (n1 -- n2)            | Subtract 2 from top stack |
|        |                          | item                      |
|  2*    |    (n1 -- n2)            | Fast multiply by 2        |
|  2/    |    (n1 -- n2)            | Fast divide by 2          |
|________|__________________________|___________________________|

EXTRAS

A very popular word in FORTH is FIG.  Although it is a FORTH-word 
you never will encounter it in a dictionary.  It stands for FORTH 
Interest Group.  This group exists to promote interest in and use 
of FORTH.  The parent-group is found in the USA;  but almost each 
country  has  its  own  branch.  Enquire  your  computerclub  for 
addresses. I give you only the USA-address:

  FORTH Interest Group
  PO Box 1105
  San Carlos
  Ca 94070
  U.S.A.

And  if  you  write,  please enclose  a  Self  Addressed  Stamped 
Envelope (SAE)!! 

EXERCISES

1.  Put (as many as you like) negative numbers on the stack.
    Have them output by {B.}. Be sure {B.} is in the dictionary.
    Mark the state of the 16th bit.
    Clear the stack with help of {SP!}.   Repeat,  but this  time 
    with positive numbers. Again, mark the state of the 16th bit.
    What can you tell now about signed numbers regarding the 16th     
    bit ? Explain why that bit is called the sign-bit !
2.  Remember  Starslash ?  On that subject I gave an example that
    turned out to give false answers: 113 768 {*} 8 {/}.  Rewrite
    this example to give the right answer, not using {*/}.
3.  Rewrite this formula:344 X 105 in R.P.N. in two ways.
                            35
4.  What is the remainder of: 576 X 861
                                 15
5.  What is the unsigned equivalent of -986 ?
6.  Write the  next formula down in such a way, that all operands            
    are on one side and the operators on the other side:
    (69 + 3) X 5  e.g. 1480 5 3 97 * + /
        18

7.  {*/MOD}  has two 16-bit numbers put on the stack,  a quotient
    and  a  remainder.   Which of them two is the higher  on  the
    stack?
    Use your brains, not the stacknotation !
8.  Subtract: 8 - 4, but don't use {-}. 9.  Explain the following 
    stacknotation: (n -- n^2). Here is the word, I wrote. :  QUAD 
    DUP * ;.
10. Write your own word of which the stacknotation is (n -- n^3).

Next time I'll give the solutions. Till then !!!

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.