Jump to content
IGNORED

TF, camel, FB Forth fun


GDMike
 Share

Recommended Posts

3 hours ago, GDMike said:

 

What I was trying to do was store all characters to some address. So I thought I could get the next available free location from "HERE" and store the data by using @ for pulling the address. So I shouldn't use the "@" at all?

when I did here . I got   -19xxx something  when I used @ I got 8224...

so yeah, I'll pull out the "@" and try again.

ty Lee 

 

If you need a buffer at HERE of, say 30 bytes, you can define a variable and ALLOT 30 bytes after it:

VARIABLE WRDAD 30 ALLOT

That will place WRDAD in the dictionary and move HERE to 30 bytes after it.

 

If you do not want to use dictionary space for that small buffer, you can grab space in low RAM because that is generally free in TurboForth. You just need to keep track of it in your project:

$2200 CONSTANT WRDAD

 

In both of the above definitions for WRDAD , your definitions of REDIT and WRTIT should be

: REDIT 1841 WRDAD 30 VMBR ;
: WRTIT CLS 1841 WRDAD 30 VMBW CR ;

 

...lee

Link to comment
Share on other sites

If it helps...

 

HERE is a function not a variable.

HERE is a function that returns the location of the end of the dictionary.

Where does it get it from?  A variable called the dictionary pointer.

 

This is where writing a Forth system or studying the source code for a system gets you some insights.

Definition of HERE in Camel99 Forth is ridiculously simple. :) 
 

: HERE    ( -- addr)  DP @  ; 

 

Note: I now write HERE as a code word in Camel99 because that speeds up the compiler quit a bit.

 

You can understand why the compiler goes faster because the compiler is using HERE all the time.

Where is new code compiled? Forth says right HERE, at the end of the dictionary. 

Makes a bit more sense?

  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Lee Stewart said:
VARIABLE WRDAD 30 ALLOT

Ok, this is probably what I'm seeking. Is This "storage" for byte value or word value? It was getting late when I tried this early this morning, and printed garbage to the screen.. but maybe I just didn't have it organized like this, I'm looking at the code with one eye, so I can't wait to try again...BUT it's looking like a major change has to happen. And that is the holding and placing row and column to allow me to backspace if I make a typo in the input..I'm not adding any other edit keys, just would like to have backspace..

Well, I wasn't prepared to see it work the way I had it..lol..no confidence at all was lurking around the edges when I was trying to code it, and I fell outta my seat when it worked.lol 

Thx lee

Link to comment
Share on other sites

2 hours ago, TheBF said:

If it helps...

 

HERE is a function not a variable.

HERE is a function that returns the location of the end of the dictionary.

Where does it get it from?  A variable called the dictionary pointer.

 

This is where writing a Forth system or studying the source code for a system gets you some insights.

Definition of HERE in Camel99 Forth is ridiculously simple. :) 
 

: HERE    ( -- addr)  DP @  ; 

 

Note: I now write HERE as a code word in Camel99 because that speeds up the compiler quit a bit.

 

You can understand why the compiler goes faster because the compiler is using HERE all the time.

Where is new code compiled? Forth says right HERE, at the end of the dictionary. 

Makes a bit more sense?

Yes, a bunch of stuff makes sense now, but at the same time, I was trying to use the ALLOT word but I only received garbage on the output...

After Lee said, ",HERE" doesn't work that way with using "@", and as soon as he said that, I said to myself, "it's on the stack"...

Anyway, I will just change some of my method and adjust the code to get proper storage setup.

 

This is what I am like seeing, your explanations here will take me a bit to shrink down and funnel in. Lol...

I appreciate it. It's exactly what I needed to understand. Working with assy and forth at the same time last year didn't work together well and I couldn't concentrate on both at once, now I'm more focused to pick it up better.

 

 

Link to comment
Share on other sites

2 hours ago, GDMike said:

Ok, this is probably what I'm seeking. Is This "storage" for byte value or word value?

 

Not sure what you are asking, but 

30 ALLOT

