20apr2006
MaisForth an601 -- Albert Nijhof
juli 2005
(HCC Forth-gg)
  1. Achtergrond

    CamelForth (1995) van Bradford J. Rodriguez stond aan de wieg van MaisForth an601 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 gehandhaafd en heel af en toe kunt u nog CamelForth code tegenkomen (gemarkeerd met BJR).
    De assembler notatie is vernieuwd.

  2. Email

    MaisForth an601 kan nog fouten bevatten. Neem contact op met ons als u vragen of opmerkingen over MaisForth an601 heeft. We zijn te bereiken via de rubriek "Mail ons" op de website van de HCC Forth-gg.

  3. Files

    an601-leesmij.html Deze file
    an601-readme.html idem, Engelse versie
     
    an601extra-nl.html  Uitleg bij de niet-standaard woorden
    an601extra-gb.html  idem, Engelse versie
     
    an601assembler.html Over 6809 assembler notatie
    an601color.html Target code in kleur
    an601.bin ROM image (C000-FFFF) van de MaisForth
     
    meta601.f Metacompiler code
    cras601.f Cross assembler code (onderdeel van metacompiler)
    targ601.f Target code

  4. Hardware

    MaisForth an601 is een 6809 Forth voor het "maiskastje". De woorden die de hardware aanspreken zijn:

       KEY? ( -- vlag )
       KEY ( -- char )
       EMIT? ( -- vlag )
       EMIT ( char -- )
       !USART ( baudfactor -- )
    
  5. MaisForth an601

    Raadpleeg file an601extra-nl.html voor de niet-standaard Forth woorden in deze tekst.

    MaisForth an601 start op met:

    Het interne werkgebied van Forth (0000-02FF):

    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 tijdelijke opslag, o.a. strings
    280-2FF Compiler Stack, dalend

    Bij de koude start wordt de beschikbare hoeveelheid RAM vastgesteld (zie HIMEM) en op de terminal gemeld.

  6. Standaard/niet-standaard woorden (ANS)

    Vocabularies in MaisForth: FORTH ONLY EXTRA INSIDE ASSEMBLER

    De standaard woorden in FORTH en ONLY worden bekend verondersteld.

    De ruim 80 niet-standaard woorden in EXTRA en ONLY staan beschreven in file an601extra-nl.html

    De interne hulpwoordjes in INSIDE zullen voor de gemiddelde programmeur niet van belang zijn. Wie er meer over wil weten, kan de target code in file targ601.f bestuderen.

  7. Hoe maak je een nieuwe ROM image, bijvoorbeeld na veranderingen in de targetcode?

    De metacompiler zou moeten werken op iedere standaard 32-bits Forth. (Ik heb o.a. Win32forth gebruikt.)

    De MaisForth image voor HX C000-FFFF is nu opgeslagen in file an601.bin

  8. Decompileren met SEE

    De decompiler wandelt door het geheugen en kijkt bij ieder adres of er een (16 bit) Forthwoord gecompileerd staat. Zo ja, dan drukt hij de naam af.

    Als bijvoorbeeld op D08E en op D08F 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.

       see accept 
       D089: BD   C0   BDC0.   --  ACCEPT  --  doer DO:  --  FORTH Word
       D08A: C0   FF   C0FF  
       D08B: FF   C8   FFC8. 
       D08C: C8    8   C808      SWAP
       D08E: C5   D4   C5D4      FALSE
       D08F: D4   D0   D4D0.         COMPILE,
       D090: D0   23 # D023      ACCEPTING
       D092: C0   7E ~ C07E      EXIT
    

    De manier om snel de decompiler te leren lezen is: maak zelf een paar kleine woordjes en laat er SEE op los.

    <>

    Woorden met een naam eindigend op () , (C) of (S) hebben een inline argument:

    naam inline    voorbeelden
    ..() cel IF() GOTO() COMPILE() ()    
    ..(C) byte (C)
    ..(S)  counted string   ."(S) "(S) ABORT"(S)

    Het is handig dit te weten, want SEE laat zien wat er in het geheugen staat en niet hoe het daar gekomen is.

    Voorbeelden:
    Het getal 1000 wordt gecompileerd als () gevolgd door een cel met 1000 erin.
    Het getal 1 wordt gecompileerd als (C) gevolgd door een byte met 1 erin.
    ." Hallo!" compileert ."(S) met de counted string "Hallo!" erachter.
    AHEAD compileert GOTO() met daarachter het 16 bits 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.

    Voorbeeld:

       see allot 
       CCE2: BD   C0   BDC0    --  ALLOT  --  doer DO:  --  FORTH Word
       CCE3: C0   FF   C0FF. 
       CCE4: FF   C2   FFC2  
       CCE5: C2   E4   C2E4.         +TO()
       CCE7:  0   49 I   49. 
       CCE8: 49 I C0   49C0  
       CCE9: C0   7E ~ C07E.         EXIT
    
    0049 is het data adres (RAM) van HERE

    De RAM adressen van alle indirecte ROM values:

       0023 TOPVOC 
       002B HLD    
       0033 MODE   
       003B IB     
       0043 HIMEM  
    
       0025 TOPMSG  
       002D CONTEXT 
       0035 SECTION 
       003D THERE   
       0045 OK      
    
       0027 TOPPFX 
       002F CS#    
       0037 #TIMES 
       003F HOR    
       0047 DOT?   
    
       0029 TOPNFA 
       0031 MSG#-2 
       0039 #IB    
       0041 VER    
       0049 HERE   
    
    Deze ROM values gedragen zich voor de programmeur als constanten. Het systeem kan hun waarde wijzigen, de programmeur kan dat alleen indirect.

  9. De metacompiler

    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. De HERE tijdens het metacompileren is de gewone HERE van de host Forth. Voor de overzichtelijkheid laat ik de target image beginnen op het eerst beschikbare adres dat in hex op 000 eindigt.

    De metacompiler meta601.f 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 wordt gestart met :::MAIS::: en heeft zijn eigen QUERY-INTERPRET lus.
    Hij wordt verlaten met ;;;MAIS;;; of als er een fout optreedt.

    Bestudeer allereerst het woord METACOMPILING dat de kern van :::MAIS::: is.

    <>

    De Target code

    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)

    <>

    Zie file an601color.html voor de Target code in kleur.

    Rode woorden in de target code staan in het META vocabulary. Zij zijn actief tijdens het metacompileren. Zie META-WORDS: gevolgd door de woordenlijst, bijna aan het eind van file meta601.f

    Blauwe woorden worden tijdens het metacompileren gecompileerd. Ze worden ter plekke opgezocht in de target-image voorzover die tot dan toe opgebouwd is. Er volgt een foutmelding als ze niet kunnen worden gevonden.

    <>

    De metacompiler kent geen voorwaartse referenties, de target code moet dus in de natuurlijke Forth volgorde staan.
    Dit lijkt misschien een probleem, maar zie hoe dat opgelost is:

    Het DOES-deel van een definiƫrend woord wordt los van het CREATE-deel gedefinieerd (bijv. DOCREATE DOVAR DO: DOCON enz.).

       DOER: ccc1      <high level Forth code>  ;
       DOERCODE ccc2   <assembler code>         NEXT END-CODE
    
    zijn functioneel gelijk aan
       : ccc1 DOES>    <high level Forth code>  ;
       : ccc2 ;CODE    <assembler code>         NEXT END-CODE
    

    Met deze late bindingen zijn we in principe van de voorwaartse referenties af.

    <>

    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 de metacompiler te doorgronden.
    Zo kennen de immediate woorden vier varianten, bijv. de punt-komma:

    (an)