SuperCPU durchleuchtet - Folge 8

Tja Leute, nachdem wir in GO64! 9/97 einiges ueber Interrupt-Programmierung
auf der SuperCPU erfahren haben, geht's jetzt voll zur Sache: Bis zu 16 MByte
Ram am Commodore 64 - und die warten nur darauf, voll ausgereizt zu werden.
Wie man den Speicher anspricht und mehr erfahrt Ihr hier.


Erstmal muss man sich klarmachen, wie der neue Speicher vorliegt: Als direkt
adressierbares Ram naemlich. Das heisst, nach $FFFF ist nicht mehr Schluss! Beim
SuperCPU-Prozessor ist die hoechste moegliche Adresse naemlich $FFFFFF - zur
Adressierung werden nun 3 Bytes benutzt, wie gehabt das Low- und Highbyte,
und zusaetzlich das Bank-Byte. Die erste Adresse nach $00FFFF ist folglich
$010000 - man koennte es auch als Adresse 0 in Bank 1 bezeichnen. Jede
Speicherbank enthaelt 64K, wobei alles linear durchadressiert wird.


Der Aufbau

Wie wir es alle kennen, haben wir Speicher von $0000-$FFFF, wobei es fuer die
SuperCPU eigentlich $000000-$00FFFF ist. Das Bank-Byte des nun
24 Bit grossen Program-Counters wird naemlich beim Einschalten automatisch auf
null gesetzt. Vielleicht habt Ihr es irgendwo schonmal gehoert: Die SuperCPU
hat von sich aus 128K Speicher. Damit naemlich der Eprom-Baustein nicht die
Geschwindigkeit bremst, wird das gesamte Betriebssystem von dort beim
Einschalten in's Ram kopiert - in die anderen 64K, die fuer uns nicht
erreichbar sind. Oder besser gesagt, nicht ganz erreichbar - denn dieses Ram
ist ab $010000-$01FFFF zu finden! Fuellt man in einer Schleife diesen Bereich,
wird sich der C64 danach aufhaengen, da das Rom - oder besser gesagt Ram - ja
nun leer ist. Mit einer SuperRAM-Card jedoch ist ab $020000 der neue Speicher
frei. Bei einem 1 MB-Simm hat man nun genau 1 MB Speicher - die letzte
Adresse ist $0FFFFF. Einige werden es vielleicht schon gemerkt haben: Man hat
nicht 64K bzw. 128K + 1 MB dazu, da Bank 0 und 1 schon vom internen SRAM der
SuperCPU belegt sind. 


Und wie kommt man ran?

Um nun Daten in das Ram zu packen und von dort zu holen, muss man keine
komplizierten Befehlsketten eingeben oder aehnliches. Um z.B. eine #$20 nach
Adresse $058100 zu schreiben, reicht ein


LDA #$20

STA $058100


Das war es schon! Damit ist der Wert im Speicher gelandet. Um ihn von dort
wieder zu holen, braucht man nur einen LDA-Befehl. Wenn wir z.B. eine Farbe
aus einer Tabelle ab $03A000 holen wollen, koennte man es so realisieren:


LDX #$00

LDA $03A000,X

STA $D020


Tja, so einfach ist das - und dazu braucht Ihr noch nichtmal im Native Mode
zu sein! Den braucht man (Ihr erinnert Euch) lediglich einzuschalten, wenn
man 16 Bit benutzen will - natuerlich funktionieren die sogenannten
'Long'-Adressierungen (mit der Adresse aus 3 Byte) auch wenn die Register auf
16 Bit sind. Eigentlich koennte der Kursteil hier schon wieder enden -
schliesslich wisst Ihr nun, wie man den neuen Speicher benutzt, oder? :-)

Aber die SuperCPU waere nicht sie selbst (Hm? Hat sie ein Bewusstsein? Das
waere eine Diskussion wert...), wenn da nicht noch allerhand weiterer toller
Features drinsteckten, die mit dem Speicher der SuperRAM-Card zu tun haben.


Ueber die Zeropage