reserves 30 bytes at HERE by advancing HERE 30 bytes. Putting that code immediately following the definition of the variable WRDAD , makes its parameter field start with the first byte (char?) of the ALLOTed space. [Note: I should point out that VARIABLE (like all words using CREATE to define word headers) insures that the word it creates starts on an even address boundary and that the parameter field also starts on an even address boundary. Similarly, it is a good idea to always ALLOT an even number of bytes. Also, the “storage” is for whatever you want, byte (8-bit) values or cell (16-bit) values, but you had better know what you are doing if you mix them!]

 

...lee

Edited by Lee Stewart
CLARIFICATION
  • Like 1
Link to comment
Share on other sites

Believe me I understand. Forth is a big number of little sub-routines.

It's more like learning a human language than a computer language.

 

Ok. Lesson on ALLOT.

 

: ALLOT  ( n -- )   \ Notice the stack diagram.  It returns nothing. Then what the heck does it do? 

 

So HERE returns the address of the end of the dictionary.  ALLOT just moves it.

 

The definition of ALLOT is just:

: ALLOT  ( n -- )   DP +! ;   

LOL!  

So, if you do 10 ALLOT

then HERE will return an address 10 bytes higher than before. That's ALL that happens. :)

 

  • Like 2
Link to comment
Share on other sites

6 minutes ago, Lee Stewart said:

 

Not sure what you are asking, but 

30 ALLOT

reserves 30 bytes at HERE by advancing HERE 30 bytes. Putting that code immediately following the definition of the variable WRDAD , makes its parameter field start with the first byte (char?) of the ALLOTed space.

 

...lee

Sorry for the duplication.

Lee and I said the same thing different ways.

 

  • Like 2
Link to comment
Share on other sites

2 hours ago, Lee Stewart said:

Not sure what you are asking, but 

30 ALLOT

reserves 30 bytes at HERE by advancing HERE 30 bytes. Putting that code immediately following the definition of the variable WRDAD , makes its parameter field start with the first byte (char?) of the ALLOTed space.

 

I added this note to the above post for clarification: I should point out that VARIABLE (like all words using CREATE to define word headers) insures that the word it creates starts on an even address boundary and that the parameter field also starts on an even address boundary. Similarly, it is a good idea to always ALLOT an even number of bytes.

 

Also, the “storage” is for whatever you want, byte (8-bit) values or cell (16-bit) values, but you had better know what you are doing if you mix them!

 

...lee

  • Like 2
Link to comment
Share on other sites

Just waking up..lol...my one problem, besides others, was I didn't have an idea of where my data was going to be stored. I'm been used to knowing exactly where in assy, but here when I type here . I received 8224 then  assumed my data was going into that ram location.

Ok . wrong..

So I looked at ALLOT and CELLS.

And I thought I could do WRDADR 30 ALLOT.

And then I thought I was reserving 30 bytes for WRDADR, great! So I thought I could do WRDADR @ to get the 1st available byte storage location from there.

 

Next, I saw cmove and ccopy (maybe not correct spelling),and I noticed one was a byte move and the other was for total words, so I Veered away from the word move WORD and both are srcadr count and dstadr, so I learned how to use those.

I'll dig into everything you guys put out there and see what I can correct in the code and I expect to know where my data is pushed to, which is what I'd like to know.

I'll have to redo everything pretty much anyway because I've got to have a way for backspace to operate.

Also, is the classic99 debugger still an option to peek at and when?

Thx for the information...coffee time.

 

Link to comment
Share on other sites

41 minutes ago, GDMike said:

Just waking up..lol...my one problem, besides others, was I didn't have an idea of where my data was going to be stored. I'm been used to knowing exactly where in assy, but here when I type here . I received 8224 then  assumed my data was going into that ram location.

Ok . wrong..

So I looked at ALLOT and CELLS.

And I thought I could do WRDADR 30 ALLOT.

And then I thought I was reserving 30 bytes for WRDADR, great! So I thought I could do WRDADR @ to get the 1st available byte storage location from there.

 

