-
Notifications
You must be signed in to change notification settings - Fork 1
14.Debugger_SEE
Used in the form
SEE cccc
it will print how the word cccc is defined along with NFA, CFA, PFA data. If cccc is a “colon-definition” the result will show a simplified de-compilation of it.
For example, the word TYPE
is a “colon-definition” and is defined as follow:
: TYPE( a n -- ) \ Send to current output channel n characters starting at address a.
BOUNDS
?DO
I C@ EMIT
LOOP
;
If you give
see type
it will print
Nfa: E7CA 84
Lfa: E7CF 7C0 LEAVE
Cfa: 2C2B 26EF
BOUNDS (?DO) +12 I C@ EMIT (LOOP) -8 EXIT ok
The first line shows TYPE
Name Field Address ($E7CA) followed by $84 that is the counter byte of a 4-bytes length
name. The counter byte always has the most significant bit set, that is $80 added to $04 giving $84.
The second line is the Link Field Address ($E7CF) which holds a heap-pointer $07C0 to LEAVE
’s NFA that in this case
happens to be the previous definition in the dictionary.
You will notice these two fields (NFA and LFA) are stored above address $E000 (i.e. MMU7) and they are effectively stored
in one of the extended 8K-RAM pages.
Assuming you launched dot-command .vForth, the third line is the Code Field Address ($2C2B) that contains the actual machine code to be run which in this case is a “CALL” to the ENTER routine of any colon-definition, located at $26EF.
The compiled code slightly differs from the source, e.g. LOOP
from the source is compiled as (LOOP)
followed by the displacement to the beginning of the loop itself.
Another example: the word NIP
, that removes the second element from Stack, isn’t a colon-definition, isn’t a colon-definition, but a low-level definition coded in machine-code as follow:
CODE NIP ( n1 n2 -- n2 ) \ Drop the second element on the stack.
POP HL| \ Get n2 from stack
EX(SP)HL \ Swap it with n1 and discard it
NEXT \ Jump to next instruction
C;
And if you give
see nip
it will print
Nfa: E2EE 83
Lfa: E2F2 2E5 DROP
Cfa: 25CE DDE3
25CE E1 E3 DD E9 FD 02 E1 F1 ac]i} aq
In this case, since NIP
is a low-level definition, the PFA part is shown as hex DUMP
and no "PFA" part, it's a real machine-code routine.
This is an example of use of the ASSEMBLER
built-in vocabulary available via NEEDS ASSEMBLER
.
Again, the first line shows NIP
’s NFA ($E2EE in this case) and $83, the count-byte, that indicates a 3-bytes length defi-
nition name.
The second line is NIP
’s LFA ($E2F2) that contains a heap-pointer 02E5 to DROP
’s NFA, the previous definition
in dictionary.
The third line is NIP
’s CFA ($25CE) which content is the machine-code routine itself.
Examining the subsequent DUMP
you should be able to recognize E1 for POP HL, E3 for EX(SP),HL and DD E9 for
JP(IX) back to the inner interpreter address that is compiled by NEXT
Assembler definition.
The four bytes that follows – FD 02 E1 F1 – are the beginning of the subsequent definition compiled in dictionary (TUCK
in
this case): Try $02FD FAR 2+ 8 DUMP
to inspect in HEAP its NFA.
Another example is the definition IF
a colon-definition that compiles a conditional branching in the program flow,
defined as follows:
: IF ( -- a 2 ) \ compile-time
COMPILE 0BRANCH
HERE 0 , 2
;
IMMEDIATE
with the following output:
Nfa: EC5C C2
Lfa: EC5F C53 BACK
Cfa: 3DEE 26EF
COMPILE 0BRANCH HERE 0 , 2 EXIT ok
In this case, since IF
is an IMMEDIATE
definition, the NFA length-byte is $C2 instead $82.
vForth-Next - a Sinclair ZX Spectrum Next Forth