lyhyt 6502-opas

Tämä on katsaus MOS Technology 6502 -prosessorin käskykantaan ja tärkeimpiin ominaisuuksiin. Olen pyrkinyt tekemään tekstistä helppolukuisen enkä tiivistä hakuteosta.

sisältö

luvut

6502:n yhteydessä 8-bittiset tavut voidaan tulkita joko etumerkittöminä tai kahden komplementti -muodossa etumerkillisinä. Ne eroavat toisistaan, kun tavun eniten merkitsevä bitti on ykkönen:

tavu binäärisenä tulkinta
etumerkitön etumerkillinen
00000000 0
00000001 1
01111110 126
01111111 127
10000000 128 −128
10000001 129 −127
11111110 254 −2
11111111 255 −1

rekisterit

6502:n monipuolisin rekisteri on 8-bittinen akku (A). Monet laskutoimitukset voivat muuttaa vain sen arvoa. 8-bittiset indeksirekisterit X ja Y sopivat mm. osoitteiden muodostamiseen, silmukkalaskureiksi ja tiedon välivarastoksi.

Enemmän ohjelmoijalta piilossa ovat 8-bittinen pino-osoitin (SP), joka pitää kirjaa sijainnista pinomuistissa, 8-bittinen tilarekisteri (P), jonka yksittäiset bitit eli liput kertovat mm. prosessorin tilasta, ja 16-bittinen ohjelmalaskuri, joka kertoo, missä osoitteessa ohjelman suoritus etenee.

liput

Liput ovat yksibittisiä rekistereitä prosessorin tilarekisterissä. Niitä on kahta tyyppiä.

Useimmin tarvittavat liput kuljettavat tietoa käskyjen välillä, esim. laskutoimitukselta ehdolliselle hyppykäskylle tai toiselle laskutoimitukselle:

Muita lippuja muuttaa yleensä vain ohjelmoija suoraan, ja ne vaikuttavat prosessorin toimintatilaan:

pino

Pino (stack) on erityinen 256-tavuinen tietorakenne RAM-osoitteissa 0x01000x01ff. Tietyillä käskyillä (esim. pha) pinoon voidaan tallentaa tietoa siten, että se voidaan lukea myöhemmin käänteisessä järjestyksessä (esim. pla-käskyllä). Ohjelmoijan ei myöskään tarvitse välittää, mitä pinossa ennestään on, koska prosessori pitää automaattisesti kirjaa pinon koosta pino-osoittimen (SP) avulla. Pinomuistin maksimikoko ei tietenkään saa ylittyä. Pino mahdollistaa mm. helpot sisäkkäiset aliohjelmakutsut.

Teknisesti pinomuisti on aivan tavallista RAM:ia, joten pinoa voi ajatella yksinkertaisena abstraktiokerroksena ohjelmoijan ja RAM:in välissä.

käskyjen rakenne

6502:n jokainen käsky alkaa yksitavuisella opkoodilla. Sitä saattaa seurata yksi- tai kaksitavuinen data eli operandi. Operandin tyyppiä kutsutaan osoitusmuodoksi.

Symbolisessa konekielessä käsky esitetään kolmikirjaimisena muistikkaana (esim. lda), jonka jälkeen mahdollinen operandi tulee. Samalla muistikkaalla voi olla monta opkoodia (yksi jokaiselle osoitusmuodolle). 6502:ssa kaksitavuiset operandit ovat muistissa vähemmän merkitsevä tavu ensin. Esimerkkejä:

käsky muistissa (heksadesimaalisena) käsky symbolisena konekielenä merkitys
8a txa kopioi rekisterin X sisältö rekisteriin A
a9 ff lda #$ff kopioi luku 255 (0xff) rekisteriin A
ad 34 12 lda $1234 kopioi muistiosoitteen 4660 (0x1234) sisältö rekisteriin A

Kääntäjien syntakseissa on pieniä eroja. Yllä $-merkki ennen lukua tarkoittaa, että luku on annettu heksadesimaalimuodossa.

osoitusmuodot

yksinkertaisimmat