Next, I saw cmove and ccopy (maybe not correct spelling),and I noticed one was a byte move and the other was for total words, so I Veered away from the word move WORD and both are srcadr count and dstadr, so I learned how to use those.

I'll dig into everything you guys put out there and see what I can correct in the code and I expect to know where my data is pushed to, which is what I'd like to know.

I'll have to redo everything pretty much anyway because I've got to have a way for backspace to operate.

Also, is the classic99 debugger still an option to peek at and when?

Thx for the information...coffee time.

 

You know where everything goes in Forth just the same. 

Data goes to an address.  :) 

 

Your confusion is what Lee said. 

 @ is  MOV  

C@ is MOVB

 

Get those right and you can move forward. 

 

Add this word to your project:

 

: BUFFER:   ( n -- )    CREATE     ALLOT ;

 

 

  • Like 2
Link to comment
Share on other sites

20 hours ago, GDMike said:

 

What I was trying to do was store all characters to some address. So I thought I could get the next available free location from "HERE" and store the data by using @ for pulling the address. So I shouldn't use the "@" at all?

when I did here . I got   -19xxx something  when I used @ I got 8224...

so yeah, I'll pull out the "@" and try again.

ty Lee 

 

 

 

If you're trying to store some characters (from the keyboard) to an address in RAM, then the word EXPECT does exactly that. :thumbsup:

 

In TurboForth, using HERE to store data can potentially lead to confusing results. This is because TF itself sometimes uses memory pointed to by HERE as a temporary workspace. For example, IIRC, the upwards screen scroll when you press Enter at the bottom of the screen - it uses HERE as a line buffer when doing the screen scroll. 

 

Yep....

 

; Scroll screen up by one line. Used by EMIT and CR to scroll the screen up if
; necessary (sub-routine, not a FORTH word).
scrlup  mov @noscrl,r8              ; test NOSCROLL
        jeq scrlno                  ; scrolling is supressed
        dec @scrY                   ; clip y coordinate to 23
        mov @here,r8   <----- HERE BE DRAGONS - TURN BACK ALL YE FAINT OF HEART
        ai r8,4
        li r6,23                    ; 23 lines to shift
        clr r0                      ; screen address
sclup_  a @xmax,r0                  ; move down one line
        mov r8,r1                   ; address of buffer to store in
        mov @xmax,r2                ; number of bytes to store in the screen 

 

I've been bitten by that before it. It was a naive design decision on my part. You would have some data stored at HERE, and if the screen scrolled (like when you're working at the command line) your data gets wiped.

 

You can get around it though:

 

: HERE ( -- n ) HERE 80 + ;

 

That should get you out of trouble. TF will use the internal version of HERE, but your code would use this version and store its data out of the way of the scroll buffer.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

19 hours ago, Lee Stewart said:

 

If you need a buffer at HERE of, say 30 bytes, you can define a variable and ALLOT 30 bytes after it:

VARIABLE WRDAD 30 ALLOT

That will place WRDAD in the dictionary and move HERE to 30 bytes after it.

 

 

I think the above is correct practice for FIG Forth systems. However for other systems, I would advocate the use of CREATE:

 

CREATE WRDAD 30 ALLOT

 

If you wanted 30 bytes of alloted space using VARIABLE (in TF) you would do:

 

VARIABLE WRDAD 28 ALLOT

 

Because the variable definition reserves 2 bytes for its own storage. Either approach will work just fine though. 

 

Then, as Lee mentions, since you are reading and writing 8 bit bytes (called characters in Forth parlance) then you need to be using C@ and C!. These work the same as @ and ! but they store 8 bits to a BYTE address, not a word address.

 

@ and ! read and write from/to EVEN address only, and read/write two bytes at a time (16 bits).

c@ and c! read/write from any address, and read/write single bytes (8 bits) at a time.

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

16 hours ago, GDMike said:

I'll review C@ and @ as well tonight. 

Based on your questions, my recommendation is to take a pause on writing a program and spend some time talking to the Forth console. :)

The console is your friend. It never lies.

In most compiled languages you have to guess what your program will do.

