.LL 72
.C 1
RAS REFERENCE MANUAL
.B 2
Beschrijving.
.B 1
RAS is de uitbreiding van de "bionische assembler"
tot relocatable assembler.
Het nu volgende verhaal beschrijft de exacte eigenschappen
van deze assembler,
voor mensen die reeds in 6809-assembleertaal kunnen
programmeren.
.BR
    Elke regel van de source-code moet een instructie
bevatten;
lege regels zijn niet toegestaan.
Een regel die met "*" begint wordt als commentaar opgevat.
Een regel die met een label begint moet dit in
de eerste kolom hebben.
Anders moet hij met een spatie (" ") beginnen.
Een regel bestaat uit 4 velden, t.w. label-,
mnemonic-, operand- en commentaar-veld.
De velden moeten door precies 1 spatie gescheiden zijn.
De assembler onderscheidt kleine en hoofdletters;
alleen hoofdletters worden als letters beschouwd.
Control characters in de input worden meteen in een
vraagteken ("?") omgezet.
.BR
    De assembler is van het multi-pass type:
Eerst wordt een aantal malen de source-text verwerkt
om de waarde van alle erin voorkomende symbolen te bepalen.
(PASS 1).
Een symbool wordt in de symbol-table geplaatst zodra
het voor de eerste keer ontmoet wordt,
en ontvangt aanvankelijk de waarde UNDEFINED.
Zodra de assembler een definitie van het symbool tegen komt,
doordat het in een EQU instructie,
of als label bij bepaald geheugen adres voorkomt,
dan wordt de waarde van het symbool in de symbol-table
ingeschreven.
Wanneer de waarde van het symbool reeds gedefinieerd was,
wordt gecontroleerd of dit dezelfde waarde is.
(Het symbool was dan kennelijk al tijdens een eerdere pass
gedefinieerd.)
Als dit niet het geval is, dan kan dit twee oorzaken hebben:
Het symbool kan dubbel gedefinieerd zijn,
in welk geval een foutmelding gegenereerd moet worden,
of het kan zijn dat we tijdens de vorige pass het symbool
een waarde gegeven hebben,
die niet meer correct is omdat bij de nieuwe pass blijkt dat
het programma toch kleiner was dan we gedacht hadden.
(Een zogenaamde fasefout.)
Op de 6809 is het van bepaalde indexed adresserings wijzen
namelijk niet zonder meer duidelijk hoeveel bytes zij
in zullen nemen;
dit hangt af van de waarde van de gebruikte offset.
Als deze offset tijdens de eerste pass nog niet bekend is,
(doordat er een verderop gedefinieerd label in voorkomt),
gaat de assembler ervan uit dat de grootste waarde gebruikt
wordt.
Tijdens een volgende pass is de offset dan wel bekend,
en kan blijken dat het met minder bytes kon.
In dat geval schuiven alle erop volgende label definities
dus naar een lager adres.
Herdefinieren van een reeds gedefinieerd symbool
levert dus geen foutmelding op als het hierdoor kleiner wordt;
alleen als het groter wordt (of van een ander type is)
geeft de assembler een foutmelding bij het adresveld.
PASS 1 wordt net zolang gedaan tot er geen
fasefouten meer optreden;
elk symbool heeft dan zijn definitieve waarde.
Als er geen fouten tijdens PASS 1 ontdekt waren,
dan wordt PASS 2
gedaan.
tijdens deze pass wordt de listing en de object-code
gegenereerd.
Een foutloze PASS 1 garandeerd nog geen foutloze PASS 2:
Tijdens PASS 2 is het namelijk verboden om een ongedefinieerde
waarde te gebruiken,
en wordt ook gecontroleerd of branch instructies "het halen".
.B 2
Foutmeldingen.
.B 1
Fouten worden aangegeven door de regel waarin de fout
optrad af te drukken,
en eronder een regel met een pijltje ("^")
die de plaats van de fout aangeeft.
Omdat dit meteen duidelijk maakt wat de fout is,
zijn fout-nummers overbodig.
Mogelijke fouten zijn:
.NF
.B 1
plaats v/d fout            fout omschrijving
adres veld           dubbel gedefinieerd symbool
operand waarde byte  operand te groot voor register.
begin label veld     register naam als label.
einde label veld     illegaal teken in label.
begin mnemonic veld  niet bestaande instructie.
einde mnemonic       illegaal teken in mnemonic.
begin operand veld   niet bestaande adresseringswijze.
einde operand veld   illegaal teken in operand.
                     of geen spatie voor commentaar.