ei operandia
Kaikki käskyn tarvitsemat tiedot sisältyvät pelkkään opkoodiin. Esimerkki: txa tai lsr (jälkimmäinen vain, kun kohteena on akku).
vakio
8-bittinen arvo, joka on jokaisella ajokerralla sama. Arvon eteen kirjoitetaan risuaitamerkki. Esimerkki: lda #$ff eli lda #255
osoite nollasivulla
8-bittinen muistiosoite ns. nollasivulla eli väliltä $00$ff (0–255). Nopeampi kuin tavallinen osoite -osoitusmuoto.
tavallinen osoite
16-bittinen muistiosoite väliltä $0000$ffff (0–65 535).
suhteellinen
8-bittinen arvo, josta prosessori muodostaa osoitteen tulkitsemalla sen etumerkillisenä (−128…+127) ja laskemalla sen kanssa yhteen seuraavan käskyn ensimmäisen tavun osoitteen. Jos kuulostaa vaikealta, ei hätää: useimmissa kääntäjissä kohdeosoitteen voi syöttää absoluuttisena, jolloin ne muuntavat sen automaattisesti suhteelliseksi. Esimerkki: beq $8000 (kääntyy esim. tavuiksi f0 0f, jos osoite $8000 on 15 tavun päässä seuraavan käskyn alusta).

indeksoidut

nollasivu indeksoituna X:llä
Prosessori muodostaa osoitteen laskemalla yhteen 8-bittisen operandin ja X:n senhetkisen arvon. Summa on aina 8-bittinen, eli osoitteen $ff (255) jälkeen tulee taas $00 (0). Esimerkki: lda $00,x
nollasivu indeksoituna Y:llä
Kuin edellinen, mutta Y:n kanssa. Esimerkki: ldx $00,y
tavallinen muisti indeksoituna X:llä
Prosessori muodostaa osoitteen laskemalla yhteen 16-bittisen operandin ja X:n senhetkisen arvon. Esimerkki: lda $8000,x
tavallinen muisti indeksoituna Y:llä
Kuin edellinen, mutta Y:n kanssa. Esimerkki: lda $8000,y

epäsuorat

Kolme monimutkaisinta ja harvimmin tarvittavaa osoitusmuotoa, joiden ideana on, että prosessori hakee annetusta osoitteesta toisen osoitteen. Niitä ei käsitellä tällä sivulla tarkemmin.

käskyt tyypeittäin

rekisterien välillä kopioiminen

Tietoa voidaan kopioida A:n, X:n, Y:n ja pino-osoittimen välillä seuraavilla käskyillä (t tulee sanasta ”transfer”):

käsky kuvaus käsky kuvaus
tay kopioi rekisteri A rekisteriin Y tya kopioi rekisteri Y rekisteriin A
tax kopioi rekisteri A rekisteriin X txa kopioi rekisteri X rekisteriin A
tsx kopioi pino-osoitin rekisteriin X txs kopioi rekisteri X pino-osoittimeen

Mahdolliset kopiointisuunnat voidaan kuvata seuraavasti: Y ↔ A ↔ X ↔ SP

Näillä käskyillä ei ole operandia.

muun tiedon kopioiminen rekistereihin

Rekistereihin A, X ja Y voidaan kopioida monipuolisesti tietoa myös seuraavilla usein tarvittavilla käskyillä (ld tulee sanasta ”load”):

käsky kuvaus
lda lähde kopioi lähde rekisteriin A
ldx lähde kopioi lähde rekisteriin X
ldy lähde kopioi lähde rekisteriin Y

Tuetut osoitusmuodot (pl. epäsuorat):

rekisterien kopioiminen muualle

Seuraavilla käskyillä rekistereistä A, X ja Y voidaan kopioida tietoa muistiin (st tulee sanasta ”store”):

käsky kuvaus
sta kohde kopioi rekisteri A kohteeseen
stx kohde kopioi rekisteri X kohteeseen
sty kohde kopioi rekisteri Y kohteeseen

Tuetut osoitusmuodot (pl. epäsuorat):

yhteen- ja vähennyslasku sekä vertailu

Yhteen- ja vähennyslaskussa kohteena (muuttuvana rekisterinä) voi olla vain A. Myös vertailukäskyt on esitelty tässä yhteydessä, koska ne muistuttavat teknisesti vähennyslaskukäskyä. Käskyjen toimintaan ei puututa tässä tarkemmin. Muistikkaissa ad tarkoittaa ”add”, sb ”subtract”, c "carry" ja cmp tai cp ”compare”.

käsky kuvaus
adc lähde lisää lähde rekisteriin A
sbc lähde vähennä lähde rekisteristä A
cmp lähde vertaa lähdettä rekisteriin A
cpx lähde vertaa lähdettä rekisteriin X
cpy lähde vertaa lähdettä rekisteriin Y