(I know nobody thinks they are guessing, but then why are there bugs?) :) 

 

In Forth you test your "guesses" first, then put them in the code when they work correctly.

This is how Chuck intended the language to be used.

Don't guess what the machine will do.  Ask it!

 

Setup:

Load the tools block with DUMP etc.  Learn how to use DUMP.

DUMP the memory at >A000.

DUMP the memory at >0000  etc.

Now you can see inside the machine.

 

Some exercises:

1. Create a variable X.  Put a number in it.  See if the number is really in that variable.

 

2. Create a new variable Q. Put a character in it.  Read the character from the variable.

 

memory

3. Create a chunk of memory 80 bytes long  ( use: create allot  )

    Put the letter A in the first byte. Confirm that it's there ( could use dump ;) )

    Put the letter B in the 2nd byte.  confirm...

    Put the letter Z in 26th byte.      confirm...

    FILL the 80 bytes with character #. confirm they are there

    Erase the 80 bytes ( fill with 0)   confirm. 

 

 

4. Make a word that takes a number and adds it to your memory chunk, giving you the address   chunk+n.

    Use that new word to put a character in memory at chunk+4, chunk+5 etc. 

    Read them back with your new word. 

 

Bonus points:

5. Create a buffer X of 80 bytes and a buffer Y of 80 bytes.

    Fill buffer X with 40 characters of char. $

   somehow "move"  those 40 characters into buffer Y. Dump buffer y to confirm

 

Try these things yourself and then ask away when something doesn't make sense.

 

 

  • Like 2
  • Thanks 1
Link to comment
Share on other sites

On 10/17/2022 at 8:25 AM, TheBF said:

Setup:

Load the tools block with DUMP etc.  Learn how to use DUMP.

DUMP the memory at >A000.

DUMP the memory at >0000  etc.

Now you can see inside the machine.

Yes, and TF has both a DUMP and VDUMP that is pretty neat. Located on the original V:1.2 disk, block #36 and Mark has mafe them pretty simple to use.

 

 

IMG_20221021_190156022.jpg

Edited by GDMike
  • Like 1
Link to comment
Share on other sites

Steps 1,2 and 3 done, but I was trying to push the letter "z" into memory address Axxx + 26 with character 65 + 25.. anyway, I didn't get that one exactly on my first try... haha..

Oops...I didn't send the right screenshot with the "AB" in first word.. sorry.. but it's definitely there.

 

Link to comment
Share on other sites

On 10/17/2022 at 8:25 AM, TheBF said:

Make a word that takes a number and adds it to your memory chunk, giving you the address   chunk+n.

What do you mean here? Do you mean, Make a word any value and then use that number to make the new chunk address?

As in, : W1 4 ;

MWH .C@ W1 + MWH + C!  

Yikes.. I've ruined that one 

Edited by GDMike
Link to comment
Share on other sites

Anyway, I tried repeating steps 1-3 and nothing worked like it did for me earlier..I'd place a value in the first address but it never changed...

I rebooted and got the same thing..BUT I didn't reboot the peb box, and after dumping another address range,(8224), I saw in the far right of the dump, the word CALL CLEAR. This was a word I was experimenting with an hour earlier in forth during my Input routine test Unless that's a TI basic routine area by chance..lol... Clearly suggesting to shut down the peb next time for a longer period if I really need a clean boot..lol

Edited by GDMike
Link to comment
Share on other sites

2 hours ago, GDMike said:

What do you mean here? Do you mean, Make a word any value and then use that number to make the new chunk address?

As in, : W1 4 ;

MWH .C@ W1 + MWH + C!  

Yikes.. I've ruined that one 

My intention was to get you to invent your own character array. :) 

 

So making something like this work.

 

CREATE Q  100 ALLOT

: []Q ( char n -- addr) ... figure this part out ;

 

Then test it with:

ASCII A  0 []Q C!
ASCII B  1 []Q C!
ASCII C  2 []Q C!

0 []Q 8 DUMP 

 

Edited by TheBF
corrected code
  • Like 1
Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...