6502.org Forum  Projects  Code  Documents  Tools  Forum
It is currently Thu Nov 21, 2024 7:42 pm

All times are UTC




Post new topic Reply to topic  [ 30 posts ]  Go to page 1, 2  Next
Author Message
PostPosted: Tue Dec 22, 2020 5:20 pm 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 22, 2020 6:48 pm 
Offline

Joined: Sun May 13, 2018 5:49 pm
Posts: 255
IamRob wrote:
Currently I am writing some ProDOS commands for ProForth on the Apple II.
Is there a place I can follow your progress? 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. 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:
Code:
S" AFILE.FS" INCLUDED
or ANS2012 Forth's File-Access extension word INCLUDE
Code:
INCLUDE AFILE.FS
Based on some of your other posts, I believe you are doing something similar for ProDOS.

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.


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 22, 2020 10:07 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
IamRob wrote:
I don't have a built in assembler in Forth, mostly because I have trouble grasping the RPN of assembly.
You don't have to. I had to work with RPN assembly briefly around 1990 at work and absolutely hated it. (Nothing against those who like it though.) Years later, it only took me a couple of hours to write my 6502 Forth assembler in its original form (but I did some improvements later, and still have more in mind). The bulk of it, ie, the main stuff, without going into branching for example, was this kind of thing:
Code:
: 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:
        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:
        HEADER "ADC#", NOT_IMMEDIATE
        OP_CODE  $69

so 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:
  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! :D

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?


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 22, 2020 10:21 pm 
Offline
User avatar

Joined: Mon May 12, 2014 6:18 pm
Posts: 365
GARTHWILSON wrote:
Code:
        LDA_ABS  FOOBAR  ,
Interesting. I've never tried but always thought an RPN style assembler would be more like this:
Code:
FOOBAR LDA_ABS
That way the operation can see if FOOBAR fits in one byte and can output the zero page version followed by FOOBAR.

Was that a common way to do it and are there any unforeseen pitfalls?


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 22, 2020 10:38 pm 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
Druzyek wrote:
GARTHWILSON wrote:
Code:
        LDA_ABS  FOOBAR  ,
Interesting. I've never tried but always thought an RPN style assembler would be more like this:
Code:
FOOBAR LDA_ABS
That way the operation can see if FOOBAR fits in one byte and can output the zero page version followed by FOOBAR

Yes; but the point is I don't do assembly language in RPN, except where I need to calculate an operand before comma'ing it in. If you want ZP, you do LDA_ZP. In every case, you know which addressing mode you get, because you specify it. The assembler has less overhead then, as it doesn't have to figure it out or see if you're looking for an addressing mode that doesn't exist. You'll always have a column of mnemonics, and if you put that column way out to the right (for vertical alignment) to accommodate whatever room you might need on the left for the longest calculation of an operand in RPN assembly, it doesn't leave you much room for comments. Indenting for visual factoring of loops, etc. becomes a mess, too. Ditching the RPN solves these problems when doing assembly language.

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Tue Dec 22, 2020 11:13 pm 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
(This post has been moved; see Embedding/Manipulating Assembler in Higher Level Languages.)

_________________
Curt J. Sampson - github.com/0cjs


Last edited by cjs on Wed Dec 23, 2020 6:07 am, edited 1 time in total.

Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 3:11 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 3:39 am 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
Quote:
Is there a place I can follow your progress?

This is as good as any a place to ask questions, or maybe start a new thread directed at disk access.
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.

That is a problem as I rely heavily on the ProDOS OS which differs greatly from an OS that uses FAT32. The structure of a disk-access call for ProDOS is

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:
Code:
S" AFILE.FS" INCLUDED
or ANS2012 Forth's File-Access extension word INCLUDE
Code:
INCLUDE AFILE.FS
Based on some of your other posts, I believe you are doing something similar for ProDOS.

Without access to an OS, it is a little difficult to Read/Write to a file. Even with the command calls I made just above, it still requires knowledge of the Parameter tables for each command and an OS to react on those parameters for file manipulation. Following what I do will only confuse you and lead you astray.
Quote:
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.

It is just too counter productive for me to concentrate on and get used to its structure right now.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 3:55 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
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 about to reply to Curt's last post (I saved my reply in a text file, so I have it all in its original form even though he moved it), but if you like, we can start a new topic on Forth assemblers, or find an old one to augment. Let us know if that's your preference. (I can't tell for sure if you're just joking above, and if you like the path the topic is taking.) Initially I was just replying to what you put in your head post. The copy/paste, find/replace, and insert/delete which you mention here however are functions of the editor, not an assembler.

A common use for [ and ] in Forth definitions however is to calculate literals during compilation, as in
Code:
        [ ISR_LIST 4 + ]LIT
Even if you know what the number will be, doing it this way can make it more clear why a particular literal number is what it is. (The ]LIT is my shortening of ] LITERAL which I was using so often.)

_________________
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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 6:13 am 
Offline
User avatar

Joined: Sat Dec 01, 2018 1:53 pm
Posts: 730
Location: Tokyo, Japan
IamRob wrote:
NOOOOOOOOOooooooooo..........!!!!!!!! Every thread I read gets derailed into talking about do things using a Forth assembler.

I don't see any need to worry; my hope is that we will swiftly move off Forth assemblers and on to Python assemblers. :-)

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


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 9:03 am 
Online
User avatar

Joined: Thu Dec 11, 2008 1:28 pm
Posts: 10985
Location: England
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 10:03 am 
Offline
User avatar

Joined: Fri Aug 30, 2002 1:09 am
Posts: 8543
Location: Southern California
BigEd wrote:
Garth: IamRob is not joking. It's a derail, and it's distressing.

Again, I was replying to something in his head post, starting on his second line, and he appeared to be wishing for a way to add assembly-language code without having to hand-assemble and type the hex code in by hand. I think it was very much on-topic.

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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 2:15 pm 
Offline

Joined: Sun Apr 26, 2020 3:08 am
Posts: 357
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.


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 10:20 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
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.


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?


Top
 Profile  
Reply with quote  
PostPosted: Wed Dec 23, 2020 10:26 pm 
Offline

Joined: Fri May 05, 2017 9:27 pm
Posts: 895
GARTHWILSON wrote:

You'll always have a column of mnemonics



Really?
Code:
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



Top
 Profile  
Reply with quote  
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 30 posts ]  Go to page 1, 2  Next

All times are UTC


Who is online

Users browsing this forum: No registered users and 9 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to: