Skip to main content

O born in days when wits were fresh and clear, 
And life ran gaily as the sparkling Thames ;
Before this strange disease of modern life, 
With its sick hurry , its divided aims ,
Its heads o'ertaxed, its palsied hearts, was rife -
Matthew Arnold ( 1822-1888 )- Scholar Gipsy.


                          STRENGTH IN FORTH 

                             Part eight

                 A CLOSER LOOK AT FORTH'S DIGESTION (3)

In  days  when  wits  were fresh  and  clear....and  hearts  were 
stronger than that strange disease,  the poet might have said  as 
far as I am concerned.  For the time being,  I'm back, trying not 
to  sit down and mourn  the loss.  I was very happy to find  that 
the love of the-chief-editor-of-this-magazine   is still  growing 
steadily.  His particulary  extrovert  behaviour  reminds  me  of 
medievial  chivalry.  One  feature  of chivalry  -  the  code  of 
behaviour  of the ideal knight - was the homage paid  to  ladies. 
Every young knight and squire with any pretension to be a man  of 
fashion made a point of being in love when he was not in  battle. 
Wether he devoted himself to one lady or distributed his  favours 
broadcast  was  not  a matter of  much  importance;  but  he  was 
expected to pay exaggerated compliments and elaborate courtesy to 
all ladies. Yes, that were the days that the attitude of life was 
not a mark of respect to numbers.  The attitude of FORTH  towards 
numbers  is  of  a  different  age....those  Modern   Times,   as 
visualised by Charley Chaplin. The numberbase has changed........

A CIVILISED BASEBALL MATCH

In part two of this course we touched the subject of  numberbases 
in  a slightly different context.  Here we will discuss the  roll 
numberbases play in input and output. In that remarkable part two 
we came up with the variable {BASE}.  We called it a word then as 
you weren't able to distinguish between a variable and a word  at 
that  time.  A variable is used to store a particular  value  and 
acts as a symbolic address.  A symbolic address is some place  in 
memory  which we can call by a symbol,  such as a name.  At  that 
address {BASE}, or as we say it in FORTH, in that variable {BASE} 
has  been stored a value which indicates the numberbase in  which 
FORTH  is held to do all numeric input and  output.  The  default 
base  is  the  decimal one.  The default base  is  set  when  the 
FORTH-system is started up, or when you reset your FORTH with the
word {COLD}. 
The  decimal  base is the one most civilised people  use  in  all 
day  life.  (Except  for  instance in  some  respect  the  anglo-
american population, that  massive  conspiracy  against me having 
10  fingers  and  10 toes. Watch out !!).
To convert the current value of {BASE},  you simply have to store 
a  different value in it.   That  is  done  by  the   sequence  n 
{BASE} {!}.  Here n means any value as long as it lies between  2 
and  70.  That last value is specified by the FORTH-standard  and 
may  actually be as high as 255.  If you are going to change  the 
numberbase, be sure there is any chance you remember the base you
were  up  to work in.  Here it's time to point out  to  you  some 
difficulties, that may arise.

FORGETTING YOUR ROOTS

First of all:  what exactly is a numberbase ?  Good asking !  But 
also...poor memory ! Go back to part two and read the explanation 
headed  REMEMBER.  Try to get a clear view on this item.  Such  a 
view  should be composed of simple elements.  These elements  are 
only  two:  the value of the figures  and the place of  a  figure  
in the row of figures that constitute a number. Both features are 
related to the numberbase. As the decimal base is the most common 
one we have learned  to  write - thank the Arabians - we now have
distinct  symbols for the values of that base.  We can use  these 
symbols  quite  easy  to express values  in  numberbases  with  a 
smaller base than 10.  To express values in radices (= plural  of 
radix = latin for root = numberbase) higher than 10,  we have  to 
'borrow'  some  symbols  from  elsewhere.   For  the  purpose  of 
expressing  values in the higher radices,  we use the letters  of 
the  alphabet.  I suppose you are familiar with  the  hexadecimal 
base and the presentation of its figures: 0 1 2 3 4 5 6 7 8 9 A B 
C D E F.  The letter A got the value of ten, C the value of twelf 
etc.  The highest figure,  F ,  has the value of fifteen. Sixteen 
is written as 10.  If your numberbase is twentyfour your  figures 