Tuetut osoitusmuodot (pl. epäsuorat):

yhdellä vähentäminen ja lisääminen

Nämä käskyt yksinkertaisesti pienentävät tai suurentavat kohteen arvoa yhdellä. Kohde oletetaan etumerkittömäksi luvuksi ja se pyörähtää ympäri ali- tai ylivuodon sattuessa.

käsky kuvaus käsky kuvaus
dex vähennä X-rekisterin arvoa yhdellä inx lisää X-rekisterin arvoa yhdellä
dey vähennä Y-rekisterin arvoa yhdellä iny lisää Y-rekisterin arvoa yhdellä
dec kohde vähennä kohteen arvoa yhdellä inc kohde lisää kohteen arvoa yhdellä

Käskyillä dex, inx, dey ja iny ei ole operandia. Sen sijaan käskyjen dec ja inc osoitusmuoto voi olla jokin seuraavista:

Carry-lippu ei vaikuta näihin käskyihin eivätkä nämä käskyt siihen (toisin kuin adc:n ja sbc:n tapauksessa).

Käskyt dec ja inc ovat huomattavan hitaita (5 kellojaksoa tai enemmän).

bittitason laskutoimitukset

käsky kuvaus
and lähde nollaa A:n bitit, joita vastaavat lähteen bitit ovat nollia
ora lähde aseta ykkösiksi A:n bitit, joita vastaavat lähteen bitit ovat ykkösiä
eor lähde vaihda niiden A:n bittien tila, joita vastaavat lähteen bitit ovat ykkösiä
bit lähde kopioi lähteen kaksi eniten merkitsevää bittiä lippuihin N ja V; aseta lippu Z vastaamaan laskutoimituksen A AND lähde tulosta

Käskyjen and, ora ja eor tukemat osoitusmuodot (pl. epäsuorat):

Käsky bit tukee vain seuraavia osoitusmuotoja:

bittien vieritys

Nämä käskyt vierittävät kohdetavun bittejä vasemmalle (asl ja rol) tai oikealle (lsr ja ror). Käskyt asl ja lsr ”ottavat sisään” aina nollan ja kopioivat ylivuotavan bitin C-lippuun, jolloin sen entinen arvo tuhoutuu. rol ja ror taas suorittavat yhdeksänbittisen kierron C-lipun kautta.

Seuraavat kuvat havainnollistavat käskyjen toimintaperiaatetta. A7–A0 tarkoittavat kohdetavun bittejä eniten merkitsevästä vähiten merkitsevään ja C carry-lippua.

asl kohde C<A7<A6<A5<A4<A3<A2<A1<A0<0
lsr kohde 0>A7>A6>A5>A4>A3>A2>A1>A0>C
rol kohde C<A7<A6<A5<A4<A3<A2<A1<A0<C
ror kohde C>A7>A6>A5>A4>A3>A2>A1>A0>C

Tuetut osoitusmuodot:

Jos kohteena on muistiosoite, nämä käskyt ovat huomattavan hitaita (5 kellojaksoa tai enemmän).

ehdolliset hyppykäskyt

Nämä hyppykäskyt toteutuvat vain, jos niihin liittyvä ehto on voimassa (b tulee sanasta ”branch”):

käsky kuvaus käsky kuvaus
bne osoite hyppää, jos zero-lippu on nolla beq osoite hyppää, jos zero-lippu on ykkönen
bpl osoite hyppää, jos negative-lippu on nolla bmi osoite hyppää, jos negative-lippu on ykkönen
bcc osoite hyppää, jos carry-lippu on nolla bcs osoite hyppää, jos carry-lippu on ykkönen
bvc osoite hyppää, jos overflow-lippu on nolla bvs osoite hyppää, jos overflow-lippu on ykkönen

Näiden käskyjen operandi on aina tyyppiä suhteellinen (ks. osoitusmuodot).

lippujen tilan asettaminen

Näillä käskyillä voidaan ”manuaalisesti” asettaa yksittäisten lippujen tiloja halutuiksi:

käsky kuvaus käsky kuvaus
clc aseta carry-lippu nollaksi sec aseta carry-lippu ykköseksi
clv aseta overflow-lippu nollaksi
cli aseta interrupt disable -lippu nollaksi sei aseta interrupt disable -lippu ykköseksi
cld aseta decimal-lippu nollaksi sed aseta decimal-lippu ykköseksi

Näillä käskyillä ei ole operandia.

muut käskyt (kesken)