midden operand veld  indexed mode syntax klopt niet.
meteen na operand    ] of register naam ontbreekt
in een getal         te groot cijfer voor dit grondtal
waarde veld EQU      gelijkstelling externe symbolen.
operand veld ORG     plaats ongedefinieerd.
na einde regel FCC   string niet afgesloten.
tijdens pass 2 kunnen we bovendien krijgen:
branch offset byte   short branch haalt het niet.
begin symbool        symbool ongedefinieerd.
operator + of -      combinatie geeft UNDEF resultaat.
.FI
.B 1
In het algemeen wordt het resterende deel van de regel
naar het eerstvolgende veld geschoven.
Een ongedefineerd symbool wordt afgedrukt met het
pariteitsbitje geset,
wat op de meeste displays "reverse video" oplevert.
.B 2
Expressies en symbolen.
.B 1
Als symboolnaam kan elke serie van letters en cijfers
dienen,
mits het eerste teken een letter is.
Een underscore "_" telt hierbij als letter.
Alleen de eerste 6 tekens van elke naam worden bekeken.
Gebruik van langere namen wordt afgeraden,
omdat zij niet in de listing passen.
Getallen beginnen met een cijfer als zij in
grondtal 10 gegeven zijn,
of met de tekens procent ("%") voor binaire,
apestaart ("@") voor octale,
of dollar ("$") voor hexadecimale getallen.
Letters worden als cijfers beschouwd,
A=10, B=11 enzovoort.
Er mogen geen cijfers in een getal voorkomen groter of
gelijk aan het grondtal.
Een symbool waarvan de naam met underscore begint is
EXTERN.
Een dergelijk symbool hoeft niet in hetzelfde source-programma
gedefinieerd te zijn.
Een sterretje ("*") staat voor het instructie-adres;
dit is het adres waarop het eerste byte van de door de
huidige regel beschreven instructie door de assembler
geplaatst wordt.
Expressies zijn combinaties van deze 3 basis operanden
met behulp van de operatoren plus ("+") en min ("-"),
voor resp. optellen en aftrekken.
(De symbolen ">", "<", "<<", ">>", "&", "|" en "~"
zijn gereserveerd voor toekomstige uitbreiding met
shift- en logische operaties.)
Behalve een waarde heeft elke expressie ook een type.
Mogelijke types zijn ABS, TXT, DAT, EXT en UND.
Een getal heeft altijd type ABS.
Het type van "*" is ABS, TXT of DAT,
afhankelijk van of we op een absoluut adres,
of in het text- of data-segment aan het assembleren zijn.
Een symbool kan elk type hebben,
afhankelijk van hoe het gedefinieerd is.
Een ongedefinieerd symbool heeft type UND (voor een lokaal),
of EXT (voor een extern symbool).
Definitie door gebruik als label geeft hem de
waarde en het type van "*".
Definitie met een EQU geeft hem hetzelfde type als
de expressie van het rechter lid.
Het type van het resultaat van een operatie
is als volgt gedefinieerd:
.B 1
.NF
    +    type linker lid                -    type linker lid
       ABS TXT DAT EXT UND                 ABS TXT DAT EXT UND
   ABS ABS TXT DAT EXT UND             ABS ABS TXT DAT EXT UND
   TXT TXT UND UND UND UND             TXT UND ABS UND UND UND
   DAT DAT UND UND UND UND             DAT UND UND ABS UND UND
   EXT EXT UND UND UND UND             EXT UND UND UND  *) UND
   UND UND UND UND UND UND             UND UND UND UND UND UND
    ^ type rechter lid                  ^ type rechter lid
.B 1
.FI
Type EXT is bijzonder omdat erbij onthouden wordt
om welk extern symbool het ging.
Eigenlijk zijn er dus een heleboel verschillende typen EXT,
en elke berekening met dit type levert hetzelfde type EXT op.
Bij aftrekken van twee EXT typen krijgen we type ABS
wanneer het om hetzelfde externe symbool ging,
en anders type UND.
Tydens PASS 2 mag geen enkele expressie type UND hebben.
Sommige instructies eisen tijdens PASS 1 zelfs al dat het
type ongelijk aan EXT of UND moet zijn.
.BR
    Expressies worden van links naar rechts uitgerekend;