are  0  1  2  3 4 5 6 7 8 9 A B C D E F G H I J  K  L  M  N.  And 
twentyfour is depicted as...10, of course. Why of course ?  
Let's  return  to  the decimal base.  In decimal  base  we  count 
quantities  in 'packages' of ten.  If the quantity is  less  than 
ten - say 8 - ,  we have zero 'packages' of ten: 10^0. So we have 
8 * 10^0 (= 8 * 1 = 8) things.  If the quantity is more than 9  - 
say eleven - ,  we have 1 'package' of ten:  1 * 10^1 = 1 * 10  = 
10.   Subtracting  ten  from  eleven  leaves  one.  One  is  zero 
'packages' of ten = 1 * 10^0 = 1. Now composing the number 11, we 
place the number of zero 'packages' at the rightmost  place,  the 
number of 10^1-packages one place to the left. So the number 1234 
has 4 packages of 10^0, 3 packages of 10^1, 2 packages of 10^2, 1 
package of 10^3.  If you start reading again at 'Let's return  to 
the decimal base' and you substitute ten and decimal by  whatever 
number you like,  you'll see that the explanation will fit  quite 
9[...................................................]0
well  for any base.  A numberbase  is  the number that  indicates 
by what 'packages' you are counting quantities. 
Another  problem is your memory.  Enter {COLD} {BASE{ {?} 10  ok
That  brings  us in decimal base. Change the numberbase  with  16 
{BASE} {!}.  Testing the result with {BASE} {?} gives 10  ok.  So 
the radix didn't change at all ? Now think ! We did put ourselves 
in  hexadecimal  base  and  16  decimal  is  written  as  10   in 
hexadecimal !  Enter 8 {BASE} {!}. Will that work ? Yes, it will, 
because  in  hexadecimal  the symbol 8 is  used  to  represent  a 
quantity of eight.(But you can't change to 32-base (decimal) with
32 {BASE} {!} when you are in hexadecimal).  Enter {BASE} {?}  10 
ok
.  Remember: FORTH will always return 10, when you enter {BASE} 
{?},  no  matter in what numberbase you think you  are.  So  that 
isn't  of much help,  if you forgot your roots.  It costs  little 
effort to think of a solution to that problem.

BACK TO YOUR ROOTS

Indeed,  if you know the word {DECIMAL}.  This word always brings 
you back to the decimal radix.  So we can define the word {BASE?} 
as :  BASE?  BASE @ DECIMAL .  ; @ fetches the value of {BASE} in 
the current base and {DECIMAL} converts it to decimal, {.} prints
the base in decimal at your CRT. {BASE?} will destroy the current 
base.  To maintain the base,  we have to define a smarter version 
of {BASE?}.  But that's up to you. Most systems provide words for 
radix-conversion,  such as {HEX} and {BIN}, which will change the 
radix to hexadecimal and binary respectively, irrespective of the 
current  base.  By now it is not difficult to see that these  two 

words could be defined as :  HEX DECIMAL 16 BASE !  ;  and :  BIN 
DECIMAL 2 BASE ! ;.  
Many decimal-to-hex routines have been published in  BASIC,  with 
greater or lesser degree of complexity.  In FORTH such a  routine 
costs a penny.  Type {DECIMAL} to make sure we start in  decimal. 
Then define the word {D>H} as :  D>H  HEX .  DECIMAL ;  . You can 
use  this  word  to convert decimal numbers into  hex  simply  by 
entering  63 D>H 3F ok.  This routine can easily be  modified  to 
translate between any two bases. When converting numbers from one 
base to another,  you should experiment with negative numbers  as 
well in order to find out how this will work best. (Read part two 
carefully on number-representation). 
In  this context I must mention two more words connected  to  the 
subject  of  numberconversion and -printing.  They are  {H.}  and 
{DEC.}.  I suppose, that the action of those two words is easy to 
guess.  Look  again at the definition of {D>H}.  You  might  have 
thought  that the sequence of {HEX} {.} and {H.}  were  identical 
and  that is not true.  {H.} indeed displays a number in  hex  as 
does {HEX} {.},  but {H.} returns to the current radix before  it 
converted the number and the other one does not, it stays in hex.
The  same  applies for {DEC.} with the decimal base as  the  only 
difference. 
It's  quite  obvious  that  you aren't going  to  use  a  lot  of 
different  numberbases.  Most computingprograms use  the  decimal 
base for input and output of numbers.  This applies for the user,
as  well  as  - in most cases - for the  programmer.  As  far  as 
FORTH is concerned:  use hex when you mean memory-addresses, when
you are defining  words using the symbolic assembler or when  you
define words using  machinecode; use binary when drawing sprites; 
use decimal in all other circumstances.  

THE GREAT NUMBERWAITER

Most  FORTH-applications  don't  require  special  routines   for 
numeric  input.  Since,  in general,  words expect to find  their 
numeric data on the stack. And this can be placed there by use of 
the keyboard interpreter before the word is executed. How this is 
done  can  be  seen  by the way the  {.GCD}-word  was  used  some 
chapters  ago (chapter 5).  Occasionally it may be  necessary  to 
wait  for  numeric  input during the execution  of  a  word.  The 
keyboard interpreter isn't designed for that kind of  operations. 

So  you  will have  to  define your own  word.  In  part  six  we 
discussed  some words that wait for input:  {QUERY} and  {EXPECT} 
were  used to wait for text to be put in.  Why not use  them  for 
numeric input ? Well, let's try it. Here is a numberwaiterword: 
: WFNI  CR ." ?" 
        QUERY 32 WORD
        NUMBER DROP 
;
The  analysis shows:  new line and give prompt,  accept  text  to 
buffer,  transfer  characters  to  wordbuffer with  ASCII  32  as 
delimiter,  convert  to 32-bits number.  {DROP} makes a  16  bits 
number out of the 32 bits number in a 16 bit system. In a 32 bits 
system {DROP} has to be left out,  as the default numberlength is 
32 bits. Instead of {QUERY} you may use {EXPECT}. Both words were 
discussed extensively in part 6 with examples of their use.
The disadvantage of this routine is that the stack is cleared and 
execution stopped if a non-valid character is found in the input.
This  rather  drastic action for a mistyped input  is  caused  by 
{NUMBER}.  If the keyboard interpreter can't determine the  typed 
charactersequence as a word in the dictionary,  then it will hand 
it over to {NUMBER},  which will try to convert the characters to 
a number.  Valid characters for numberconversion are a minus-sign 
as the first character,  a decimal point as the last one and  all 
characters  that  may  be interpreted as digits  in  the  current 
numeric base.  If {NUMBER} cannot succeed in producing digits, it 
will  abort  the  routine.  So if XCFDCVCXZ will  likely  not  be 
recognised  as a dictionary entrance,  and {NUMBER} jumps out  of 
its head at the sight of such garbage, an abortion follows.     
An  alternative number-inputroutine may use the  word  {CONVERT}. 
Just  like  {NUMBER}  its action depends on  the  width   of  the 
computationstack;  is it 16 or 32 bit wide ?  There are two  main 
differences between {NUMBER} and  {CONVERT}.  Firstly,  {CONVERT} 
will  not  generate  an error message on  detecting  a  non-valid 
character.  The  address of the first unconvertible character  is 
left  on the stack instead. Secondly, it does not test the  first 
character  for the presence of a minus-sign.  The  input  routine 
could show like: 

CREATE *BUF  80 ALLOT
: CLEAR *BUF 80 ERASE ;
: >*BUF CLEAR *BUF 80 EXPECT *BUF ;
HEX

: INPUT  BEGIN  CR ." Enter number: " >*BUF DUP C@ 2D = DUP >R -
                0 SWAP 1- CONVERT 
                C@ DUP BL = OVER 2E = OR
                OVER 0= OR 0=
         WHILE  R> 2DROP 2DROP ." Not valid"
         REPEAT R> IF
                     >R NEGATE R>
                   THEN DROP DECIMAL
;

I  choose to define {INPUT} in a FORTH,  which uses -1  as  true. 
That's  why the minus is used in the sequence C@ 2D = DUP >R -  . 
If  a minus-sign has been entered the result of {C@} 2D {=}  will 
be put as -1 TOS.  Subtracting -1 is the same as adding 1 to  the 
address at which the minus-sign (in ASCII-format,  of course) was
stored.  {>R} saves the t/f-flag onto the  returnstack for  later 
use  by R> (after {REPEAT}) putting the t/f- flag TOS for use  by 
{IF}.  The {1-} may seem very strange,  but the word {CONVERT} in 
this particular FORTH adds 1 to the address of the {*BUF}.  So  I 
had to subtract 1 first in order to bring myself back next to the 
byte that holds the minus-sign and at the byte that contains  the 
first  digit.  All this shuffling was carried out in order to  be 
able to except a minus-sign as input and to include a  minus-sign 
in  the  output by means of negating the  number  constructed  by 
{CONVERT}. Now the conversion can take place. {CONVERT} picks out 
of  the inputstream one character at a time and hands it over  to 
{DIGIT}  for  the actual conversion.  As long  as  the  character 
offered  is a digit,  {CONVERT} will look for the next  digit  in 
the next byte.(It really is a Digital Research, one might say).  
If  it is  not a  digit that  is encountered,  then  the  address 
of  that byte is put TOS.  You can't see that happen  inside  the 
definition of {INPUT},  as it is all part of the internal  action 
of {CONVERT}.  When execution has left {CONVERT},  {C@}  examines 
the  byte  of  which  the  address  has  been  placed  TOS.   The 
testing is done on three possible characters:  a blank ({BL}),  a 
decimal  point  ( ascii 2E),  or a 0.  All that testing  then  is 
{OR}red to gain the right true or false flag for {WHILE}.  If the 
result is a false flag,  then the stack is cleared and a  message 
kicked off to your display:  Not valid. And execution switches to
{BEGIN}  again and again until a valid number has  been  entered. 
The code after {REPEAT}  gets the minus-flag from the returnstack
and  if  true there was a minus-sign,  {NEGATE}  will  turn   the 
converted number to negative.  

Much  more observations can be made on the  {INPUT)-word:  -  the 
word  is written in a FORTH with a 32 bit computationstack -  the 
word  is much more versatile than the {WFNI}-word - it needs some
adaptations - may be - to run in your FORTH.

A SORTING ALGORITHM

Now  you  know all about numeric input.  but  not  about  numeric 
output.  FORTH provides operators to let you format your  numeric 
output.  You  know  {.},  plain dot.  {.R} also prints  a  signed 
number, but you can specify the format. 123 4 {.R} will print the 
number 123 at the right of a field of 4 characters wide.  I  will 
give you a more or less complicated program  to show you how {.R} 
may be used. 

: <MOVE   4* 0 SWAP  DO  ( sourceaddr destaddr count --- )
                       OVER I + 4 - @
                       OVER I + 4 - !
                - 4  +LOOP 2DROP

: LARRAY  CREATE 4* ALLOT 
          DOES>  SWAP 4* + 
;
256 LARRAY S-D
511 CONSTANT RAND
: FILL-ARRAY  256 0 DO 
                      RAND RND I S-D !
                    LOOP
;
: SHOW-ARRAY 252 12 / 0 DO 
                          12 0 DO
                                 J 12 * I + S-D @
                                 6 .R 
                               LOOP CR
                        LOOP
;

: SORT-ARRAY 255 MIN 1 DO 
                         I S-D @
                             I 0 DO
                                   DUP I S-D @
                                   > NOT
                                        IF
                                          I S-D DUP 4 + J I -
                                          <MOVE DUP I S-D ! LEAVE
                                        THEN
                                 LOOP DROP
                        LOOP


The  ideas for this routine were found in  HCC-nieuwsbrief-77,  a 
Dutch computermagazine. There have been made some adaptations and 
definitions of {LARRAY} and {<MOVE} were added. In a 16 bit FORTH 
you  have  to  replace 4 by 2 everywhere.  The word  {RND}  is  a 
randomnumber  generator and {4*} may not be available; it can  be 
replaced by 4 {*} or 2* for 16 bit FORTHs.

This  short  application  will work smoothly,  when  you  act  as 
follows:  - fill the array {S-D} with randomly chosen numbers  by 
executing the word {FILL-ARRAY};   - inspect the contents of  the 
array with {SHOW-ARRAY}; - sort the array with n {SORT-ARRAY} , n
being  any number smaller then 257;  - check the array  on  being 
sorted with {SHOW-ARRAY}.  It is not a fast sorting routine. This 
is  not  as  much due to FORTH,  as it is the  algorithm  of  the 
routine itself. 
In  a 16 bit FORTH {.R} will work on single-length numbers  only. 
To display a 32 bit number you will have to use {D.R}.  With {U.} 
you  can  display  an unsigned number. 

THE GREENGROCER'S ALGORITHM

FORTH   provides  even  more sophisticated  words  for  formatted 
numeric output. So far you never encountered any decimal point in 
a  number.   But  one  day  you  were  overheard  by  your  local 
greengrocer  when you were boasting again about your  programming 
skill  in  FORTH.   He  asked  you to write  a  program  for  his 
bookkeeping. Bookkeeping involves money, almost always. And money 
is expressed in a particular currency-notation e.g.  £ 1100.23 or 
$ 123.12. I am sure, that your greengrocer will count the section 
after the decimal point as well, yes every penny of it. There you 
are..!  FORTH  won't  understand you when you type  £  11.23.  Of 
course there is a solution,  although I am not a greengrocer  and 
not  much of a bookkeeper.  The first thing to bear in  mind  is, 
that a greengrocer does not mind to type 112312  when he means  £ 
1123.12,  the  pound  sign is a lesser god.  Also, don't pay  any
attention  to that decimal point. FORTH will accept 112312 as the 
integer 112312. And if the green beans were sold at a total price
of £ 234.56, then the input of 23456  will bring the number 23456 
on top of the stack.  To add 112312 with 23456 is simply done  by 
{+}, which leaves  135768. To please our middle class worker, you 
could  format  the output with all respect you  owe  money,  i.c. 
including the £-sign and the decimal point.( Thank heaven a pound 
is  no  longer split in 20 shilling and every  shilling  into  12 
pence !! ).
The word that will do the job is called Printpounds, short {.P}.

: .P    DUP ABS <# # # 46 HOLD #S SWAP SIGN 32 HOLD 156 HOLD #>
        TYPE SPACE ;

12345 {.P} £ 123.45 OK. To print £ 12 you will have to enter 1200 
{.P}  to get £ 12.00;  0012 {.P} will result in £ 00.12.  In  the 
{.P}-word are used many new and unknown words.  In spite of their 
strange outfit they are easy to read,  if you know how.  First of 
all  we  have {<#}.  In FORTH # means number,  so {<#}  could  be 
translated as 'start numberformatting'. The {#} means convert one 
digit,  so  {#} {#} means convert two digits.  By all means  this 
should be clear !! Next we meet 46 {HOLD}. {HOLD} will insert the 
specified  -  by  its ASCII-value - character  in  the  converted 
string. Here the character is a dot. The word {#S} is easily read
as 'numbers' and it converts the remaining digits.  The action of 
{SIGN} is to insert a minus sign if necessary. The two characters 
to  be  inserted by {HOLD} are a space (32) and a  £-sign  (156). 
Having completed that job,  all that remains is to terminate  the 
conversion  and  to  leave  the  converted  string  ready  to  be 
displayed  by  {TYPE}.   Explaining  the  action  of  the  number 
formatting words I spoke of 'string' several times.  That  should 
have surprised you !  But it didn't,  I suppose ?  Remember  that 
numbers  are put on a stack.  They are put there in binary  form, 
not in ASCII. So if we enter 12345, then there will be the binary 
representation of that number on top of the stack.  The first {#} 
we  use after {<#} will convert the least significant digit  into 
ASCII,  which it then stores at {PAD}.  You should consider {PAD} 
as  a  region of memory,  used as a scratchpad  for  numeric  and 
text operations.  {PAD} itself is a system constant,  leaving the 
startaddress  of  the scratchpad buffer.  After  all  the  number 
formatting words have done their jobs,  the scratchpad will  hold 
(!)  a characterstring rather than a binary  number.  That's  why 
{TYPE} can do the display and not {.} or the like. 
The words {#},  {#S},  {SIGN} and {HOLD} may only be used between 
{<#} and {#>}. And all act on the number(32 bit or double) TOS . 

FURTHER DETAILS OF THE G.G'S ALGORITHM

The  above example of number formatting shows  another  important 
feature.  If  it  is  necessary - as it was in the  case  of  the 
greengrocer's  bookkeeping  -  to  display   a  'floating  point' 
number,  it is not said that the internal arithmetic should be in 
floating  point  format.  That can be carried out  completely  in 
integer arithmetic in most cases, it's even much faster. There is 
a compromising solution.  Let's be fair,  the greengrocer is  all 
day  concentrated on pounds and shillings split with a  point:  £ 
10.23.  In the evening he absolutely will type 10.23 and not 1023 
as  I wanted him to do that in the earlier example.  It's only  a 
greengrocer,  not a computerfanatic. Let him type his earnings in 
the way greengrocers think they should do...

First we compose a new word, that will facilitate the output.

: .P2   DUP ABS DPL @ 0 MAX 
        <#
        ?DUP IF 
               0 DO # LOOP
             THEN
        46 HOLD #S  SWAP SIGN 
        32 HOLD 156 HOLD
        #>
        TYPE SPACE
;

If  you compare this word with the previous {.P}-word,  you  will 
discover a great likeness.  The main difference is the use of the 
word {DPL}.  When I enter 123.456 OK and then {DPL} {?} 3 OK  and 
then 12.3456 OK {DPL} {?} 4 OK, you will notice that shifting the 
decimal point affects the value of {DPL}, according to the number 
of  digits  on the right side of the decimal  point.  When  there 
hasn't  been typed a decimal point in the number,  the  value  of 
{DPL}  will be -1.  The current value of {DPL} is always that  of 
the last number put on the stack.  I used that value to set up  a 
{DO.....LOOP}.  In each turn of the loop a digit is converted and 
moved  to {PAD}.  That is,  as many digits as in the last  number 
were  right  of the decimal point.  The {IF...THEN}  checks  with 
{?DUP} and {MAX} if the value of {DPL} was higher than 0.  If the
value is less or equal then no decimal point has to be inserted.
{.P2} definitely shows that between {<#} and {#>} other words are 
allowed.
The  input  of  12.34 will be transformed in £ 12.34  by  use  of 
{.P2}.  I  think,  you're going to get some free meals  from  the 
greengrocer now !! Stringbeans, may be, weird stringbeans ?! 
Next time we will travel into the Stringdom of FORTH.

                                             $Till then$ 

SUMMARY

|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|    WORD      |   STACKNOTATION   |       DESCRIPTION          |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|     COLD     |     (  ---  )     |The cold start procedure on |
|              |                   |first entry in the system.  |
|              |                   |All values are set to their |
|              |                   |default. It may be used from|
|              |                   |the keyboard to restart with|
|              |                   |the nucleus dictionary alone|
|  DECIMAL     |     (  --- )      |Sets BASE to decimal numeric|
|              |                   |conversion for input/output.|
|  HEX         |     (  --- )      |Sets BASE to hexadecimal    |
|              |                   |numeric conversion for input|
|              |                   |and output.                 |
|  DEC.        |     ( n --- )     |Displays n in decimal base, |
|              |                   |using the format of {.},    |
|              |                   |regardless of the current   |
|              |                   |value of BASE.              |
|  H.          |     ( n --- )     |The hexa equivalent of DEC. |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|    WORD      |   STACKNOTATION   |       DESCRIPTION          |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|  NUMBER      |  ( addr --- n )   |Converts the characterstring|
|              |                   |starting at addr to a signed|
|              |                   |number n using the current  |
|              |                   |numeric base. A leading nega|
|              |                   |tive sign and a trailing dec|
|              |                   |imal point may be included. |
|              |                   |A non-valid conversion is   |
|              |                   |followed by an errormessage.|
|              |                   |NUMBER ignores the decimal  |
|              |                   |point.                      |
| CONVERT      |(n1 add1--n2 add2) |Converts text starting at ad|
|              |                   |dress add1 to the equivalent|
|              |                   |stacknumber. The value of n1|
|              |                   |is left as n2 with regard to|
|              |                   |current base. The address of|
|              |                   |the first non-convertible   |
|              |                   |character is left as add2.  |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|    WORD      |   STACKNOTATION   |       DESCRIPTION          |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| <#           |    ( --- )        |Sets up for numeric output  |
|              |                   |formatting. The conversion  |
|              |                   |is performed to produce text|
|              |                   |at PAD.                     |
| #            |  ( n1 --- n2 )    |Converts the least-signifi- |
|              |                   |cant digit of n1 to the cor-|
|              |                   |responding ASCII character. |
|              |                   |Stores it at PAD and leaves |
|              |                   |the remaining part of the   |
|              |                   |number as n2 for further con|
|              |                   |version. Used between <# and|
|              |                   |#>.                         |
| #S           |  ( n1 --- n2 )    |Converts number n1 into text|
|              |                   |at PAD by repeated use of #.|
|              |                   |Used between <# and #>.     |
|              |                   |n1 is left on the stack with|
|              |                   |the value of zero as n2.    |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|    WORD      |   STACKNOTATION   |       DESCRIPTION          |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
| #>           |( n1 --- add count)|Terminates numeric conversi-|
|              |                   |on by dropping n1 and leaves|
|              |                   |address and charactercount  |
|              |                   |of the converted string in a|
|              |                   |form suitable for TYPE.     |
| HOLD         | ( c --- )         |Inserts ASCII-character c   |
|              |                   |into a converted numeric    |
|              |                   |string. Used between <# and |
|              |                   |#>.                         |
| SIGN         | ( n1 n2 --- n2 )  |Stores an ASCII-character   |
|              |                   |minussign into the converted|
|              |                   |numeric output string at PAD|
|              |                   |if n1 is negative. Used be- |
|              |                   |tween <# and #>.  n2 is  the|
|              |                   |absolute value of n1.       |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯

|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|    WORD      |   STACKNOTATION   |       DESCRIPTION          |
|¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯|
|  PAD         | ( --- addr )      |A constant which leaves  the|
|              |                   |address of the start of the |
|              |                   |text scratchpad buffer.     |
|              |                   |Numeric characters are      |
|              |                   |stored downwards from PAD,  |
|              |                   |text is stored upwards.     |
|   DPL        |  ( --- addr )     |User variable used to  store|
|              |                   |information about the posi- |
|              |                   |tion of the decimal point in|
|              |                   |a number.                   |
|   .R         |  ( n1 n2 --- )    |Prints number n1 at the     |
|              |                   |right-hand end of a field of|
|              |                   |n2 spaces.                  |
 ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯                 

EXTRAS

The other day a new FORTH was launched in the Federal Republic of 
Germany:  32 Forth. It is a 32-bit FORTH. It is released by Markt 
& Technik.  Rainer Aumiller and Denise Luda wrote especially  for 
this FORTH a huge book of 531 pages,  of which most is  dedicated 
to 32 Forth.  The other part describes FORTH in general and  this 
is really worth while reading (for me and Germans most).  
The book's identity: ISBN 3-89090-237-5. Ed. Markt & Technik.
Price 49.- DM. 

EXERCISES

In the previous part 8 I didn't give any exercise, because of the 
subject of the Editor we were dealing with.  This time you'll get 
your the exercises to which you are entitled.
Next time you'll get the solutions.

1.  In  the text above I invited you to write a word to  get  the 
    numberbase, without affecting the original base. Now do it !!
2.  The FORTH-standard specifies a range of 2  to 70 for  {BASE}.
    What would be a practical upper limit and why ?
3.  Conversed negative numbers can be displayed with  {.}.  Which
    word would be more useful ?
4.  Write the definitions of {H.} and {DEC.}. !
5.  Is  it  possible  to use the {INPUT}-word for  entering  non-
    decimal symbols ? If yes, how ?
6.  If you convert the number 65 decimal to hex,  you get 41.  It
    is hard to tell, wether 41 is a decimal or a hexadecimal num-
    ber,  if you don't know the current radix.   Rewrite {H.}  in 
    such a way,  that you always can see,  wether a number is hex 
    or not. So 41 hex is displayed by new {H.} as &H41, say.
7.  Rewrite new {H.} of exercise no. 6, to display negative hexa-
    decimal numbers as -&H41 !!
8.  Why can't one  change the radix to 32 (decimal) by  32 {BASE}
    {!} when in hexadecimal base ?

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.