[net.lang.forth] single-stepping in Forth

anderson@uwvax.ARPA (05/03/84)

<>

Single-stepping in Forth is not hard if you understand how the virtual
machine works and how it is implemented.  The key is to modify only
the "inner interpreter", the piece of code that transfers control
from one word to the next.  All it does is, roughly speaking,

MOV (IP)+,W
JMP @(W)

where IP and W are Forth virtual registers (IP is like a program counter).
How this is implemented depends on your machine, but it is not complicated.

You can implement single stepping by inserting a call to your debugging
routine before or after the MOV.  This assumes the routine is assembler,
not Forth.  If it's Forth things are messier because you don't want
debugging routine single-stepping through itself.  There is probably
some way to do it involving a flag.

The only other way of doing single stepping I can think of is to
modify "docol" (the code pointed to by the CFA of colon definitions).
However, this would not really be single stepping because it
would not "break" at the start of "code" words.

I used single-stepping while I was bringing up Forth on my 6809 system;
the inner interpreter contained a couple of NOPs for this very purpose, and
I replace them with a jump to the monitor.  One thing, though, is
that you have to do an awful lot of single stepping to get anywhere.

Hope this helps --  David Anderson (anderson@uwvax (or wisc-rsch, as
					they call it now))

liberte@uiucdcs.UUCP (05/08/84)

#R:uwvax:-24100:uiucdcs:30900008:000:2039
uiucdcs!liberte    May  8 15:05:00 1984

Although the single stepping methods suggested by Dave Anderson may be 
helpful, particularly in bringing up a new system, neither of them do
what I had in mind, as stated.

They are both "global" stepping, in that they would step through everything
(except code words).  What I wanted was "local" stepping that would step
through just the words I choose.  To do this by changing (modifying the
compiled code of) either the inner interpreter (;S, I believe) or the docol
word, one would also have to have a table of words that are being stepped
through and the stepper would have to continuously determine whether it
is supposed to step through the current word.  Blechkt!

The alternative is, as I suggested, to change just the CFA of those words
which you wish to step through and have the stepper control the interpreting
of those words.  Then the inner interpreter would always return to the
stepper as each subword finished.  A schematic of the stepper follows.

: step  ( instead of docol for stepped words )
  magic words to initialize
  begin
   load next subword address
   display name of subword
   prompt for command
   if step then execute subword
   ( return here )
   more magic words
  again
;


Another approach is to have the stepper change the subword address following
the next subword to reference the stepper again so that after the next
subword returns, the stepper is activated again.  This would act like a
series of breakpoints.  The problem here, as with breakpoints, is that the
address replaced by the stepper address must be saved and restored, probably
on the return stack.  Another more serious problem is that finding that
address depends on what the next subword does.  Literals stored in the code
would have to be jumped over correctly.  This is an argument for keeping
literals in a separate place, as in Smalltalk, another threaded interpreted
language of more appropriate design.


Daniel LaLiberte,  U of Illinois, Urbana-Champaign, Computer Science
{moderation in all things - including moderation}