Re: CS-101 problems and their FORTH solutions.
Posted: Tue Jan 29, 2019 10:23 pm
GARTHWILSON wrote:
Martin_H wrote:
This might be an embarrassing admission, but does Forth usually contain a run time trace and profile feature? I've never used one.
Code: Select all
1 # LDY,
IP )Y LDA, W 1+ STA, DEY,
IP )Y LDA, W STA,
<some.address> JMP,
Here is the code from the Blazin' Forth system loader.
Code: Select all
SCR #19
0 ( UTILITIES -- DEBUGGING: RP@ UNRAVEL ?PARAMS SDBJUN85)
1 CODE RP@ ( -- ADDR RETURN STACK 1- )
2 XSAVE STX, TSX, TXA, PHA, 1 # LDA, XSAVE LDX, PUSH JMP, END-CODE
3
4 : ID? ( TRUE IF VALID NAME)
5 DUP @ [ ' : @ ] LITERAL =
6 SWAP @ C@ [ ' FORTH @ C@ ] LITERAL = OR ;
SCR #20
0 ( UTILITIES -- DEBUGGING: ;NEXT NEXT> >NEXT SDBJUN85)
1 HEX
2 VARIABLE 'TRACE VARIABLE <IP VARIABLE IP>
3
4 CODE ;NEXT ( EXIT THEN NEXT )
5 ( EXIT) PLA, IP STA, PLA, IP 1+ STA,
6 ( GET W) PLA, W STA, PLA, W 1+ STA,
7 ( NEXT) CLC, IP LDA, 2 # ADC, IP STA, CS
8 IF, IP 1+ INC, THEN, 0 # LDY, W 1- JMP, END-CODE
9
10 CODE NEXT> ( RESTORE NEXT)
11 018 # LDA, NEXT 0B + STA, 0A5 # LDA, NEXT 0C + STA,
12 084 # LDA, NEXT 0D + STA, NEXT JMP, END-CODE
13
14
15 DECIMAL
SCR #21
0 ( UTILITIES - DEBUGGING: >NEXT <IP> ID.L SDBJUL85)
1 HEX
2 CODE >NEXT ( N -- POINT NEXT TO N)
3 04C # LDA, NEXT 0B + STA, BOT LDA, NEXT 0C + STA,
4 BOT 1+ LDA, NEXT 0D + STA, POP JMP, END-CODE
5
6 CREATE <IP> ASSEMBLER
7 <IP LDA, IP CMP, <IP 1+ LDA, IP 1+ SBC, CS NOT
8 IF, IP> LDA, IP CMP, IP> 1+ LDA, IP 1+ SBC, CS
9 IF, DEX, DEX, IP LDA, BOT STA, IP 1+ LDA, BOT 1+ STA,
10 W 1+ LDA, PHA, W LDA, PHA,
11 'TRACE LDA, W STA, 'TRACE 1+ LDA, W 1+ STA, W 1- JMP,
12 THEN, THEN, ' ;NEXT @ 0C + JMP, DECIMAL
13
14 : ID.L ( CFA LEN -- )
15 OVER >NAME DUP ID. SPACE ROT 1- - + SPACES ;
SCR #22
0 ( UTILITIES - DEBUGGERS: 'EXIT STEP TRACE CONT SDBJUL85)
1 : 'EXIT ( CFA -- LAST WORD)
2 BEGIN 1+ DUP @ ['] EXIT = UNTIL ;
3 VARIABLE CON
4 : STEP ( CFA -- )
5 NEXT> CR @ 10 ID.L .S SPACE KEY CONTROL "{CONTROL P}" OVER = IF
6 CON OFF DROP CR ." P? "
7 BEGIN QUERY RUN CR ." P? " CON @ UNTIL
8 THEN CONTROL "{RUN/STOP}" OVER = IF
9 DROP CR ." TRACING OFF" QUIT
10 THEN DROP <IP> >NEXT ;NEXT ; ' STEP 'TRACE !
11
12 : TRACE NEXT> ' DUP ID? NOT ABORT" CAN'T TRACE"
13 DUP <IP ! 'EXIT IP> ! <IP> >NEXT ;
14 : NOTRACE NEXT> ." TRACING OFF" QUIT ;
15 : CONT CON ON 0 ;
Code: Select all
084 # LDA,
Code: Select all
IP # LDA,
TRACE was followed by the name of a word to trace but did not initiate a trace, tracing occurred when IP was between two addresses stored in <IP and IP> so the word was traced whenever it was executed until tracing was turned off.
Blazin' Forth used ID? to determine if a word was one that could be traced. It used 'EXIT to find where the word to be traced ended. Since my decompiler does a better job at determining where a word ends and low level code in the trace range is harmless, I put TRACE in its own block and modified the load screen slightly:
Code: Select all
SCR# 1
0: ( BLAZIN' FORTH 85 SYSTEM LOADER )
1: VIEW OFF
2: DECIMAL
3: CR 13 LOAD
4: CR 15 22 THRU .// UTILITIES
5: " SAD" FIND NIP 9 AND 23 LINELOAD
6:
7: CR 50 57 THRU .// STRINGS
8: CR 58 70 THRU .// SID SUPPORT
9: CR 71 104 THRU .// VIC SUPPORT
10:
11: VIEW ON .( LOCATE ENABLED) CR
SCR# 23
0: // TRACE
1: DECIMAL
2: : TRACE
3: NEXT> ' DUP ID? NOT
4: ABORT" CAN'T TRACE"
5: DUP <IP ! 'EXIT IP> !
6: <IP> >NEXT ;
7: ;S
8: // IF THE DECOMPILER IS AVAILABLE
9: // HERE IS A BETTER TRACE
10: : TRACE
11: NEXT> SAD OFF SEE
12: SAD @ ?DUP 0=
13: ABORT" CAN'T TRACE"
14: 2- <IP ! EAD @ IP> !
15: <IP> >NEXT ;
SAD is a variable that holds the starting address of the latest decompiled word ( the address of its parameter field or body). EAD holds the ending address, or rather the address just past the end of the latest decompiled word.
Code: Select all
EAD @ SAD @ - .
Oh and where there is a // , just think backslash ( \ ). The Commodore 64 has no backslash key.
[Edit: Fixed the source code. This source is from a print dump and the print dump functionality does not support the Commodore 64's quote mode. Where the source shows {CONTROL P} , press the C64's control key and the P key. Where it shows {RUN/STOP} , press the C64's run/stop key.]