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.