That really depends on the implementation. A good optimising Forth
running on a processor with enough registers will use the registers to
emulate a stack; however, the x86 doesn't have many registers, so that
might be rarer.
Forth doesn't define many uses for registers; as you know, it's highly
stack based.
Which Forth are you using?
>If not, can I access the generated assembly in
>mnemonic or numeric form, so I can see whats going on with my code?
Yes, you can. However, depending on your Forth, you might be suprised.
Many Forths don't emit any actual code; they emit only addresses or
offsets, which are loaded and indirectly called.
There's no standard way to access the code, but if you'll tell us which
Forth you're using I'm sure we can come up with a simple way.
>I'm also really wondering how Forth acts as an assembly language. Can
>anyone point me to a good webpage about these topics (or tell me if you
>have the time and inclination)? I'm having trouble concentrating on
>learning with this question about registers on my mind.
You sound like you'll make a good Forth programmer, then; Forth was
invented largely to be simple enough to be understood completely by the
programmer.
Most Forths have a built-in assembler as well as a Forth compiler, just in
case you need the speed. After you look at the other Forths people have
recommended, you might want to take a look at Pygmy Forth for DOS. Its
beauty is that it's very simple, yet reasonably complete (it has an editor
built-in, which I enjoy modifying to make it work more like I think an
editor should act). Like I said, it's very simple, and all source code is
included.
--
-William "Billy" Tanksley
That depends on the implementor and the designs decisions he
makes. Me? well, I have implemented a direct threaded forth for
16 bit DOS using SI for the instruction pointer, SP for the data
stack pointer, BP for the return stack pointer, CS pointed to
the code area where primitives were stored, DS & SS pointed to
the code/data area for forth definitions and global data and
stacks, and ES pointed to the separate header area. This gave me
more space than a small model would have.
I have also implemented a 32 bit subroutine threaded forth using
ESP for the return stack, EBX for the data stack and EBP for a
local variable frame pointer.
There ain't no standard and each forther does it his own way. In
any particular implementation it is not too hard to find out
(even without the source code) what registers are being used for
what. That is, unless the implementation is subroutine threaded
and uses register tricks for optimization. Then watch out cause
the optimiser might assume you are not playing with the
registers.
In the old days (8086) size and speed both inclined the
implementor to use SI as the instruction pointer since LODSW
JMP AX could be used to executed the next forth cell. Size
inclined the implementor to use SP as the data stack so that POP
and PUSH could be used in primitives. But the 32 bit CPUs have
changed that. Especially cheap RAM and the Pentium optimisations
which incline the implementor away from using LODS and also POP
and PUSH.
If you don't write your own system you will have to look at the
implementation (source if you have it, or else a code dump) to
find out register usage.
As to forth assemblers there are two kinds: forward and
backward. The latter is more 'forthy' in the sense that the
instructions are written like:
vbl1 EAX MOV
vbl2 EAX ADD
The former is more like ordinary assembler code:
MOV EAX , vbl1
ADD EAX , vbl2
Some assemblers like Jim Schneiders will handle both backwards
and forwards instructions. The assembler itself is written in
forth (what else??).
Have fun learning.
Regards.
Seth <zekek...@sprintmail.com> wrote in message
news:7t8o67$1gq$1...@birch.prod.itd.earthlink.net...
> When implemented in an x86, how does Forth utilize the
registers and
> can I access them directly? If not, can I access the
generated assembly in
> mnemonic or numeric form, so I can see whats going on with my
code? I'm
"Elegance is for tailors!" -- Ludwig Boltzmann
So sometimes the stacks are fully simulated with registers, at least on
machines with enough registers... Are the stacks ever actually actually
built up of RAM, so as to be an actual stack of memory addresses?.
> Which Forth are you using?
>
Right now I'm playing with EFORTH, F-PC and SwiftForth. I am
downloading one which is called, I believe, Win32Forth, which I will be
using with Julian Noble's webpage tutorial.
> Yes, you can. However, depending on your Forth, you might be suprised.
> Many Forths don't emit any actual code; they emit only addresses or
> offsets, which are loaded and indirectly called.
Would this be with those Forths not using registers to build the
stacks? Does this have to do with the how the stacks are implemented on an
architecture?
> Most Forths have a built-in assembler as well as a Forth compiler, just in
> case you need the speed. After you look at the other Forths people have
> recommended, you might want to take a look at Pygmy Forth for DOS. Its
> beauty is that it's very simple, yet reasonably complete (it has an editor
> built-in, which I enjoy modifying to make it work more like I think an
> editor should act). Like I said, it's very simple, and all source code is
> included.
I'll check it out, thanks!
Cheers,
Elizabeth
--
===============================================
Elizabeth D. Rather (US & Canada) 800-55-FORTH
FORTH Inc. +1 310-372-8493
111 N. Sepulveda Blvd. Fax: +1 310-318-7130
Manhattan Beach, CA 90266
http://www.forth.com
"Forth-based products and Services for real-time
applications since 1973."
===============================================
Jerry
--
Engineering is the art of making what you want from things you can get.
-----------------------------------------------------------------------
Maybe you are thinking of
http://www.complang.tuwien.ac.at/forth/threaded-code.html
- anton
--
M. Anton Ertl Some things have to be seen to be believed
an...@mips.complang.tuwien.ac.at Most things have to be believed to be seen
http://www.complang.tuwien.ac.at/anton/home.html
I think there was also a discussion by Brad Rodriguez, as well as
some discussion of the direct-threaded mechanism in F-PC's help file.
It sure would! If someone even just knows the website it is at I can
search it out from there, I'd really appreciate it!
Thanks, I'll check that out! I'm starting to wonder about implemeting
Forth in a RISC processor. As I remember there was a Forth called MacForth
(or something) at the same site I got SwiftForth from... Is there a way to
download only the manual for MacForth, and does it contain implementation
strategy?
You needn't struggle to remember the URL, just point newbies to the
FAQs.
The FAQ BOOKS includes 3 URLs regarding threading and 2 printed
references.
If you can recommend others, I will add them.
--
Bye for now ____/ / __ / / / / /
/ / / _/ / / / /
Chris Jakeman __/ / / __ / / /_/
/ / / / / / / \
__/ __/ ____/ ___/ __/ _\
Forth Interest Group United Kingdom
Voice +44 (0)1733 753489 chapter at http://forth.org.uk
No, I'm afraid the manual for MacForth isn't available separately.
Implementing Forth on RISC processors isn't significantly different from
implementing it on other processors. Each processor has its unique set of
features that are either helpful or challenging, and a good implementor
learns the strategies for getting an efficient match. We've implemented
Forth on over 30 processors, and can do a new one in only a few weeks' time.
Cheers,
Elizabeth
(PS: I changed from Netscape 4.7 to Outlook Express 4.72 to try to avoid
the empty postings, and the problem has followed me. I can't delete them
because I don't see them till they're already posted. Maybe it's a server
issue. I'm investigating; meanwhile, my apologies to all)
Seth,
I want to back up to this point in your questions because I think I see
a confusion that hinders you. What follows is long winded. Please excuse
that; I haven't the patience to compact it.
The Forth language assumes a Virtual Machine, as do many others. The
compiler aside, that machine permits one to fetch constants by name, to
fetch and store variables by name, and to operate on these in various
ways, including ways you write - and name - yourself. A sequence of
names is executed by an interpreter, and when one name includes another
(so it must return to the original), the interpreter keeps track by
using a Return Stack. (The return stack can be used within a word -
that's a name that defines an action - for temporary storage, so long
as the stored items are removed within the word. Exceptions are hereby
acknowledged.) Data are passed from word to word on the Data Stack
(commonly called just "stack").
That's the programmer's model. (I didn't discuss the dictionary. It's a
slight to call it an implementation issue, but let's anyhow.) In fact,
an actual impletation may so far differ from the model that analyzing
the code wouldn't likely reveal the model to one who doesn't know what
to look for. An example I have in mind is an optimizing native-code
Forth compiler.
Notice: no mention of registers. Registers are certainly used to
implement the model (a program counter at least!), but they are not part
of the model. However, when writing Forth, one doesn't always write in
Forth. Sometimes one writes in assembler, instead. Then one has to know
how the various registers are used to implement the model, and a little
about the interpreter: how to get back to it. (The way in is called
NEXT.) Usually, the data stack is used to pass values into and out of an
assembly word, just as with Forth words. (In use, those words are
indistinguishable.)
Maybe concrete examples will help to nail this down. The code below has
the same word defined in both Forth (that is, at high level) and
assembler. The machine is a 68HC11, similar to a 6809. Before I show it,
a word about comments.
Good comments explain WHY code does something. WHAT it does should be
evident to a fluent reader. Before we are fluent, we appreciate horrors
like " A B + \ add a to b ". Sometimes, teachers ask for comments like
this so they can be sure that students have written what they meant. All
well and good; the bad is that some programmers continue that practice
all their lives because thay were once told to. I will repeat the code
below with comments meant for a beginner (you, maybe), not just for
myself; don't take that for a model. Never mind what a DDA is!
\ \ \ DDA accumulator / / /
2VARIABLE ACC1 \ An accumulator for a DDA
\ : M+! ( n adr -- ) >R DUP 0< R@ 2@ D+ R> 2! ; \ 615 cycles
\ Adds an int to a double. 90 (+), 87 (-) cycles.
\ Average time can be saved at the expense of max
\ time by testing to see if propagate is needed.
CODE M+! ( n adr -- )
CDEE , 00 C, \ LDX 0,Y
18EC , 02 C, \ LDD 2,Y
E3 C, 02 C, \ ADDD 2,X Add low word
ED C, 02 C, \ STD 2,X
18EC , 02 C, \ LDD 2,Y Synthetic sign extension
2B C, 05 C, \ BMI neg
CC C, 00 , \ LDD # 0
20 C, 03 C, \ BRA prop
\ neg
CC C, -1 , \ LDD # -1
\ prop
E9 C, 01 C, \ ADCB 1,X Propagate carry
A9 C, 00 C, \ ADCA 0,X
ED C, 00 C, \ STD 0,X
C6 C, 04 C, \ LDAB # 4 Pop two cells
183A , \ ABY
7E C, FE4A , \ JMP NEXT
END-CODE
\ Test Words
: S? ACC1 2@ D. ; : N ACC1 M+! S? ; : S! DUP 0< ACC1 2! ;
\ Usage example
: INTEGRATE ( n -- n ) \ with bounds
ACC1 M+! ACC1 @ 4700 MIN 0 MAX DUP ACC1 ! ;
Now let's take it apart.
: M+! make a dictionary entry named M+!
( n adr -- ) \ stack comment. For Forth words, may be enough
>R ( n ) \ move the address to the return stack ("rack" it)
DUP ( n n ) \ make a second copy of the signed integer
0< ( n f ) construed as ( d )
\ convert the copy to FFFF if the number is neg. or 0 if pos.
\ That is exactly what is needed to sign-extend the integer to a double.
\ CAUTION: for some machines, a SWAP may be needed. I just don't know.
R@ ( d adr ) \ copy the address from the rack
2@ ( d d ) \ fetch a double from adr
D+ ( d ) \ add the doubles
R> ( d adr ) \ move the address from rack to stack
2! ( ) \ store d at adr
; \ end definition; clean up the dictionary links
This serves as a way to test my ideas (and the CODE to come), but it is
too slow for my application. To write assembly code, I need to know my
Forth's register usage. (Calling convention and dictionary management
are taken care of by CODE and END-CODE.) Index register Y is the data
stack pointer; decrementing it adds to the stack. On this 8-bit machine,
a data cell is two locations. There two 8-bit accumulators, A and B,
which can be used as a 16-bit accumulator, D, for some operations. The
hardware stack is the return stack. Index register X and accumulator D
needn't be preserved between words. General Forth note: "," stores a
word into the dictionary and "C," a byte. I assemble by hand this way to
save dictionary room; no assembly words are needed.
CODE \ make a dictionary entry
M+! \ name for CODE to use
( n adr -- ) \ stack comment; start with two ints, end with none
CDEE , 00 C, \ LDX 0,Y load X with TOS; adr
18EC , 02 C, \ LDD 2,Y load D with NOS; n
E3 C, 02 C, \ ADDD 2,X add the two bytes pointed to by X to D
ED C, 02 C, \ STD 2,X store the result in the same place
18A6 , 02 C, \ LDAA 2,Y load A with NOS (hi) to see the sign bit
2B C, 05 C, \ BMI neg skip to "neg" if the number is negative
CC C, 00 , \ LDD # 0 Positive. Zero to propagate carry
20 C, 03 C, \ BRA prop
\ neg
CC C, -1 , \ LDD # -1 Negative number. FFFF is needed.
\ prop
E9 C, 01 C, \ ADCB 1,X
\ add the next byte pointed to by X to B with carry
A9 C, 00 C, \ ADCA 0,X and the next one yet to A.
( There is no add with carry to D )
ED C, 00 C, \ STD 0,X store the sums where the addends were
C6 C, 04 C, \ LDAB # 4 jam 4 into B
183A , \ ABY add B to Y; increment the stack pointer
7E C, FE4A , \ JMP NEXT go back to the inner interpreter
END-CODE \ clean up the dictionary links
So (whew!), registers can be important, but they aren't a part of Forth
per se. What you want to do is get the virtual machine firmly in mind,
and there are no registers there. Even if you want to write your own
Forth, WHAT you implement will be the VM. The registers are only a part
of HOW.
Jerry
P.S. OK, Ill tell you anyway. A DDA - digital differential analyzer - is
a circuit that digitally implements an op-amp. Op-amps can solve
differential equations. Remember analog computers? Software DDA models
let me translate analog designs to code and run real time control
systems on processors that don't seem fast enough at first sight.
Well, I'm glad you wrote all that, though the point you were trying to make
(and made well) I already understood (VM and return stack issues). I got
some info out of the code which really cleared up other problems I was having
though (some things which just had not 'clicked' for me until I saw them
coded), so thanks very much!!!
Sent via Deja.com http://www.deja.com/
Before you buy.
jim
"Elizabeth D. Rather" wrote:
Because her new news reader (the latest Netscape offering) posts a blank
one for every real one. You got the ratio exactly right.
Jerry
Turns out it was because last week I got infected by the "Happy99" virus. This
was detected fairly promptly and I thought I had eradicated it, but it turns out
there was an extra hit that we didn't detect. If this post works, it's fixed
now. Not Netscape's fault.
By the way, thanks to Dave Hansen who sent me a useful clue.
Apologies once again for the extra messages.
http://Landau1.phys.virginia.edu/classes/551/
for a version in .ZIPped PostScript form (you can read it with Ghostscript).
The point of the paper (pay attention Forth proselytizers!) is that
you might find the easiest way to get a resistant C or C++ programmer to
look at Forth is by making the assembler do some simple tricks. The
fact is, even if you want ultimately to code in C for whatever foolish
reason, if you need to add some tuned assembly code, develop it in Forth.
You can always add the C boilerplate--setting up and breaking down the
stack frame, declaring segments, etc. etc. afterward. But you will know
that the code part works so any remaining bugs have to do with the boiler
plate and red tape.
I bet that made you REAL happy. Do you have some insight as to how
your machine caught its cold? I'd like to avoid the flu, if poss.
Thanks.
"Happy99" is an easy one to avoid. It's not really a virus. It's a
program that comes as an attachment to e-mail which has to be run to
"infect" a machine. To avoid it, simply don't run it! To be safe, you
should never run a program which you know nothing about.
--
-GJC
-gcha...@shore.net