Denn wenn man eine Weile codet, wird man frueher oder spaeter darueber stolpern,
dass man eine Adresse in einer Bank ungleich 0 in einem Zeropage- (Direct
Page, wie wir ja seit kurzem wissen - die Page muss ja nicht mehr bei $0000
liegen) Zeiger ablegen moechte. Normalerweise macht man das auf der SuperCPU
ja z.B. so (angenommen wir sind im 16 Bit-Mode):


LDA #$5000 

STA $FC


Und schon hat man die #$00 in $FC und die #$50 in $FD und kann dann ueber LDA
($FC),Y (oder auf der SuperCPU ja auch ohne ,Y) auf die Adresse zugreifen.
Intelligenterweise weiss der 65816-Prozessor, dass die Adresse in Bank 0 liegen
soll - das wird einem jetzt erst klar. Was aber nun, wenn die Adresse z.B. in
Bank 2 liegt? Dafuer gibt's den neuen speziellen 3-Byte-Zeiger. Natuerlich
braucht der 3 Direct Page-Speicherstellen - dafuer kommt man aber damit auch
an jedes einzelne Byte im gesamten 16 MByte-Adressraum (und den kann man ja mit
der SuperRAM-Card komplett vorliegen haben). Angenommen, wir wollen indirekt
auf Adresse $020000 zugreifen - so geht's:


STZ $FC

STZ $FD

LDA #$02

STA $FE

LDY #$05

LDA [$FC],Y


In $FC steht das Lowbyte unserer Adresse, hier 0 (deshalb auch der STZ), auch
das Highbyte ist 0, damit haetten wir $0000. Dann folgt das Bank-Byte, $02, es
ergibt sich die Adresse $020000. In das Y-Register packen wir eine 5, und der
naechste LDA holt dann den Wert von Adresse $020005! Wie Ihr seht, sind die
Jungs vom Western Design Center beim Entwickeln des Prozessors wieder 100%ig
dem Konzept des 6502 gefolgt - diese Art der Adressierung ist eigentlich die
logische Erweiterung der bisherigen Struktur.

Somit stehen uns die zwei Standard-Moeglichkeiten zur Verfuegung, entweder
direkt (ueber die Adresse) oder indirekt (ueber einen Pointer in der
Zero/Direct Page) auf den Speicher zuzugreifen. Lasst Euch das erstmal auf der
Zunge zergehen!


Moment mal eben

Nach etwas Nachdenken kommen einige Fragen auf. Wie sieht es z.B. mit
Programmen aus? Muss man jetzt immer die 'Long'-Adressierung verwenden, auch
wenn man auf Bank 0 zugreifen will? Natuerlich nicht - aber man kann es
selbstverstaendlich. Listing 1 zeigt ein paar kleine Transfer-Routinen.
Zuerst wird ein Bereich des 'normalen' Speichers (wir nehmen mal einen Teil
des Screenrams zu Demonstrationszwecken) in die SuperRAM kopiert. Dann wird
dieser noch in einen anderen Speicherbereich verschoben, und schliesslich
landet er wieder in Bank 0 - auf dem Screen. Selbstverstaendlich kann man
statt $0400 auch $000400 schreiben! Bezieht man sich aber auf die untersten
64K, kann man auf die Long-Adressierung auch verzichten, da der Prozessor,
wenn er nur eine 16 Bit lange Adresse findet, defaultmaessig Bank 0 annimmt. 

Was nun aber, wenn man sich z.B. staendig auf z.B. Bank 3 beziehen will? Man
holt verschiedenste Werte ueberall aus dem Speicher, doch Bank 3 ist haeufig
benutzt - linear durchadressierter Speicher ist ja schoen, aber immer $03XXXX
tippen ist auch nicht gerade das Gelbe vom Ei. Darum gibt es die
Moeglichkeit, das Bank-Byte, dass der Prozessor automatisch vor die Adresse
haengt, wenn dort keins angegeben ist, vorzugeben. Wie gesagt ist es
normalerweise 0 - doch das kann man aendern! Diese 0 naemlich steht im
sogenannten Data Bank Register. Wann immer man mit einer Adresse aus 2 Byte,
egal ob absolut, indiziert oder indirekt, arbeitet, fuegt die SuperCPU vorne
die 0 aus dem Data Bank Register an - der Program-Counter ist schliesslich 3
Byte. Ausnahmen bilden hier der Stack und die Direct Page - die liegen immer
in Bank 0, egal was im Data Bank Register steht. Um nun das Data Bank
Register zu aendern, gibt's die Befehle PHB und PLB. Man geht also immer ueber
den Stack. Um also eine 3 in das Data Bank Register zu bekommen, schreibt
man:


