Page 2 of 3
Re: Assembler with structured conditionals
Posted: Thu Dec 06, 2018 1:41 am
by Dr Jefyll
[...] Self Modifying Code (perhaps too broad a title
Sorry about that, I kinda got sidetracked on that one. The disscussion digressed to a discussion on fixing that ugly hand calculated offset in my example SMC.
Oops. And the digression was caused by me.

FWIW, my excuse is that Self Modifying Code has gotten a lot of bad PR, and I feel the best way to overcome that is to show SMC being used in a clean and tidy way. When your example of SMC also happened to include hand calculated offsets I felt compelled to speak up, because the two do NOT go hand in hand.
[...] I daresay there's no perfect solution, but perhaps it'd be best if the error-check codes (but not the addresses) got pushed & popped from their own separate stack.
That's why I've got CS-DUP CS-DROP CS-SWAP and CS-ROT which also work with high level Forth conditionals. I just treat the address and security number as a single unit.
Yes, you have a solution of sorts but it's not one I like much, and I thought perhaps I could do a little better.
Unfortunately, after refreshing myself on the subject (it's been years since I involved myself with this) I have no dramatic improvement to offer. In my notes I did find the following...
Code: Select all
: IF[WITHIN], ( like IF, but used within an assembler structured conditional )
>R >R [COMPILE] IF,
R> R> ; IMMEDIATE
... but this is less flexible than what you're doing, and certainly no prettier.
cheers,
Jeff
ps: returning to the subject of clean and tidy coding, don't you think you should used a named constant in cases like this?
Re: Assembler with structured conditionals
Posted: Thu Dec 06, 2018 1:45 am
by GARTHWILSON
If I implement the structured conditionals, I might do something like:
Code: Select all
HEX
CODE ACLOSE ( -- ) \ Close all open files.
STX_ZP XSAVE C,
BEGIN,
LDY_ZP 98 C, \ (but give a name, as Jeff suggests)
0<>
WHILE,
LDA_ABS 258 C, \ LAST OPENED
JSR FFC3 , \ CLOSE
REPEAT,
LDX_ZP XSAVE C,
JMP NEXT ,
(My Forth assembler requires comma'ing in the operands.) One thing I would definitely do is put the test condition on the line before the WHILE, so the first character of WHILE, can be vertically aligned with that of BEGIN, and REPEAT,. Same thing with an IF, for example. It's just (very strong) personal preference. That's a nice thing about Forth though, and maybe one reason that managers sometimes aren't too fond of Forth. It allows us free thinkers to do things our own way, independently of how others do it. It's also one reason Forth will never die. Since we can get under the hood and modify or extend even the very compiler and assembler, it won't affect us much if commercial support were ever to disappear.
Edit: In my assembler macros for the normal (non-Forth) assembler, I put the condition with the IF, WHILE, etc., like IF_EQ, WHILE_NEG, etc..
Re: Assembler with structured conditionals
Posted: Fri Dec 07, 2018 9:10 pm
by JimBoyd
and, yes, you should include a copy of the license in the ZIP file.
You are correct, I should have. I wasn't thinking about it but, those who downloaded the first ZIP file are limited to 'fair use' of copyright law. The first one has been replaced with a ZIP file containing the assembler
and a copy of the LGPL version 2.1.
Re: Assembler with structured conditionals
Posted: Fri Dec 07, 2018 9:17 pm
by JimBoyd
ps: returning to the subject of clean and tidy coding, don't you think you should used a named constant in cases like this?
Well, it's one of those locations used by the C64 kernel and I didn't want to add a constant to my Forth kernel that would only be used once.
I suppose I could add a constant that exists on the host but not the target. Since it's only used once in the entire Forth kernel, would a comment do?
The Commodore 64 Programmers Reference Guide calls location $98
LDTND number of open files/index to file table, and locations $259-$262
LAT Kernel table: active logical file numbers.
Re: Assembler with structured conditionals
Posted: Fri Dec 07, 2018 9:29 pm
by JimBoyd
One thing I would definitely do is put the test condition on the line before the WHILE, so the first character of WHILE, can be vertically aligned with that of BEGIN, and REPEAT,. Same thing with an IF, for example. It's just (very strong) personal preference.
Since the conditional
has to be there to determine which branch opcode is compiled by
WHILE, , and
IF, , I tend to see the conditional as part of the
WHILE,. That's why I put it on the same line.
If I understand your assembly notation, shouldn't this:
be this:
or something similar?
Re: Assembler with structured conditionals
Posted: Fri Dec 07, 2018 10:45 pm
by GARTHWILSON
One thing I would definitely do is put the test condition on the line before the WHILE, so the first character of WHILE, can be vertically aligned with that of BEGIN, and REPEAT,. Same thing with an IF, for example. It's just (very strong) personal preference.
Since the conditional
has to be there to determine which branch opcode is compiled by
WHILE, , and
IF, , I tend to see the conditional as part of the
WHILE,. That's why I put it on the same line.
I always have the test condition before the conditional word. So instead of something like
Code: Select all
FOOBAR @ 0= IF
<do stuff>
<do stuff>
THEN
I always do
Code: Select all
FOOBAR @ 0= \ Is it zero?
IF <do stuff> \ If so, do this stuff.
<do stuff>
THEN
An exception would be when it works well to have all the structure words at the end of the line, something like
Code: Select all
<bla> <bla> <bla> <condition?> IF
<do_this> <do_that> <do_the_other> ELSE
<otherwise_do_this_other_stuff> THEN
Also for looping controls:
Code: Select all
<limit> <index>
DO <do_stuff>
<do_stuff>
LOOP
In any case, I don't ever want the structure words to be at a diagonal from each other. Always either vertical or horizontal for visual factoring. Always. (Again, personal preference.)
If I understand your assembly notation, shouldn't this:
be this:
or something similar?
Yes, you're right. LDA,Y. (For ZP, there's LDA_ZP,Y.)
Re: Assembler with structured conditionals
Posted: Sat Dec 08, 2018 9:19 pm
by JimBoyd
In any case, I don't ever want the structure words to be at a diagonal from each other. Always either vertical or horizontal for visual factoring. Always. (Again, personal preference.)
That doesn't really bother me, as long as the indentation correctly shows the control flow nesting.
Re: Assembler with structured conditionals
Posted: Sun Dec 16, 2018 7:40 pm
by JimBoyd
When I was developing my metacompiler, I added a feature that I never actually needed ( it was easy to add ). The metacompiler has a word SUB which is used to write subroutines a code word might need.
I really shouldn't post when I'm tired. I
do use
SUB in my kernel source. Before that, I used
LABEL ( makes a metacompiler label ) and invoked the assembler directly.
SUB was so much easier.
If it were just a stand alone program that takes a text file and spits out an assembled binary, then it's simply a different syntax rather than an entirely different tool chain.
I made some improvements to my metacompiler. With
INCLUDE , it can take this sequential file from a C64 disk and compile it with no Forth, no headers, just the assembly code. It then prompts for a filename and spits out a binary to the disk. The demo does what some programs meant to be called from
BASIC does, SYS 49152 does one thing and SYS 49155 does another.
Code: Select all
HEX START
C000 ORIGIN
SUB TWIN.DEMOS
AHEAD,
0 # LDA, TAX,
10 # LDY,
BEGIN,
D020 STA, CLC, 1 # ADC,
CS-DUP 0= UNTIL, // CONTINUE
INX,
CS-DUP 0= UNTIL, // CONTINUE
DEY,
0= UNTIL,
RTS,
THEN,
0 # LDY, FC STY,
7 # LDA, FD STA,
4 # LDA, FE STA,
E8 # LDY,
BEGIN,
DEY,
FC )Y LDA, 80 # EOR,
FC )Y STA,
0 # CPY,
CS-DUP 0= UNTIL, // CONTINUE
FD DEC, FE DEC,
0= UNTIL,
RTS,
END-CODE
TSAVE
Re: Assembler with structured conditionals
Posted: Fri Jan 04, 2019 12:21 am
by JimBoyd
Changes to the Fleet Forth kernel necessitated changes to the definitions of
CODE ,
;CODE , and
END-CODE .
Here is the new source
Code: Select all
SCR# F
// SUBR CODE ;CODE END-CODE
HEX FORTH DEFINITIONS
: SUBR ( -- ADR TRUE )
CREATE LATEST TRUE
OVER TSB
[ ASSEMBLER ] ASSEMBLER MEM ;
: CODE ( -- ADR TRUE )
SUBR HERE DUP 2- ! ;
: ;CODE ( TRUE -- TRUE )
DUP TRUE ?PAIRS
COMPILE DOES [COMPILE] [
[ ASSEMBLER ] ASSEMBLER
MEM ; IMMEDIATE
: END-CODE ( ADR TRUE -- )
CURRENT @ CONTEXT !
TRUE ?PAIRS TSB ;
As for
SUBR , well, some Forth's have code like this:
Code: Select all
CREATE SOMENAME <setup assembler>
<assembly code>
to create subroutines.
SOMENAME returns its address and is used like this:
or, depending on the assembler, like this:
SUBR creates a subroutine without the need to explicitly setup the assembler.
All such subroutines are concluded with
END-CODE .
Re: Assembler with structured conditionals
Posted: Wed Jan 09, 2019 9:48 pm
by JimBoyd
returning to the subject of clean and tidy coding, don't you think you should used a named constant in cases like this?
Since defining a constant in the target source builds that constant in the target, I added
DEFINE to my metacompiler. It builds a constant on the host so no memory is used for it on the target.
Code: Select all
SCR# 2
// META CONSTANTS
HEX
98 DEFINE #FILES
259 DEFINE LF.TABLE
FFC3 DEFINE FCLOSE
// CLOSE ALL OPEN FILES
CODE ACLOSE ( -- )
XSAVE STX,
BEGIN,
#FILES LDY,
0= NOT WHILE,
LF.TABLE 1- ,Y LDA, // LAST OPENED
FCLOSE JSR, // CLOSE
REPEAT,
XSAVE LDX,
NEXT JMP, END-CODE
P.S. It may take a while to cleanup all of Fleet Forth's source code, but the improved readability will be worth it.
Cheers,
Jim
Re: Assembler with structured conditionals
Posted: Wed Jan 09, 2019 9:59 pm
by JimBoyd
Code: Select all
HEX START
C000 ORIGIN
SUB TWIN.DEMOS
.
.
.
I renamed the metacompiler's
SUB to
SUBR for consistency with the host assembler. Why
SUBR over
SUB ? To avoid confusion if this Forth assembler macro is ever defined:
The metacompiler's
SUBR creates a label on the host ( in the shadow vocabulary ) that returns the virtual address of the subroutine on the target, but no header or CFA is compiled on the target, only the subroutine.
Re: Assembler with structured conditionals
Posted: Thu Jan 10, 2019 7:59 am
by barrym95838
(For ZP, there's LDA_ZP,Y.)
And what op-code do you comma in for that one?

Re: Assembler with structured conditionals
Posted: Thu Jan 10, 2019 10:35 am
by GARTHWILSON
(For ZP, there's LDA_ZP,Y.)
And what op-code do you comma in for that one?

Yeah, messed up again. It happens too much. Thanks for straightening me out. Too much hurrying, and it's counterproductive. I'd get more done if I would just make better use of time (which is sort of a New Year's resolution for 2019) instead of trying to hurry through things.
In any case, the op codes are never comma'ed in, but are laid down by the words like LDA,Y. (Since there's no LDA ZP,Y, there's no need to put the "ABS" in. I had to check.) The word LDA,Y just has the header, plus the CFA pointing to comp_op ("compile op code," a runtime routine), and the parameter field of only one byte (not two), that of the op code. The assembly-language source code has two macro invocations and looks like this:
Code: Select all
HEADER "LDA,Y", NOT_IMMEDIATE
OP_CODE $B9
The operand (but not the op code) must be comma'ed in.
Now I'm in a hurry to get to bed.
Important meeting later today.
Re: Assembler with structured conditionals
Posted: Thu Jan 10, 2019 6:18 pm
by barrym95838
I'd get more done if I would just make better use of time ...
[OT] Amen. I have a gigantic pile of "stuff" that needs my attention. I often get a feeling of being lost under the weight of it all, and I don't even have the fortitude to at least nibble away at it, which would be better than trying to pretend that it's not there ... [sigh]
Re: Assembler with structured conditionals
Posted: Mon Apr 29, 2019 9:34 pm
by JimBoyd
I didn't mention it ( although it's in the source code ) but my assembler has the word
BRAN, which takes an address and a condition code from the stack. As an example of how it works, here is the source for Fleet Forth's
S>D
Code: Select all
CODE S>D ( N -- D )
1 ,X LDA,
PUSH.TRUE 0< BRAN, // COMPILES BMI
PUSH.FALSE 0< NOT BRAN, // COMPILES BPL
END-CODE
PUSH.TRUE and PUSH.FALSE are metacompiler labels for the locations where a true and a false respectively are pushed onto the data stack.
TRUE and
FALSE have no bodies. Their code field's point to these locations so
S>D could have been written as
Code: Select all
CODE S>D ( N -- D )
1 ,X LDA,
' TRUE @ 0< BRAN, // COMPILES BMI
' FALSE @ 0< NOT BRAN, // COMPILES BPL
END-CODE
BRAN, and all the words that compile or resolve a branch perform distance checking and abort if the distance is too far. I was motivated to add this when I was working on that word that takes a 64 bit unsigned number and returns the square root as a 32 bit result.