+Lee Stewart Posted August 7, 2021 Author Share Posted August 7, 2021 10 hours ago, TheBF said: I took a look at the TF loader. Are these object files relocatable? I think I get how Mark's loader works, but I don't understand how it would relocate. (I have some ideas on how to do the loading with my favourite /STRING word.) They are not relocatable. Implementing relocatable code is a good bit more complicated. The only tags implemented are those associated with AORG.................9 DATA.................B BYTE.................B BSS..................B DEF..................6 <checksum>...........7—the checksum itself is ignored <end-of-file text>...: All other tagged words are ignored. ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 7, 2021 Share Posted August 7, 2021 52 minutes ago, Lee Stewart said: They are not relocatable. Implementing relocatable code is a good bit more complicated. The only tags implemented are those associated with AORG.................9 DATA.................B BYTE.................B BSS..................B DEF..................6 <checksum>...........7—the checksum itself is ignored <end-of-file text>...: All other tagged words are ignored. ...lee OK good to know. I started studying this tag meanings in the E/A manual and made a rather large case statement. I will prune it with your information. To further check my assumptions, would a workable strategy be to load the object code into the dictionary and but do some computation on the addresses so they are correct for the location you put them at? The objective would be to allow the Forth system to take code that was assembled for ORG = X but re-jig it so it can load at HERE but re-compute the all the addresses to be HERE relative. It would give Forth the ability to use external code modules. 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 7, 2021 Author Share Posted August 7, 2021 4 hours ago, TheBF said: The objective would be to allow the Forth system to take code that was assembled for ORG = X but re-jig it so it can load at HERE but re-compute the all the addresses to be HERE relative. Your loader would need to be able to understand all instructions with address references—possible, but complicated, with branch statements and statements that use symbolic address references, but I do not think possible with other uses of address labels. The only reason relocatable object code can be managed (and fairly easily, at that) is that the assembler marks all relocatable addresses in the tagged object code with segment addresses and offsets in a linked chain for each unique, relocatable address reference. The loader merely needs to walk each of those chains backwards to replace the segment+offset with the relocated addresses. For REF, prior loading of tagged object code containing the relevant DEF labels (per @Willsy’s loader) would provide the necessary variable definitions with the relevant addresses. Regarding using DEF and REF the way I implied in my earliest post on this topic, DEF would need to define the relevant word to contain the address of the DEFed label rather than the data at that address. I suppose you could flag the loader to manage DEFs as EXECUTE objects (CFAs per @Willsy’s loader) or direct branches (BL, BLWP) that would return where they left. @Willsy’s use of CFAs is probably wisest because it makes the code part of Forth. The only down side to this is that you must have the original ALC, which must be modified to have DEFed labels contain the address of the executable code rather than its own address and the return changed to B *NEXT to get back to the Forth environment. I am sure I have oversimplified (misconstrued?) some of the above, but it could be a fun project. At the very least, these musings provide something of a springboard for going forward, ...lee 1 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 7, 2021 Share Posted August 7, 2021 Yes I came to that conclusion too, that I would need to look ahead at some instructions to find B and BL at a minimum to recompute those addresses. Now that I have slightly better understanding I find myself wondering if the REF/DEF stuff could be done with a vocabulary for all DEFs. When you encounter a 6 tag you: 1. Extract the name from the object code 2. Search the DEF vocabulary for the tag.. 3. If found it means there is already a reference to this code so take the address of that reference and patch it into the address of this new DEF. Not sure I am getting this yet. That logic might be faulty. Alternatively a DEF vocabulary does give you a linked list of all the names that you can walk and do the relocation updates. Maybe? I think it would easier if the TI assembler used more of those tags to give us more context. 1 Quote Link to comment Share on other sites More sharing options...
+FarmerPotato Posted August 7, 2021 Share Posted August 7, 2021 20 hours ago, TheBF said: I took a look at the TF loader. Are these object files relocatable? I think I get how Mark's loader works, but I don't understand how it would relocate. (I have some ideas on how to do the loading with my favourite /STRING word.) Relocatable is the desired feature, yes. For symbols within the object file, there is a tag that means “add the base address to me”. Bonus features: 1. Create constants on the dictionary for each DEF table entry. Then caller says [ THESYM ] BLWP, (I am not familiar with the forth assembler) 2. Resolve REF table entries by looking up constants 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 7, 2021 Share Posted August 7, 2021 I took a run at this with the CAMEL Forth code. Below is the logic used to deal with DEF/REF resolution. I used a vocabulary I init the memory space to >FFFF and I stopped setting the tag 6 entries to zero. I use that >FFFF to determine if the address has been resolved. I guess I assumed that DATA and BYTE statements will not init to >FFFF so that's flawed. The ANS Forth search order control is handy with the PREVIOUS word. This code does what I expect with the test object file. Do you think this close to what is required? : DEF/REF ( addr len -- ) PARSE# >R ( -- addr' len') ( r: -- ref_addr) ALSO REFS DEFINITIONS /TAG 6 CHOP -TRAILING FIND-NAME ( -- nfa) ?DUP IF ( Reference found) R@ @ TRUE = \ fetch the ref_addr to see if UN-resolved IF ( empty reference ) NFA>BODY @ R> ! \ store NEW address ELSE R> DROP DROP THEN ELSE ( new reference) HEADER, COMPILE DOCON R> , \ make a Forth Constant THEN PREVIOUS DEFINITIONS ; It also means I can do this: \ create some external system references ALSO REFS DEFINITIONS HEX 8300 CONSTANT PAD 83E0 CONSTANT GPLWS 8400 CONSTANT SOUND 8800 CONSTANT VDPRD 8802 CONSTANT VDPSTA 8C00 CONSTANT VDPWD 9000 CONSTANT SPCHRD 9400 CONSTANT SPCHWT 9800 CONSTANT GRMRD 9802 CONSTANT GRMRA 9C00 CONSTANT GRMWD 9C02 CONSTANT GRMWA 000E CONSTANT SCAN \ key scan entry 0020 CONSTANT BREAK \ break key sub-routine DEAD CONSTANT KSCAN \ dummies for testing DSK2.TEST-OBJ BEEF CONSTANT VBLANK AABB CONSTANT KSTAT PREVIOUS DEFINITIONS Spoiler .( EA3 object file loader Aug 7 2021 Fox) NEEDS WORDLIST FROM DSK1.WORDLISTS ONLY FORTH ALSO DEFINITIONS NEEDS .S FROM DSK1.TOOLS NEEDS +TO FROM DSK1.VALUES NEEDS CASE FROM DSK1.CASE NEEDS -TRAILING FROM DSK1.TRAILING NEEDS READ-FILE FROM DSK1.ANSFILES NEEDS S= FROM DSK1.COMPARE VOCABULARY REFS FORTH DEFINITIONS DECIMAL 0 VALUE #1 \ a file handle : NFA>BODY ( addr -- addr') NFA>CFA >BODY ; : 2OVER ( a b c d -- a b c d a b) 3 PICK 3 PICK ; : 2NIP ( a b c -- c) NIP NIP ; : FIND-NAME ( addr len -- nfa ) \ nfa is "name field address" CONTEXT @ @ ( -- NFA ) BEGIN DUP WHILE ( tos<>0) DUP 1+ 2OVER S= WHILE ( compare<>0) NFA>LFA @ ( follow link to next name) REPEAT THEN 2NIP ; \ heap memory management : HEAP! ( addr -- ) H ! ; \ set heap pointer : HEAP ( -- addr) H @ ; \ current heap pointer : HALLOT ( n -- ) H +! ; \ move heap pointer : HEAP, ( n -- ) HEAP ! 2 HALLOT ; \ compile n into heap HEX : NEW. 2000 HEAP! HEAP 2000 FF FILL ; \ string utilities : CHOP ( addr len n -- addr' len' addr2 len2 ) >R \ Rpush n 2DUP DROP R@ \ dup $, do left$ 2SWAP \ put original $ on top R> 1- /STRING \ cut remainder string, leave tag at front 2SWAP \ put chopped string (output) on top ; : /TAG ( addr len -- addr' len') 1 /STRING ; \ cut tag character : PARSE# ( addr len -- n ) BASE @ >R HEX /TAG 4 CHOP NUMBER? ABORT" Bad number" R> BASE ! ; : DEF/REF ( addr len -- ) PARSE# >R ( -- addr' len') ( r: -- ref_addr) ALSO REFS DEFINITIONS /TAG 6 CHOP -TRAILING FIND-NAME ( -- nfa) ?DUP IF ( Reference found) R@ @ TRUE = \ fetch the ref_addr to see if UN-resolved IF ( empty reference ) NFA>BODY @ R> ! \ store NEW address ELSE R> DROP DROP THEN ELSE ( new reference) HEADER, COMPILE DOCON R> , \ make a Forth Constant THEN PREVIOUS DEFINITIONS ; VARIABLE PROGLENGTH CREATE PROGNAME 10 ALLOT : PROG-ID ( addr len -- addr len) PARSE# PROGLENGTH ! 8 CHOP PROGNAME PLACE ; : .TOOLVER ( addr len -- addr 0) /TAG 40 CHOP -TRAILING CR TYPE DROP 0 ; : ParseLine ( add len -- ) BEGIN DUP ( len<>0) WHILE OVER C@ ( 1stChar) CASE [CHAR] 0 OF PROG-ID ENDOF [CHAR] 6 OF DEF/REF ENDOF [CHAR] 7 OF DROP 0 ENDOF [CHAR] 9 OF PARSE# HEAP! ENDOF [CHAR] B OF PARSE# HEAP, ENDOF [CHAR] : OF .TOOLVER ENDOF ENDCASE 1 /STRING 0 MAX \ advance to next char REPEAT 2DROP ; : ?PATH ( addr len -- addr len) 2DUP [CHAR] . SCAN NIP 0= ABORT" Path expected" ; DECIMAL : EA3LOAD ( "DSKx.FILE" -- ) ?PATH DV80 R/O OPEN-FILE ?FILERR TO #1 NEW. BEGIN #1 EOF 0= WHILE PAD DUP 80 #1 READ-LINE ( pad len ? ior) ?FILERR DROP ( pad len ) ParseLine REPEAT #1 CLOSE-FILE ABORT" CLOSE error" ; \ create some external system references ALSO REFS DEFINITIONS HEX 8300 CONSTANT PAD 83E0 CONSTANT GPLWS 8400 CONSTANT SOUND 8800 CONSTANT VDPRD 8802 CONSTANT VDPSTA 8C00 CONSTANT VDPWD 9000 CONSTANT SPCHRD 9400 CONSTANT SPCHWT 9800 CONSTANT GRMRD 9802 CONSTANT GRMRA 9C00 CONSTANT GRMWD 9C02 CONSTANT GRMWA 000E CONSTANT SCAN \ key scan entry 0020 CONSTANT BREAK \ break key sub-routine DEAD CONSTANT KSCAN \ dummies for testing DSK2.TEST-OBJ BEEF CONSTANT VBLANK AABB CONSTANT KSTAT PREVIOUS DEFINITIONS .( Usage: S" DSKx.FILENAME" EA3LOAD) 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 7, 2021 Share Posted August 7, 2021 3 minutes ago, FarmerPotato said: Relocatable is the desired feature, yes. For symbols within the object file, there is a tag that means “add the base address to me”. Bonus features: 1. Create constants on the dictionary for each DEF table entry. Then caller says [ THESYM ] BLWP, (I am not familiar with the forth assembler) 2. Resolve REF table entries by looking up constants The version I posted here is maybe close. It does have a lot of what you want. The references are in a separate vocabulary. I need to learn more about that other tag. Is it supported in the Assembler? Can you Assemble your routines into an object file and posted it or PM it to me? Calling is pretty simple if you never want to come back. MYREF @@ B, If they are sub-routines end them with B *R11. Call from FbForth with: ASM: NEWORD MYREF @@ BL, ;ASM 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 8, 2021 Author Share Posted August 8, 2021 1 hour ago, TheBF said: \ create some external system references ALSO REFS DEFINITIONS HEX 8300 CONSTANT PAD 83E0 CONSTANT GPLWS \ ... You should not need to anticipate these references. Simply include them as EQUates and, if they are used, they will appear tagged with ‘6’ at the end of the tagged object file and will be created by your loader’s code. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8, 2021 Share Posted August 8, 2021 17 minutes ago, Lee Stewart said: You should not need to anticipate these references. Simply include them as EQUates and, if they are used, they will appear tagged with ‘6’ at the end of the tagged object file and will be created by your loader’s code. ...lee Ok. So they would come along for the ride if the program uses them. That's easier. If you get a minute, do you think the logic in that DEF/REF word looks correct? I am out of my depth on how these things actually work. Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 8, 2021 Author Share Posted August 8, 2021 2 hours ago, TheBF said: If you get a minute, do you think the logic in that DEF/REF word looks correct? I am out of my depth on how these things actually work. Surely. I am treading water here a bit myself. ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8, 2021 Share Posted August 8, 2021 Ok. We can shuffle along together then. So one thing you could do better than me by far is provide some normal ALC code assembled to obj file. If you already have some code that consists of a few sub-routines we should be able to figure out how well these ideas work to make callable words from normal ALC code. Then whatever we get working we can port to both systems. The code will diverge in file words and dynamic word creation but the other stuff can be quite similar I think. It's always been a weakness of Forth that it doesn't play nice in the sandbox with other languages so this might be a way to fix that. In theory we might even be able to take GCC output, if it can generate TI object code. 2 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 8, 2021 Author Share Posted August 8, 2021 14 hours ago, TheBF said: Ok. We can shuffle along together then. The attached ALC from Thierry Nouspikel’s disassembly of the Editor/Assembler utilities may aid in our effort: EditorAssemblerLoMemUtilities_Nouspikel.a99 I changed all register references from numbers to ‘R’ notation. Hopefully, I got them all without screwing up non-register numbers. The loader starts at A23BA. The tag jump table is near the end at A2662. You probably guessed correctly that the labels are the actual addresses of the assembled code with a prefix of ‘A’. ...lee 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8, 2021 Share Posted August 8, 2021 1 minute ago, Lee Stewart said: The attached ALC from Thierry Nouspikel’s disassembly of the Editor/Assembler utilities may aid in our effort: EditorAssemblerLoMemUtilities_Nouspikel.a99 21.57 kB · 1 download I changed all register references from numbers to ‘R’ notation. Hopefully, I got them all without screwing up non-register numbers. The loader starts at A23BA. The tag jump table is near the end at A2662. You probably guessed correctly that the labels are the actual addresses of the assembled code with a prefix of ‘A’. ...lee Thank you. This will be just what I needed to get some corner cases. I am just writing up a test I did with a tiny program found on the Assembly topic by mathew180. I am making progress. 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8, 2021 Share Posted August 8, 2021 TI 99 Object code load and run from Forth. With @mathew180 's little training program plus a couple of lines of code the loader works. We need AORG >2000 because Forth takes offense if we load code on top of it. And to return to Forth we just B *R10. We can do this because CAMEL99 does not use R0,R1,R2 or R3. * Training program by @mathew180 AORG >2000 DEF START * VDP Memory Map * VDPRD EQU >8800 * VDP read data VDPSTA EQU >8802 * VDP status VDPWD EQU >8C00 * VDP write data VDPWA EQU >8C02 * VDP set read/write address * Workspace WRKSP EQU >8300 * Workspace R0LB EQU WRKSP+1 * R0 low byte reqd for VDP routines * Program execution starts here START LIMI 0 * LWPI WRKSP CLR R0 * Set the VDP address to zero MOVB @R0LB,@VDPWA * Send low byte of VDP RAM write address ORI R0,>4000 * Set read/write bits 14 and 15 to write (01) MOVB R0,@VDPWA * Send high byte of VDP RAM write address LI R1,>2000 * Set high byte to 32 (>20) LI R2,768 * Set every screen tile name to >20 CLS MOVB R1,@VDPWD * Write byte to VDP RAM DEC R2 JNE CLS B *R10 * return to Forth END The DEF START lines creates the Forth word START . It is put into a separate name space called REFS just for assembly language labels. (Maybe that should be called DEFS ?) To run START we wrap in a Forth Code definition: ALSO ASSEMBLER ALSO REFS ( expose the name spaces to Forth) CODE CLEAR START @@ B, ENDCODE EA3LOADER-DEMO.mp4 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8, 2021 Share Posted August 8, 2021 One thing I didn't know. Object files are are DISPLAY FIXED 80 format. Had to change that in the loader code as well. Quote Link to comment Share on other sites More sharing options...
+TheBF Posted August 8, 2021 Share Posted August 8, 2021 Lee, Your code assembled and the loader seems to have loaded it. I looked a the table at the upper end of low ram and it looks correct. I removed the extra logic that I put in yesterday in the DEF/REF word. I will address that when something stops working. So we can do AORG >2000 programs or AORG >E000 for short programs. In we invoke SAMS memory we could put a lot of CODE in low RAM and make the Forth wrapper do the page selection before calling it. Spoiler has the working version which includes the assembler now as well. Spoiler CR .( EA3 object file loader Aug 7 2021 Fox) NEEDS WORDLIST FROM DSK1.WORDLISTS VOCABULARY REFS VOCABULARY ASSEMBLER ONLY FORTH DEFINITIONS NEEDS .S FROM DSK1.TOOLS NEEDS +TO FROM DSK1.VALUES NEEDS CASE FROM DSK1.CASE NEEDS -TRAILING FROM DSK1.TRAILING NEEDS READ-FILE FROM DSK1.ANSFILES NEEDS S= FROM DSK1.COMPARE ALSO ASSEMBLER DEFINITIONS INCLUDE DSK1.ASM9900 ONLY FORTH DEFINITIONS DECIMAL 0 VALUE #1 \ a file handle : NFA>BODY ( addr -- addr') NFA>CFA >BODY ; : 2OVER ( a b c d -- a b c d a b) 3 PICK 3 PICK ; : 2NIP ( a b c -- c) NIP NIP ; : FIND-NAME ( addr len -- nfa ) \ nfa is "name field address" CONTEXT @ @ ( -- NFA ) BEGIN DUP WHILE ( tos<>0) DUP 1+ 2OVER S= WHILE ( compare<>0) NFA>LFA @ ( follow link to next name) REPEAT THEN 2NIP ; \ heap memory management : HEAP! ( addr -- ) H ! ; \ set heap pointer : HEAP ( -- addr) H @ ; \ current heap pointer : HALLOT ( n -- ) H +! ; \ move heap pointer : HEAP, ( n -- ) HEAP ! 2 HALLOT ; \ compile n into heap HEX : NEW. 2000 HEAP! HEAP 2000 FF FILL ; \ string utilities : CHOP ( addr len n -- addr' len' addr2 len2 ) >R \ Rpush n 2DUP DROP R@ \ dup $, do left$ 2SWAP \ put original $ on top R> 1- /STRING \ cut remainder string, leave tag at front 2SWAP \ put chopped string (output) on top ; : /TAG ( addr len -- addr' len') 1 /STRING ; \ cut tag character : PARSE# ( addr len -- n ) BASE @ >R HEX /TAG 4 CHOP NUMBER? ABORT" Bad number" R> BASE ! ; : DEF/REF ( addr len -- ) PARSE# >R ( -- addr' len') ( r: -- ref_addr) REFS DEFINITIONS /TAG 6 CHOP 2DUP CR ." DEF: " TYPE -TRAILING HEADER, COMPILE DOCON R> , \ make a Forth Constant FORTH DEFINITIONS ; VARIABLE PROGLENGTH CREATE PROGNAME 10 ALLOT : PROG-ID ( addr len -- addr len) PARSE# PROGLENGTH ! 8 CHOP PROGNAME PLACE ; : .TOOLVER ( addr len -- addr 0) /TAG 40 CHOP -TRAILING CR TYPE DROP 0 ; : ParseLine ( add len -- ) BEGIN DUP ( len<>0) WHILE OVER C@ ( 1stChar) CASE [CHAR] 0 OF PROG-ID ENDOF [CHAR] 6 OF DEF/REF ENDOF [CHAR] 7 OF DROP 0 ENDOF [CHAR] 9 OF PARSE# HEAP! ENDOF [CHAR] B OF PARSE# HEAP, ENDOF [CHAR] : OF .TOOLVER ENDOF ENDCASE 1 /STRING 0 MAX \ advance to next char REPEAT 2DROP ; : ?PATH ( addr len -- addr len) 2DUP [CHAR] . SCAN NIP 0= ABORT" Path expected" ; DECIMAL : DIS/FIX DISPLAY SEQUENTIAL 80 FIXED ; \ TI ASM object file format : EA3LOAD ( "DSKx.FILE" -- ) ?PATH DIS/FIX R/O OPEN-FILE ?FILERR TO #1 NEW. BEGIN #1 EOF 0= WHILE PAD DUP 80 #1 READ-LINE ( pad len ? ior) ?FILERR DROP ( pad len ) ParseLine REPEAT #1 CLOSE-FILE ABORT" CLOSE error" ; .( Usage: S" DSK?.FILENAME" EA3LOAD) 1 Quote Link to comment Share on other sites More sharing options...
idflyfish Posted August 25, 2021 Share Posted August 25, 2021 Hi Lee, I just received my copy of the fbForth 2.0 Manual and thumbed through it. Fantastic job sir! 1 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted August 26, 2021 Author Share Posted August 26, 2021 13 hours ago, idflyfish said: Hi Lee, I just received my copy of the fbForth 2.0 Manual and thumbed through it. Fantastic job sir! Thank you, kindly. I wondered where you might have gone, but then I saw your signature. ...lee 1 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted November 20, 2021 Author Share Posted November 20, 2021 While attempting an fbForth port of @TheBF’s Camel99 Forth code for installing the KONAMI Game Font, I realized that DATA[ does not handle line comments ( \ ), which probably means that I implemented DATA[ before implementing \ —oh, well. I will implement it in fbForth 2.0:14, but I am not sure that will be anytime soon. Right now we need to stick with only using ( and --> between DATA[ and ]DATA words. ...lee 2 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted November 20, 2021 Share Posted November 20, 2021 50 minutes ago, Lee Stewart said: While attempting an fbForth port of @TheBF’s Camel99 Forth code for installing the KONAMI Game Font, I realized that DATA[ does not handle line comments ( \ ), which probably means that I implemented DATA[ before implementing \ —oh, well. I will implement it in fbForth 2.0:14, but I am not sure that will be anytime soon. Right now we need to stick with only using ( and --> between DATA[ and ]DATA words. ...lee Yes I had a similar issue in early versions so then I kind of cheated by resorting to EVALUATE. Could you make an equivalent with to my code below with: ASCII , WORD INTERPRET HEX : BYTE ( -- ) BEGIN [CHAR] , PARSE-WORD DUP WHILE EVALUATE DUP FF00 AND ABORT" Not a byte" C, REPEAT 2DROP ; : DATA ( -- ) BEGIN [CHAR] , PARSE-WORD DUP WHILE EVALUATE , REPEAT 2DROP ; 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 16, 2021 Author Share Posted December 16, 2021 On 11/20/2021 at 1:41 PM, TheBF said: Yes I had a similar issue in early versions so then I kind of cheated by resorting to EVALUATE. Could you make an equivalent with to my code below with: ASCII , WORD INTERPRET Spoiler HEX : BYTE ( -- ) BEGIN [CHAR] , PARSE-WORD DUP WHILE EVALUATE DUP FF00 AND ABORT" Not a byte" C, REPEAT 2DROP ; : DATA ( -- ) BEGIN [CHAR] , PARSE-WORD DUP WHILE EVALUATE , REPEAT 2DROP ; The thing is, I am using DATA[ to turn INTERPRET around so that it presumes the token is a number first so that I can remove any need for the user’s use of , or C, . DATA[ presumes the token is a number, not an executable word. Of course, I may be missing something. ? ...lee Quote Link to comment Share on other sites More sharing options...
+TheBF Posted December 17, 2021 Share Posted December 17, 2021 1 hour ago, Lee Stewart said: The thing is, I am using DATA[ to turn INTERPRET around so that it presumes the token is a number first so that I can remove any need for the user’s use of , or C, . DATA[ presumes the token is a number, not an executable word. Of course, I may be missing something. ? ...lee Right and that is faster that my method. I was referring to how one might make DATA xxxx,xxxx, word in Fig-Forth. Something like: : DATA ( -- ) BEGIN ASCII , WORD HERE C@ WHILE HERE INTERPRET , REPEAT DROP DROP ; Would that work? Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted December 17, 2021 Author Share Posted December 17, 2021 (edited) On 12/16/2021 at 7:07 PM, TheBF said: Right and that is faster that my method. I was referring to how one might make DATA xxxx,xxxx, word in Fig-Forth. Something like: : DATA ( -- ) BEGIN ASCII , WORD HERE C@ WHILE HERE INTERPRET , REPEAT DROP DROP ; Would that work? I will need to think on it. [EDIT: Still thinking...] ...lee Edited January 1, 2022 by Lee Stewart 1 Quote Link to comment Share on other sites More sharing options...
+Lee Stewart Posted January 1, 2022 Author Share Posted January 1, 2022 (edited) Quote Inline Code Simplified (from @TheBF, CAMEL99 Forth Information goes here, post #1159) I tried this kind of thing a few years ago but it seemed overly complicated. I think this code is better and it is smaller. I also think it is easily applicable to other indirect threaded Forth systems. The big surprise to me was the new way I return to Forth. See ;CODE] It adds only 54 bytes to the system and you could use machine code between [CODE ;CODE] The total overhead for inserting CODE is 4 byte header + 6 byte return= 10 bytes which is about the same size as adding a short word header so not much saving, but sometimes it is clearer to see short code snippets inline. \ INLINEASM.FTH headless code words inside Forth definition DEC 30 2021 FOX \ example below for usage NEEDS .S FROM DSK1.TOOLS NEEDS MOV, FROM DSK1.ASM9900 HERE HEX : [CODE ( -- ) HERE CELL+ , HERE CELL+ , \ create the ITC header for a CODE word POSTPONE [ \ turn off the Forth compiler ; IMMEDIATE : ;CODE] ( -- ) IP HERE 6 + LI, \ (points to Forth after NEXT,) NEXT, \ compile next into headless code word ] \ turn on the Forth compiler ; IMMEDIATE HERE SWAP - SPACE DECIMAL . .( bytes) HEX CR \ example VARIABLE X 2 X ! VARIABLE Y 3 Y ! : TEST ( -- ) [CODE Y @@ X @@ ADD, ;CODE] X @ . ; Below is my implementation for fbForth 2.0, which adds 58 bytes (4 more than for CAMEL99 Forth) to the system: \ INLINEASM.FBF headless code words inside Forth definition 30DEC2021 FOX \ Modified for fbForth 2.0 31DEC2021 LES \ Example below for usage HERE HEX : [CODE ( -- ) HERE 2+ , HERE 2+ , \ create the ITC header for a CODE word [COMPILE] [ \ turn off the Forth compiler [COMPILE] ASSEMBLER \ ASSEMBLER vocabulary ; IMMEDIATE : ;CODE] ASSEMBLER \ following code needs ASSEMBLER vocabulary IP HERE 6 + LI, \ set IP to HERE+6 (points to Forth after NEXT,) NEXT, \ compile "B *NEXT" into headless code word and.. \ ..back to previous vocabulary ] \ turn on the Forth compiler ; HERE SWAP - SPACE DECIMAL . ." bytes" HEX CR \ example 2 VARIABLE X 3 VARIABLE Y : TEST ( -- ) [CODE Y @@ X @@ A, ;CODE] X @ . ; ...lee Edited January 1, 2022 by Lee Stewart Additional info and CORRECTION of [CODE stack effects 1 1 Quote Link to comment Share on other sites More sharing options...
+TheBF Posted January 1, 2022 Share Posted January 1, 2022 I can understand @HOME AUTOMATION 's confusion emoji. This is outside the realm of normal Forth application programming. We are modifying how the compiler works, which is fair game in Forth but it means you must have "carnel knowledge" of the system. Something that helps ALC programmers understand Forth a bit better is the word HERE is much like $ in assembler. However the use of [COMPILE] and IMMEDIATE takes most people a while to wrap their heads around and I still have to do tests to get it right. ? 2 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
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.