voor elke operand staat een operator die bepaald of
de operand opgeteld of afgetrokken moet worden van het
tot nu toe berekende resultaat.
(Dat met waarde 0 van type ABS begint.)
Alleen de eerste operand hoeft geen operator ervoor te
hebben, in welk geval plus aangenomen wordt.
.B 2
Assembler opdrachten.
.B 1
Afgezien van de mnemonics voor 6809 instructies,
kent de assembler de volgende pseudo-instructies:
.B 1
ORG <expressie>
.BR
Vanaf nu wordt de opgewekte machine-code beginnend
op het door de expressie gegeven adres geplaatst.
De expressie moet gedefinieerd zijn voordat de ORG
voor het eerst ontmoet wordt,
en bovendien type ABS hebben, zodat we in het
absolute segment verder assembleren.
Als er een harkje ("#") volgt meteen op de expressie,
dan wordt bovendien het high-order byte van de expressie
door de assembler als direct-page beschouwd.
(Dit is het equivalent van de SETDP instructie van MOTOROLA.)
.B 1
<label> EQU <expressie>
.BR
Het genoemde label krijgt de waarde voorgesteld door
de expressie.
De aanwezigheid van het label is verplicht.
We kunnen een symbool definieren in termen van symbolen
die pas later gedefinieerd worden,
maar dit leidt er in de regel toe dat PASS 1 enkele malen
extra uitgevoerd moet worden voor de assembler de zaak
ontward heeft.
Definities van symbolen in termen van elkaar,
of zichzelf,
leidt ertoe dat de symbolen ongedefinieerd blijven.
Het is verboden om een extern symbool af te laten
hangen van een ander (ongedefinieerd) extern symbool.
(Dus als het type van de expressie EXT is,
moet het label lokaal zijn.)
.B 1
END
.BR
Einde van de source-listing.
Alles wat na de END staat wordt door de assembler niet
bekeken.
Het ontbreken van een END leidt er bij assembleren vanuit
het geheugen toe dat de assembler gewoon doorgaat
met het assembleren van rommel buiten de edit buffer.
.B 1
TEXT
.BR
Vanaf nu wordt de machine-code in het text-segment geplaatst,
beginnend op het eerste lege adres in dit segment.
(Aanvankelijk 0)
.B 1
DATA
.BR
Vanaf nu wordt de machine-code in het data-segment geplaatst,
beginnend op het eerste lege adres in dit segment.
(Aanvankelijk 0)
.B 1
FCB <expressie lijst>
.BR
Alle expressies in de lijst
(die door komma's (",") gescheiden moeten zijn),
worden uitgerekend,
en in de genoemde volgorde in het geheugen geplaatst
als 8 bits waarde.
Als de waarde type ABS heeft,
en niet tussen -128 en 255 (inclusief) ligt,
wordt een foutmelding wegens overflow gegeven.
.B 1
FDB <expressie lijst>
.BR
Alle expressies in de lijst
(die door komma's (",") gescheiden moeten zijn),
worden uitgerekend,
en in de genoemde volgorde in het geheugen geplaatst
als 16-bits waarde.
Het high-order byte gaat hierbij voorop.
.B 1
FCC <expressie lijst>
.BR
Deze instructie is gelijk aan FCB,
met als enige verschil dat als expressie een "string"
mag optreden.
Een string is een rij van characters,
tussen twee gelijke tekens (de delimiters) in.
Elk afdrukbaar ASCII teken behalve de delimiter kan
in de string voorkomen.
Als delimiter kan elk character optreden dat geen speciale
functie heeft,
(aanbevolen zijn de enkele quote "'",
of de slash "/"),
dus niet letters, cijfers, de underscore "_",
de operatoren plus "+" en min "-",
of het instructie adres "*".
De ASCII codes voor de characters in de string worden
achter elkaar in het geheugen geplaatst,
het meest linkse op het laagste adres.
.B 1
RMB <expressie>
.BR
Er worden zoveel bytes open gelaten als de expressie
aangeeft.
(Dus de expressie wordt bij "*" opgeteld.)
De expressie moet gedefinieerd zijn.
Een label bij deze instructie krijgt de waarde van "*"
zoals die voor het uitvoeren was.
(Dus het adres van het eerste byte van de gereserveerde
ruimte.)
.B 1
OPT
.BR
Deze instructie maakt het mogelijk de assembler opties
te wijzigen.
Omdat er maar 1 optie is,
namelijk het aan of uitzetten van de listing,
kijkt hij niet verder naar zijn operand veld.
.B 2
Adresserings wijzen.
.B 1
De assembler kent alle adresserings wijzen volgens
de MOTOROLA syntax.
Hij kiest zelf de meest korte manier van adresseren
die mogelijk is.
Het is helaas niet mogelijk hiervan af te wijken.
Als dit ooit geimplementeerd wordt zullen hier
de tekens punt (".") voor een 1 bytes,
en dubbelepunt (":") voor een 2 bytes wijze
gebruikt worden,
met de restrictie dat altijd de kortst mogelijke manier
die niet korter is als de gevraagde gebruikt wordt.
(Een 0-bytes wijze hoeven we dus niet aan te geven
omdat die standaard is.)
Op elke plaats waar een waarde nodig is mag een expressie
staan.
De herkende wijzen zijn:
.BR
.NF
#L      L       ,R      L,R     A,R     B,R     D,R
L,PC    L,PCR   ,-r     ,--r    ,r+     ,r++    [L]
[,r]    [L,r]   [A,r]   [B,r]   [D,r]   [L,PC]  [L,PCR]
[,-r]   [,--r]  [,r+]   [,r++]
.BR
.FI
met L een waarde, en r een van de registers X,Y,U of S.
Bij de mode L,PC wordt de waarde van L als de offset
gebruikt,
terwijl bij L,PCR de offset gegeven wordt door het
verschil van de gegeven waarde en het huidige adres.
(De waarde van "*" na deze instructie.)
De mode L,r wordt vertaald als een 5-bits (=0-bytes)
offset 0 als L toevallig 0 is,
en niet als ,r.
.B 2
6809 instructies.
.B 1
De 6809 instructies worden met hun standaard MOTOROLA
mnemonic aangeduid.
Er zijn geen speciale afkortingen voor 6800 equivalente
instructie reeksen (zoals ABA, INX).
De meeste instructies vergen een operand,
die tevens de informatie omtrend de adresseringswijze
bevat.
Op grond van de toegestane adresserings wijzen,
kunnen we de instructies als volgt indelen:
.B 1
SUB, CMP, SBC, ADD, AND, BIT, LD, ST, EOR, ADC, OR
.BR
Vergen een accumulator aanduiding
(meteen aan de mnemonic vastgeschreven A of B),
en een operand.
Alle geheugen adresseringen zijn toegestaan,
behalve immediate bij ST.
.B 1
LDD, LDX, LDY, LDU, LDS, CMPD, CMPX, CMPY, CMPU, CMPS,
SUBD, ADDD
.BR
Vereisen een geheugen operand.
.B 1
STD, STX, STY, STU, STS, JSR, JMP
.BR
Vereisen een geheugen operand,
maar immediate is hier niet toegestaan.
.B 1
BRA, BRN, BHI, BLS, BCC, BCS, BHS, BLO, BNE, BEQ,
BVC, BVS, BPL, BMI, BGE, BLT, BLE, BGT, BSR
.BR
Vereisen een label als operand.
Een L voor de mnemonic geplakt maakt er een long-branch van.
.B 1
NEG, COM, LSR, ROR, ASR, ASL, ROL, DEC, INC,
TST, CLR
.BR
Vereisen een accumulator aanduiding
(een aan de mnemonic vastgeschreven A of B),
of een geheugen operand, ongelijk aan immediate.
.B 1
PSHS, PULS, PSHU, PULU
.BR
Vereisen een immediate operand,
of een lijst van registernamen gescheiden door komma's (",").
Toegestane registernamen zijn: A,B,D, X,Y,U,S, DP,CC,PC.
Merk op dat het niet mogelijk is om een stackpointer op
zijn eigen stack te zetten!
.B 1
LEAX, LEAY, LEAU, LEAS
.BR
Vereisen een operand in indexed mode.
.B 1
CWAI, ANDCC, ORCC
.BR
Vereisen een immediate operand.
.B 1
TFR, EXG
.BR
Vereisen twee registernamen gescheiden door een komma (",").
Namen van 8-bits registers zijn A,B,CC,DP.
Van 16-bits registers zijn dit D,X,Y,U,S,PC.
Het is verboden om 8 en 16 bits registers te combineren.
.B 1
SYNC, DAA, SEX, RTS, ABX, RTI, MUL, SWI, SWI2, SWI3
.BR
Hebben geen operand nodig.
.B 2
De 6309 uitbreiding
.B 1
De 6309 was een microprocessor gefabriceerd door Hitachi,
met de licensie om een 6809 compatible processor te maken.
Zij hebben de CPU echter sterk uitgebreid,
hoewel zij niet gemachtigd waren die uitbreidingen ook bekend
te maken.
De gebruikers hebben deze echter zelf in kaart gebracht.
RAS ondersteunt de 6309 instructie set,
maar gebruikt een afwijkende assembler syntax voor sommige
instructies.
.B 1
Om te beginnen heeft de 6309 een aantal extra registers.
Dat zijn twee 8-bit accumulatoren, E en F,
een 8-bit mode register MD,
en een 16-bit register V waarin een constante bewaard
kan worden die bij reset behouden blijft.
Het paar E,F kan als 16-bit register W gebruikt worden,
zoals A,B als D gebruikt wordt.
Het paar W en D samen vormt weer een 32-bit register
aangeduid als Q,
maar er zijn niet veel instructies die daar iets mee doen.
.BR
Instructies die op de 6809 op een accumulator werken,
zoals ADDA of INCB, kunnen op de 6309 vaak ook met
E, F, D of W werken.
.BR
Ook kunnen de nieuwe registers gebruikt worden in
de indexed addressing mode,
in analogie met de modes A,X of D,X,
waarbij X ook een ander 16-bit register (Y, U of S)
kan zijn.
Daarnaast kan W zelf ook als index register gebruikt worden
in de modes ,W, ,W++, ,--W, C16,W.
Waarbij C16 een 16-bit constante is.
.B 1
Er zijn ook een aantal geheel nieuwe instructies.
Daaronder zijn operaties tussen registers,
tussen geheugenplaatsen, en tussen individuale bits.
.B 1
ADDR, ADCR, SUBR, SBCR, ANDR, ORR, EORR, CMPR
.BR
voeren de operatie waar hun 1e drie letters voor staan uit
op twee registers ('bron' en 'doel'),
waarbij het resultaat teruggeschreven wordt in het
doelregister.
(Behalve bij CMPR, dat geen van de registers wijzigt,
maar alleen de condite codes zet.)
Hun syntax is dezelfde als die van TFR .
(Wat gezien kan worden als de 'R versie' van ST.)
B.v.
.B 1
ADDR X,U
.BR
telt X bij U op en zet het resultaat in U.
.BR
Merk op dat zowel TFR als deze nieuwe instructies ook
op de nieuwe registers E, F, V en W kunnen werken,
en dat de resterende register codes bij uitlezen 0 opleveren.
.B 1
BAND, BOR, BEOR, BIAND, BIOR, BIEOR, LDBT, STBT
.BR
zijn instructies die individuele bits manipuleren of kopieren.
Behalve voor STBT gaat het resultaat altijd naar een register.
De andere operand komt uit het geheugen,
maar alleen via 'direct' addressering.
Alleen de registers A, B en CC kunnen gebruikt worden.
De versies die met BI beginnen inverteren eerst het bit
dat uit het geheugen komt.
.BR
Behalve het register en het geheugenadres moeten dus ook de
bitnummers in beide worden aangegeven.
Dit vergt een speciale syntax.
In RAS gebeurt dit door achter de operand een dubbele punt
en dan het bitnummer (0-7) te zetten.
B.v.:
.B 1
BOR A:3 30:5
.BR
berekent de OR tussen bit 5 van geheugenplaats 30 en bit 3
van A, en schrijft het resultaat terug in bit 3 van A.
Dat alles zonder andere bits te veranderen.
(Andere assemblers vereisen dat deze nummers
gescheiden door komma's van de rest,
in een verwarrende volgorde gegeven worden.)
.B 1
AIM, OIM, EIM en TIM
.BR
combineren (als bitwijs logische AND, OR, EOR of BIT)
hun immediate operand met het geadresserde geheugen.
Zij hebben dus eigenlijk twee geheugen operanden.
(Hoewel de eerste dus altijd immediate moet zijn.)
De RAS syntax noemt ze beide, gescheiden door een spatie.
B.v.
.B 1
AIM #24 ,U++
.BR
wat het byte aangewezen door U uit het geheugen ophaalt,
dat AND met de constante 24, en het resultaat dan
terugschrijft.
Waarna U dan wordt opgehoogd.
Dus zoiets als CLR ,U++, maar dan met gedetailleerde
beheersing over welke bits gecleard worden.
.B 1
LDQ, STQ
.BR
verhuizen het 4-byte Q register van of naar het geheugen.
Zij werken met alle addressing modes waar LD en ST normaal
mee werken.
Maar LDQ kan dus een 4-byte immediate operand hebben.
.B 1
MULD, DIVD, DIVQ
.BR
voeren vermenigvuldigingen en delingen uit.
Zoals MUL twee 8-bit waarden vermenigvuldigt om een 16-bit
resultaat te krijgen,
doet MULD dat met 16-bit waarden voor een 32-bit resultaat.
Dat resultaat komt dan in Q;
de operanden komen uit D en uit het geheugen.
DIV instructies doen het omgekeerd; die beginnen met een
operand van de dubbele afmeting,
en delen die door een van de enkele afmeting om twee
resultaten van enkele afmeting te krijgen.
Namelijk het quotient en de rest.
Die komen dan in het lage, resp. het hoge deel van
het register waar de teller stond.
De deler komt uit het geheugen.
Net als bij MULD kunnen alle addressing modes gebruikt
worden.
.B 1
SEXW
.BR
breidt een 16-bit waarde in W uit tot een 32-bit waarde in Q,
met behoud van teken.
.B 1
MOV, MOVR, FILL, PUT
.BR
zijn block-move instructies.
De gebruikte mnemonics zijn uniek voor RAS;
in andere assemblers heten deze instructies allemaal TFM,
en moet je aan de adressingmode zien met welke je te maken
hebt.
De syntax van deze instructies in RAS is dezelfde als van TFR.
Er moeten twee 16-bit registers genoemd worden
(X, Y, U, S of D).
Die bevatten het startadres van twee geheugen gebieden,
en de instructies kopieren dan het 1e gebied naar het tweede.
Hoeveel bytes gekopieerd moeten worden wordt aangegeven
door W.
Bij MOV worden na elke transfer beide registers met 1 verhoogd.
Bij MOVR worden ze juist verlaagd
(en is het 'startadres' dus eigenlijk het eindadres).
Dit zijn dus 'block moves', die hetzelfde doen tenzij de
te gebruiken gebieden overlappen.
.BR
Bij FILL wordt alleen het 2e register opgehoogd,
zodat hetzelfde byte naar een heel gebied gekopieerd wordt.
Bij PUT wordt alleen het 1e register opgehoogd,
zodat alle bytes in het gebied naar dezelfde geheugenlocatie
worden gekopieerd.
(Dit kan zin hebben als hier een memory-mapped I/O device zit.)
.B 1
LDMD, BITMD
.BR
zetten of testen bits in het 6803 mode register MD.
Een immediate operand geeft aan welk bitpatroon gezet
of welke bits getest moeten worden.
Er zitten overigens maar vier functionele bits in MD,
waarvan er twee alleen leesbaar zijn, en twee andere
alleen schrijfbaar.
De leesbare bits (via BITMD) geven aan of er een
ongeldige instructie is uitgevoerd of een deling door nul
heeft plaatsgevonden. (En zet ze bij lezen meteen op 0.)
De twee laagste bits bepalen of de fast interrupt werkt als
op de 6809, of dat hij alle registers op de stack zet zoals
IRQ dat doet.
En of de 6309 in 'native mode' werkt,
waar de meeste instructies minder klokcycli nodig hebben,
en bij interrupts het W register ook op de stack gezet wordt.