LDA #$03

PHA

PLB


Und schon ist das Data Bank Register = 3. Achtung! Nun bezieht sich jegliche
Standard-Zwei-Byte-Adresse auf Bank 3! Ein INC $2000 zum Beispiel erhoeht nun
das Byte in $032000 ! Durch geschicktes Setzen das Data Bank Registers kann
man die meisten Speicheroperationen auch ohne die langen 24 Bit-Adressen
ausfuehren - aber man kann's auch lassen... wie es einem passt. Manchem
PC-Programmierer laeuft es sicher kalt den Ruecken runter, denn die
Segmentierung des Speichers dort in ebenfalls 64K grosse Bereiche ist manchmal
ein ziemlicher Krampf - und das trotz der zukunftsweisenden
Intel-Technologie. Bei der SuperCPU kann man jedoch je nach Bedarf entweder
direkt auf jede beliebige Speicherstelle zugreifen, oder aber das Data Bank
Register auf die 64K-Bank setzen, auf die man gerade am meisten zugreift -
wenn dies nicht sowieso Bank 0 ist. Nur auf eins muss man achten: Auch ein STA
$D020 bewirkt einen Schreibzugriff nach $03D020, wenn das Data Bank Register
= 3 ist - also nicht wundern, wenn die Rahmenfarbe sich nicht aendert! Das tut
sie dann nur, wenn man mit STA $00D020 angibt, dass es sich um eine Adresse in
Bank 0 handelt - woher soll die CPU das sonst auch wissen. Ausserdem muss man
wissen, dass es nicht fuer alle Befehle eine Long-Adressierung gibt: So kann
man zwar LDA und STA uneingeschraenkt benutzen, ebenso AND und die anderen
Verknuepfungen, ADC und auch SBC, aber z.B. nicht INC oder ROL. Das ist aber
kaum ein Nachteil, denn solche Werte hat man sowieso meist in der Zeropage
oder in Bank 0. Ein anderes Ding ist es, wenn man ganze Programme in einer
anderen Bank als 0 laufenlaesst - fuer die SuperCPU ja kein Problem. Dazu kommen
wir auch noch - spaeter. Listing 2 zeigt ersteinmal den Umgang mit dem Data
Bank Register. Dies traegt uebrigens seinen Namen daher, dass es sich nur auf
Daten bezieht - ein JMP $1000 bezieht sich nach wie vor auf $001000, auch
wenn im Data Bank Register beispielsweise Bank 6 eingetragen ist!


Ueber alle Grenzen?

Eine etwas einfachere Frage ist, ob man ueber die vermeintliche Grenze einer
Bank hinauskommt, wenn man z.B. auf $FFFF mit ,X zugreift und im X-Register
eine 1 oder hoeher steht. Die Antwort lautet: Klar funktioniert das. Denn im
Gegensatz zu anderen Konzepten der Speicheraufteilung ist bei der SuperCPU
die Unterteilung in Baenke wirklich nur dazu da, dem Programmierer das Leben
zu erleichtern. Deshalb braucht man sich bei der Indizierung auch keine
Sorgen zu machen: Ein LDA $02FFFF,X mit X=1 holt logischerweise den Wert aus
$030000. 

So, das soll's fuer diesmal erstmal wieder gewesen sein. Im naechsten Teil
erfahrt Ihr, wie man mit Hilfe der Block-Move-Befehle blitzschnell ganze
Speicherbereiche durch die Gegend transferiert, und als Kroenung gibt's eine
kleine Routine, die eine normale Musik bei $1000 laufen laesst - allerdings bei
$021000...

Im darauffolgenden, letzten Teil unserer SuperCPU-Kurses gibt es dann eine
Komplettuebersicht ueber alle neuen Befehle, ihre Opcodes und die Taktzyklen.



(w) Malte Mundt
©1999 Go64 Redax! & Count Zero/SCS*TRC for all HTML Stuff

[ Zum 7. Teil ][ Zum Index ][ Zum 9. Teil ]