The real power of [ and ]
The real power of [ and ]
Currently I am writing some ProDOS commands for ProForth on the Apple II.
I don't have a built in assembler in Forth, mostly because I have trouble grasping the RPN of assembly. But that's ok. I found a really cool way to add assembly into my words. I have a pretty good assembler outside of Forth, so the question is how to get the resulting code into Forth without having to type the code in.
I created a Forth word call BLOAD. Which can load a binary file to a buffer. All we have to do is designate where that buffer is.
In ProForth one creates a code word like this:
: TEST ;CODE [ HEX 20 C, FC58 , A0 , ... etc ] ;
As you can see, it takes a bit of typing to type in the code by hand. Then it finally dawned on me that since all code between [ and ] are immediately executed I should also be able to use disk commands.
The final result is:
: TEST ;CODE [ HERE BLOAD BINARY.PRGRM ] ;
HERE designates the address after the word TEST and the binary program is loaded right there.
No more typing in lists of hex digits followed by commas.
Remember that all words between the brackets are executed immediately (just as if typing at the OK prompt) and does not get compiled into the word definition.
I don't have a built in assembler in Forth, mostly because I have trouble grasping the RPN of assembly. But that's ok. I found a really cool way to add assembly into my words. I have a pretty good assembler outside of Forth, so the question is how to get the resulting code into Forth without having to type the code in.
I created a Forth word call BLOAD. Which can load a binary file to a buffer. All we have to do is designate where that buffer is.
In ProForth one creates a code word like this:
: TEST ;CODE [ HEX 20 C, FC58 , A0 , ... etc ] ;
As you can see, it takes a bit of typing to type in the code by hand. Then it finally dawned on me that since all code between [ and ] are immediately executed I should also be able to use disk commands.
The final result is:
: TEST ;CODE [ HERE BLOAD BINARY.PRGRM ] ;
HERE designates the address after the word TEST and the binary program is loaded right there.
No more typing in lists of hex digits followed by commas.
Remember that all words between the brackets are executed immediately (just as if typing at the OK prompt) and does not get compiled into the word definition.
Re: The real power of [ and ]
IamRob wrote:
Currently I am writing some ProDOS commands for ProForth on the Apple II.
Code: Select all
S" AFILE.FS" INCLUDEDCode: Select all
INCLUDE AFILE.FSThe RPN assembly grows on you if you start using it, but you do have to force yourself to use it and double-check the opcodes (and the stack to make sure there aren't left-overs) the first few times. For simple code, I totally just compile in the opcodes like you've shown.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: The real power of [ and ]
IamRob wrote:
I don't have a built in assembler in Forth, mostly because I have trouble grasping the RPN of assembly.
Code: Select all
: ADC# 69 C, ; : AND# 29 C, ; : ASL_A 0A C, ;
: ADC_ABS 6D C, ; : AND_ABS 2D C, ; : ASL_ABS 0E C, ;
: ADC_ZP 65 C, ; : AND_ZP 25 C, ; : ASL_ZP 06 C, ;
: ADC(ZP) 72 C, ; : AND(ZP) 32 C, ; : ASL,X 1E C, ;
: ADC,X 7D C, ; : AND,X 3D C, ; : ASL_ZP,X 16 C, ;
: ADC,Y 79 C, ; : AND,Y 39 C, ;
: ADC_ZP,X 75 C, ; : AND_ZP,X 35 C, ;
: ADC(ZP,X) 61 C, ; : AND(ZP,X) 21 C, ;
: ADC(ZP),Y 71 C, ; : AND(ZP),Y 31 C, ;
<etc.>which shows most of the '02 addressing modes. So you just put the mnemonic down followed by the operand (if any) with a comma (or C-comma, or in the case of the '816, a "3C," also, for the few times you need a three-byte operand). There is no parsing, even though the mnemonic precedes the operand. It is up to you to specify the addressing mode along with the mnemonic, and to use the right word to compile the operand (whether comma or C-comma). So you'll do for example,
Code: Select all
LDA_ABS FOOBAR ,Later I wrote a word "comp_op", laid down by macro OP_CODE, to shorten the op-code words by five bytes each (this is from the Forth assembly source-code, not high-level Forth):
Code: Select all
HEADER "ADC#", NOT_IMMEDIATE
OP_CODE $69so that after the header (formed by the HEADER macro), there are only the two bytes of CFA (pointing to comp_op) laid down in the code field by the OP_CODE macro, followed by the one byte of op code which the macro also lays down, and nothing more, ie, no nest, unnest, or lit, and only one byte (not two) for the op code number itself. comp_op also takes care of the semicolon's job, so it's all there, without adding more bytes.
For the places in the kernel where you'd want to jump to in various primitives you would write, I have constants like this:
Code: Select all
8F34 CONSTANT POP 8F74 CONSTANT SET-TRUE
8F32 CONSTANT POP2 8F86 CONSTANT SET-FALSE
8F7E CONSTANT POP2-FALSE 8F38 CONSTANT CPUSH
8F6C CONSTANT POP2-TRUE 8F3B CONSTANT PUSH
8F30 CONSTANT POP3 8F84 CONSTANT PUSH-FALSE
8F6A CONSTANT POP3-TRUE 8F72 CONSTANT PUSH-TRUE
8F7C CONSTANT POP3-FALSE 8F3D CONSTANT PUT
8F6E CONSTANT POP-TRUE 8F42 CONSTANT NEXT
8F80 CONSTANT POP-FALSE 00FD CONSTANT XSAVE
00F0 CONSTANT N C98D CONSTANT setirq
4 CONSTANT tempA FE CONSTANT irq?\Note that no separate assembler vocabulary is needed, because for example assembly's AND will not conflict with Forth's AND because assembly's word always comes with the addressing mode, whether #, _ABS, or whatever, as part of the name.
And, not particularly related to this method, not that being Forth, macro capability is built in, with no extra effort on the part of the person writing the assembler!
There's a little more to it, particularly in the matter of branching and labels, but It'll take me more time to describe that, which I'll do later if you're interested. For now, this should give you the ideas to get started. You assembly source code then won't look so different from how it does for a normal assembler.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: The real power of [ and ]
GARTHWILSON wrote:
Code: Select all
LDA_ABS FOOBAR ,Code: Select all
FOOBAR LDA_ABSWas that a common way to do it and are there any unforeseen pitfalls?
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: The real power of [ and ]
Druzyek wrote:
GARTHWILSON wrote:
Code: Select all
LDA_ABS FOOBAR ,Code: Select all
FOOBAR LDA_ABShttp://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Embedding/Manipulating Assembler in Higher Level Languages
(This post has been moved; see Embedding/Manipulating Assembler in Higher Level Languages.)
Last edited by cjs on Wed Dec 23, 2020 6:07 am, edited 1 time in total.
Curt J. Sampson - github.com/0cjs
Re: The real power of [ and ]
NOOOOOOOOOooooooooo..........!!!!!!!! Every thread I read gets derailed into talking about do things using a Forth assembler.
I was trying to point out that I can load a binary file directly into a word definition, and you guys pick up on that I don't do assembly in Forth. This conversation is getting way off the subject line. :O)
I was hoping to see more examples using the brackets within word definitions.
And although a Forth assembler CAN be done, a Forth assembler just doesn't have the features I need. Like copy/paste, find/replace, insert/delete. And is just counter productive for me at this time.
I was trying to point out that I can load a binary file directly into a word definition, and you guys pick up on that I don't do assembly in Forth. This conversation is getting way off the subject line. :O)
I was hoping to see more examples using the brackets within word definitions.
And although a Forth assembler CAN be done, a Forth assembler just doesn't have the features I need. Like copy/paste, find/replace, insert/delete. And is just counter productive for me at this time.
Re: The real power of [ and ]
Quote:
Is there a place I can follow your progress?
Quote:
I'm currently looking into adding file support into Tali2. I don't have an OS to help get info from disk, so I've written a very basic FAT32 implementation to access the files.
JSR $BF00
HEX command
DW parmtable
The "command" can be anything from creating directories to deleting files to loading/writing blocks to open/load/write files as a whole. Plus a few more commands for other things.
A parameter table is very easy to create. I just use the CONSTANT word definition.
HERE 3 C, 0 , BF70 @ 400 - , 0 C, CONSTANT OPARM
To make a call to the OS then is just:
: OPENFILE OPARM COMMAND OSI ; (OSI being the OS Interpreter)
Quote:
I have support for using a file as a block device (reading and writing data, but I don't have support for writing to the FAT so it can't be resized), but I'd prefer to be able to do something like:or ANS2012 Forth's File-Access extension word INCLUDEBased on some of your other posts, I believe you are doing something similar for ProDOS.
Code: Select all
S" AFILE.FS" INCLUDEDCode: Select all
INCLUDE AFILE.FSQuote:
The RPN assembly grows on you if you start using it, but you do have to force yourself to use it and double-check the opcodes (and the stack to make sure there aren't left-overs) the first few times. For simple code, I totally just compile in the opcodes like you've shown.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: The real power of [ and ]
IamRob wrote:
NOOOOOOOOOooooooooo..........!!!!!!!! Every thread I read gets derailed into talking about do things using a Forth assembler.
I was trying to point out that I can load a binary file directly into a word definition, and you guys pick up on that I don't do assembly in Forth. This conversation is getting way off the subject line. :O)
I was hoping to see more examples using the brackets within word definitions.
And although a Forth assembler CAN be done, a Forth assembler just doesn't have the features I need. Like copy/paste, find/replace, insert/delete. And is just counter productive for me at this time.
I was trying to point out that I can load a binary file directly into a word definition, and you guys pick up on that I don't do assembly in Forth. This conversation is getting way off the subject line. :O)
I was hoping to see more examples using the brackets within word definitions.
And although a Forth assembler CAN be done, a Forth assembler just doesn't have the features I need. Like copy/paste, find/replace, insert/delete. And is just counter productive for me at this time.
A common use for [ and ] in Forth definitions however is to calculate literals during compilation, as in
Code: Select all
[ ISR_LIST 4 + ]LIThttp://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: The real power of [ and ]
IamRob wrote:
NOOOOOOOOOooooooooo..........!!!!!!!! Every thread I read gets derailed into talking about do things using a Forth assembler.
Actually, I take your point, and would prefer a wider view of assembly embedding anyway, so I've copied Garth's post and moved my reply to a new topic: Embedding/Manipulating Assembler in Higher Level Languages.
Curt J. Sampson - github.com/0cjs
Re: The real power of [ and ]
Great point: keep topics on track, and if suggesting alternative approaches, put them in a new thead.
Garth: IamRob is not joking. It's a derail, and it's distressing.
Garth: IamRob is not joking. It's a derail, and it's distressing.
- GARTHWILSON
- Forum Moderator
- Posts: 8775
- Joined: 30 Aug 2002
- Location: Southern California
- Contact:
Re: The real power of [ and ]
BigEd wrote:
Garth: IamRob is not joking. It's a derail, and it's distressing.
As far as a perceived change of subject may go, there have been plenty of times when I thought I needed to solve a particular problem, and started a conversation about it with someone, and they, having experience that's different from mine, point out another way of approaching the goal which makes it so I don't have to solve the problem I thought I did, as it becomes a non-issue. I always welcome those.
http://WilsonMinesCo.com/ lots of 6502 resources
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
The "second front page" is http://wilsonminesco.com/links.html .
What's an additional VIA among friends, anyhow?
Re: The real power of [ and ]
It was my fault. I brought up 2 different subjects in my post, but the one I wanted to concentrate on the most is the one in the subject line. It is not so much a joke as an amusing observation that the Forth Assembler comes into play in every discussion.
Eventually I will program one in just because I like playing with Forth. Garth also brought up a good comment that the functions I need are part of the editor (copy/paste, find/replace, insert/delete) and not the assembler, but the problem becomes when I need to be able to use these functions when using the assembler. Those functions are usually part of the screens editor.
But if I can interact certain functions to work across multiple vocabularies then that might save me some code when not only creating applications like a word processor or spreadsheet, but also be able to use those functions when executing those applications.
Another analogy would be, I would need those functions to create a game, but would not need those functions when running the game, which is why I would not want those functions to be part of the Forth system.
For everything to be usable (Assembler, Editor, Forth system) at the same time, and on top of that try to create an application or game, requires a virtual memory system that allows one to swap memory modules in and out so one always has available memory, or if one wants to use shared resources for both creating and editing an application, and also have the same resources available when running an application if needed.
If all this confuses anyone, it just means I am looking down the road, long term usage, to be able to make efficient use of not only vocabularies but certain modules within a vocabulary. I am looking for a way to use certain functions that can be shared with all the vocabularies without making the functions part of the Forth system or duplicating the functions in each vocabulary.
One way is to have multiple Forth systems. Each Forth would contain different functions depending on whether one is editing/assembling or running programs.
I also like the idea of having an INCLUDE word that can load in module functions that are compiled before compiling the program. As an example, the editor could include functions this way:
INCLUDE COPY/PASTE
INCLUDE FIND/REPLACE
INCLUDE INSERT/DELETE
... remainder of the editor
And then the assembler could use the editor with just one line.
INCLUDE EDITOR
I will use this post to establish a base-line of what I am trying to achieve and will delve more in my next post how I might be able to achieve that with the use of the left and right brackets. Things are still forming in my head, but thanks for some of the ideas mentioned so far.
Eventually I will program one in just because I like playing with Forth. Garth also brought up a good comment that the functions I need are part of the editor (copy/paste, find/replace, insert/delete) and not the assembler, but the problem becomes when I need to be able to use these functions when using the assembler. Those functions are usually part of the screens editor.
But if I can interact certain functions to work across multiple vocabularies then that might save me some code when not only creating applications like a word processor or spreadsheet, but also be able to use those functions when executing those applications.
Another analogy would be, I would need those functions to create a game, but would not need those functions when running the game, which is why I would not want those functions to be part of the Forth system.
For everything to be usable (Assembler, Editor, Forth system) at the same time, and on top of that try to create an application or game, requires a virtual memory system that allows one to swap memory modules in and out so one always has available memory, or if one wants to use shared resources for both creating and editing an application, and also have the same resources available when running an application if needed.
If all this confuses anyone, it just means I am looking down the road, long term usage, to be able to make efficient use of not only vocabularies but certain modules within a vocabulary. I am looking for a way to use certain functions that can be shared with all the vocabularies without making the functions part of the Forth system or duplicating the functions in each vocabulary.
One way is to have multiple Forth systems. Each Forth would contain different functions depending on whether one is editing/assembling or running programs.
I also like the idea of having an INCLUDE word that can load in module functions that are compiled before compiling the program. As an example, the editor could include functions this way:
INCLUDE COPY/PASTE
INCLUDE FIND/REPLACE
INCLUDE INSERT/DELETE
... remainder of the editor
And then the assembler could use the editor with just one line.
INCLUDE EDITOR
I will use this post to establish a base-line of what I am trying to achieve and will delve more in my next post how I might be able to achieve that with the use of the left and right brackets. Things are still forming in my head, but thanks for some of the ideas mentioned so far.
Re: The real power of [ and ]
IamRob wrote:
I created a Forth word call BLOAD. Which can load a binary file to a buffer. All we have to do is designate where that buffer is.
In ProForth one creates a code word like this:
: TEST ;CODE [ HEX 20 C, FC58 , A0 , ... etc ] ;
As you can see, it takes a bit of typing to type in the code by hand. Then it finally dawned on me that since all code between [ and ] are immediately executed I should also be able to use disk commands.
The final result is:
: TEST ;CODE [ HERE BLOAD BINARY.PRGRM ] ;
HERE designates the address after the word TEST and the binary program is loaded right there.
Remember that all words between the brackets are executed immediately (just as if typing at the OK prompt) and does not get compiled into the word definition.
In ProForth one creates a code word like this:
: TEST ;CODE [ HEX 20 C, FC58 , A0 , ... etc ] ;
As you can see, it takes a bit of typing to type in the code by hand. Then it finally dawned on me that since all code between [ and ] are immediately executed I should also be able to use disk commands.
The final result is:
: TEST ;CODE [ HERE BLOAD BINARY.PRGRM ] ;
HERE designates the address after the word TEST and the binary program is loaded right there.
Remember that all words between the brackets are executed immediately (just as if typing at the OK prompt) and does not get compiled into the word definition.
I have looked at ;CODE on three Forth implementations. 64Forth is a superset of FIG Forth for the C64. My Fleet Forth is a Forth-83 Forth for the C64. Gforth is an Ansi Standard Forth. In all three ;CODE compiles a word named (;CODE) on some systems, and DOES on others, and changes state to interpret. When executed, TEST will change the code field of the latest word in the CURRENT vocabulary to point to the code that follows ;CODE. If TEST is the latest word in the CURRENT vocabulary when it is executed, it will change it's own code field so it is no longer a colon definition. it's code field will point to the code following (;CODE) ( or DOES ) in it's body.
I agree that [ and ] are handy, when defining a colon definition. When assembling a code word or the assembly part of a CREATE ;CODE word, the state is interpret so they aren't even needed.
Does ProForth's ;CODE work differently because there is no Forth assembler?
Re: The real power of [ and ]
GARTHWILSON wrote:
You'll always have a column of mnemonics
Really?
Code: Select all
CODE BOUNDS ( N1 N2 -- N1+N2 N1 )
CLC,
0 ,X LDA, 2 ,X ADC, 0 ,X STA,
1 ,X LDA, 3 ,X ADC, 1 ,X STA,
' SWAP @ JMP, END-CODE