CamelForth (1995) van Bradford J. Rodriguez stond aan de wieg van MaisForth an507 hoewel dat nu nauwelijks nog te merken is.
De metacompiler is volledig nieuw en lijkt in niets op die van CamelForth.
De targetcode is ingrijpend veranderd. De keuze van de Forthregisters is wel gehandhaafd. Af en toe kunt u nog assembler code uit CamelForth tegenkomen, ik heb ernaar gestreefd om die steeds te markeren met BJR.
De assembler notatie is vernieuwd.
MaisForth an507 kan nog fouten bevatten. Neem contact op met ons als u vragen of opmerkingen over MaisForth an507 heeft. We zijn te bereiken via de rubriek "Mail ons" op de website van de HCC Forth-gg (http://www.forth.hccnet.nl).
"an507versies.txt" | Overzicht van veranderingen |
"an507extra-nl.html" | Uitleg bij de niet-standaard woorden |
"assembler.html" | Overzicht van de 6809 assembler notatie |
"an507.bin" | ROM image (C000-FFFF) van de MaisForth |
"meta507.f" | Metacompiler |
"targ507.f" | Target code |
"cras507.f" | Cross assembler, door meta507.f te laden |
MaisForth an507 is een 6809 Forth voor het "maiskastje". De woorden die de hardware aanspreken zijn:
KEY? ( -- vlag ) KEY ( -- char ) EMIT? ( -- vlag ) EMIT ( char -- ) !USART ( baudfactor -- )
Het interne werkgebied van Forth is 000-2FF.
000-07F Dictionary draden, Users, Find Stack 080-0FF Terminal Input Buffer 100-17F Data Stack, dalend 180-1FF Return Stack, dalend 200-27F Circulaire Buffer voor o.a. strings (tijdelijk!) 280-2FF Compiler Stack, dalendBij de koude start wordt de beschikbare hoeveelheid RAM vastgesteld (zie HIMEM) en op de terminal gemeld.
Raadpleeg de file "an507extra-nl.html" voor de niet-standaard Forth woorden in deze tekst.
De standaard Forth woorden in FORTH en ONLY worden bekend verondersteld.
De ruim 80 niet-standaard woorden van het EXTRA en ONLY vocabulary worden beschreven in de file "an507extra-nl.html".
Interne hulpwoordjes, die voor de gemiddelde programmeur niet van belang zullen zijn, staan in het INSIDE vocabulary. Wie daar meer over wil weten, moet de target code in "targ507.f" zelf bestuderen.
Hoe maak je een nieuwe ROM image bijv. na veranderingen in de target?
De decompiler doet niets anders dan kijken of er op een adres een woord gecompileerd staat. Zo ja, dan drukt hij dat af.
Als bijv. op D000 en op D001 beide een gecompileerd woord lijkt te staan, laat SEE beide zien, hoewel minstens een van beide een toevalstreffer moet zijn. In zo'n geval worden de namen niet recht onder elkaar afgedrukt. De lezer moet zelf de juiste lezing kiezen.
De manier om snel de decompiler te leren lezen is: maak zelf een paar kleine woordjes en laat er SEE op los.
>
Alle woorden die een inline gecompileerd argument verwachten, eindigen
op () als het om een cel gaat, bijv. IF() GOTO() () op (C) als het om een byte gaat, bijv. (C) op (S) als het om een string gaat, bijv. ."(S)Dit is handig bij het decompileren (SEE). De decompiler laat namelijk zien wat er in het geheugen staat en niet met welke programmatekst dat tot stand gekomen is.
Voorbeelden:
Het getal 1000 wordt gecompileerd als () plus een cel met 1000 erin.
Het getal 1 wordt gecompileerd als (C) plus een byte met 1 erin.
." Hallo!" compileert ."(S) plus counted string "Hallo!".
AHEAD compileert GOTO() plus een cel met het doeladres.
enz.
>
Na TO() +TO() en INCR() volgt het data-adres van een Value. Dat kan een gewone Value zijn of een indirecte ROM Value.
SEE ALLOT levert bijvoorbeeld op:
+TO() 0049 EXITVolledige lijst van RAM adressen van indirecte ROM values:
0023 TOPVOC 0025 TOPMSG 0027 TOPPFX 0029 TOPNFA 002B HLD 002D CONTEXT 002F CS# 0031 MSG#-2 0033 MODE 0035 SECTION 0037 #TIMES 0039 #IB 003B IB 003D THERE 003F HOR 0041 VER 0043 HIMEM 0045 OK 0047 DOT? 0049 HEREDeze ROM values gedragen zich voor de programmeur als constanten. Het systeem kan hun waarde wijzigen, de programmeur kan dat alleen indirect.
De metacompiler zou moeten werken op iedere standaard 32-bits Forth. (Ik heb Win32forth gebruikt.)
Als het metacompileren begint is de metacompiler af, daar komt dus niets meer bij. Daarom kan de target image er gewoon achter komen te staan. Voor de overzichtelijkheid laat ik de target image beginnen op het eerst beschikbare adres dat in hex op 000 eindigt. De HERE tijdens het metacompileren is de gewone HERE van de host Forth.
De metacompiler is nog wat rommelig en niet al te uitvoerig gedocumenteerd. Hier volgt een oriënterende rondleiding met enige hints:
Tekst tussen <---- en ----> wordt door Forth overgeslagen.
>
De metacompiler heeft zijn eigen QUERY-INTERPRET lus die gestart wordt met :::MAIS:::
Hij wordt verlaten met ;;;MAIS;;; of als er een fout optreedt.
Bestudeer allereerst het woord METACOMPILING dat de kern van :::MAIS::: is.
>
Door TRACE en NOTRACE om een stuk programmatekst in de target code te zetten, is tot in detail te volgen wat daar bij het metacompileren gebeurt. (spatiebalk: wacht/doorgaan)
>
Alle woorden in de target code die bij het metacompileren tot uitvoering komen, staan in het META vocabulary. Dat zijn de echte metacompiler woorden. Om interactief tijdens het metacompileren een DROP uit te kunnen voeren moet het woord DROP dus expliciet in META opgenomen zijn. Zie META-WORDS gevolgd door de woordenlijst, bijna aan het eind van "meta507.f".
>
Alle woorden die bij het metacompileren zullen worden gecompileerd, worden ter plekke opgezocht in de target-image voorzover die tot dan toe opgebouwd is. Bestaat het woord nog niet, dan volgt onherroepelijk een foutmelding.
Deze metacompiler kent geen voorwaartse referenties. De code moet dus in de natuurlijke Forth volgorde staan. Bekijk de defining words om te zien hoe het daarbij opgelost is:
Hun DOES-deel wordt zelfstandig gedefinieerd, los van het CREATE-deel.
DOER: ccc high level Forth code ; DOERCODE ccc assembler code NEXT END-CODEzijn functioneel gelijk aan
: ccc DOES> high level Forth code ; : ccc ;CODE assembler code NEXT END-CODE
voorbeeld met CREATE
\ in target: DOERCODE DOCREATE REG X PULS REG D PSHS X D TFR NEXT END-CODE \ in metacompiler: : xCREATE (MET-DOER zorgt ervoor dat later runtime de Doer DOCREATE opgezocht en in het cfa gezet wordt.-- ) xHEADER MET-DOER DOCREATE ;
Zo ook KOMPILE dat er voor zorgt dat later runtime het te compileren woord opgezocht en gecompileerd wordt, bijv in:
: xAHEAD ( -- AHEADa 11 ) KOMPILE GOTO() HERE 0 x, HX 11 ;
Met deze late bindingen zijn we in princiepe van de voorwaartse referenties af.
>
De x-woorden
Woorden in de metacompiler beginnen vaak met een x (x: x; xIF enz.) Zij worden later en masse zonder die x in het META vocabulary herdefinieerd. Deze wat omslachtige werkwijze maakt het voor de lezer veel gemakkelijker om te metacompiler te doorgronden.
Zo kennen de immediate woorden vier varianten, bijv. de punt-komma:
(an)