Assembler-Kurs Teil 7
Bevor wir uns den ROM-Routinen des C64 zuwenden, werden noch die vier
Bit-Verschiebebefehle ASL, LSR, ROL und
ROR erklärt. Diese Befehle benötigen wir
erst im Kursteil 9 bei der Multiplikation und Division von Ganzzahlen.
Trotzdem sollen diese Befehle schon
jetzt behandelt werden, da Sie in der
Folge 9 genug Probleme mit dem
Verständnis der Fließkomma-Zahlen haben
werden und nicht noch zusätzlich mit
neuen Befehlen konfrontiert werden
sollen.
Die Verschiebebefehle
ASL (Arithmetic Shift Left)
Bei diesem Befehl wird der gesamt Akkuinhalt, oder der Inhalt der angegebenen
Speicherstelle bitweise nach links verschoben. Das Bit 7 wird in das Carry-Bit ausgelagert, in Bit 0 des Bytes wird
eine 0 eingefügt.
7 6 5 4 3 2 1 0 Carry <= * * * * * * * * <= 0
Ein einmaliges Linksverschieben entspricht einer Verdoppelung der ursprünglichen Zahl.
Beispiel: LDA #$19 ASL STA $1000
$19 entspricht der binären Bitfolge:
00011001 . Ein ASL führt nun zu 00110010($32) und einer 0 im Carry-Bit. Das
Ergebnis der Verschiebung wird in der
Speicherstelle $1000 abgelegt.
Aber neben der Möglichkeit der Verdoppelung einer Zahl kann man mit ASL
auch bequem die Bits einer Speicherstelle über das Carry-Bit testen. Es werden das Negativund das Zero-Flag
beeinflußt.
Der Befehl ASL bietet folgende
Adressierungsmöglichkeiten:
ASL Akku-orientiert ASL $1000 absolut ASL $1000,X absolut X-indiziert ASL $FA Zeropage-absolut ASL $FA,X Zeropage-abs. X-indiziert
LSR (Logical Shift Right)
LSR bildet das Gegenstück zu ASL. Das
betroffene Bit wird nun nach rechts
geschoben. Dabei gelangt das bit 0 in
das Carry-Bit und in Bit 7 wird eine 0 eingesetzt.
7 6 5 4 3 2 1 0 0 => * * * * * * * * => Carry Beispiel: LDA #$19 LSR STA $1000
Aus der Bitfolge 00011001 wird durch LSR
ein 00001100 . Außerdem enthält das
Carry-Bit jetzt die links aus dem Byte
geschobene 1 . Das Ergebnis wird wieder
in der Speicherstelle $1000 abgelegt.
LSR hat in diesem Fall die dezimale Zahl
25($19) ganzzahlig halbiert. Das
gesetzte Carry-Bit signalisiert dabei, daß ein Rest aufgetreten ist (25 :2=12 Rest 1) .
LSR erlaubt die selben Adressierungsarten und beeinflußt die gleichen
Falggen wie der ASL-Befehl.
ROL (ROtate Left)
Der ROL-Befehl hat große Ähnlichkeit mit
dem ASL, nur daß das Byte jetzt nicht mehr nur verschoben wird, sondern um 1 Bit rotiert. Wie auch bei ASL landet das
Bit 7 im Carry. Das Carry-Bit wird
anschließend in Bit 0 übertragen. Somit
ist das Bit 7 schließlich in Bit 0 gelangt.
7 6 5 4 3 2 1 0 Carry <= * * * * * * * * <= Carry Beispiel: LDA #$B1 ROL STA $1000
In den Akku wird die Bitkombination
10110001 geladen. Nach dem ROL befindet
sich der Wert 01100011($63) im Akku, der in die Speicherstelle $1000 abgelegt
wird. Das Carrybit enthält ebenfalls
eine 1 .
ROR (ROtate Right)
Wie nicht anders zu erwarten war, ist
ROR wieder das Gegenstück zu ROL. Jetzt
wird das Byte nicht um ein Bit nach
links, sondern nach rechts rotiert. Es
befindet sich daher Bit 0 im Carry. Der
Inhalt des Carry-Bits rotiert nun in Bit
7 hinein.
7 6 5 4 3 2 1 0 Carry => * * * * * * * * => Carry Beispiel: LDA #$B1 ROR STA $1000
Auch für ROR wird das Beispiel durchgeführt. Aus 10110001 wird nach ROR die
bitfolge 11011000 . Das Carry-Bit ist
auch in diesem Beispiel gesetzt.
Die zuletzt besprochenen Befehle lassen
dieselben Adressierungsarten wie der
ASL-Befehl zu, und auch sie verändern
die Flaggen N und Z.
ROM-Routinen
Unsere Assembler-Programme stehen immer
im RAM ( Random Access Memory), dem
Lese-/ Schreib-Speicher. In das ROM ( Read
Only Memory) können wir nicht hineinschreiben, es kann nur gelesen werden.
Folglich sind die oben erwähnten ROM-Routinen einige gegebene unterprogramme, die wir in unsern eigenen Assembler-Programmen verwenden können.
Der Sinn der Benutzung dieser ROM-Routinen soll Ihnen am Beispiel des
" Bildschirm löschens" verdeutlicht
werden:
Bisher benötigten wir eine Schleife, die
den gesamten sichtbaren Bildschirmbereich mit dem SPACE-Zeichen "" vollgePOKEd hat. Es war also ein erheblicher
Programmieraufwand erforderlich. Nun
geht das Ganze aber viel kürzer. Wir springen einfach mit JSR ein ROM-Unter- programm an, das das Bildschirmlöschen
für uns übernimmt. Ein " Clear Screen" wird jetzt einfach mit JSR $ E544 ausgeführt.
Übrigens werden alle ROM-Routinen mit
einem JSR angesprungen, da diese
allesamt mit RTS enden.
Einige ROM-Routinen benötigen vor ihrem
Aufruf gewisse Informationen, ohne die
sie nicht fehlerfrei arbeiten können.
Zum Beispiel braucht die Routine zum
Setzen des Cursors die Zeilenposition im
X-Register und die der Spalten im Y-Register.
LDX #$00 LDY #$08 JSR $E50C
Dieses Programm setzt den Cursor in der
Zeile 0 auf die Spalte 8 .
Das folgende Programm gibt den ASCII-Text an der aktuellen Cursorposition aus
LDA #$00 LDY #$C1 JSR $AB1E
Der auszugebende Text für diese Routine
muß im Speicher an der Stelle $ C100 beginnen, und mit einem Byte $00 enden.
Als Zeiger auf diese Textstelle fungieren hierbei der Akku ( niederwertiges
Byte der Adresse) und das Y-Register
( höherwertiges Byte) . Wie Sie einen
ASCII-Text direkt im Speicher ablegen
können, verrät Ihnen das Handbuch Ihres
Assemblers. Oft gibt es dafür einen
Befehl der Art
C100 . ASC " beispieltext" Der Text liegt dann folgendermaßen im Speicher:
C100 42 45 49 53 50 49 45 4C beispiel C108 54 45 58 54 00 00 00 00 text
Eine weitere wichtige Routine ist die
Tastaturabfrage JSR $ FFE4 . Hierbei steht
der ASCII-Code der gedrückten Taste im
Akkumulator.
Das Beispielprogramm C000 JSR $FFE4 C003 BEQ $C000 überprüft, ob irgendeine Taste gedrückt wurde. In BASIC hätten wir 10 GET A$ 20 IF A$ = "" THEN 10 geschrieben.
Natürlich kann ich Ihnen in diesem Kurs
nicht alle verfügbaren ROM-Routinen vorstellen. Wenn ich aber Ihr Interesse
daran geweckt habe, dann sollten Sie
sich ein Buch zulegen, das
" dokumentierte ROM-Listings" enthält.
Aber wo genau liegt eigentlich der ROM-Bereich im Speicher?
Wir haben bis jetzt von $ AB1 E bis $ E50 C
aufgerufen. Bei $ C000-$ CFFF liegt aber
ein RAM-Bereich, den wir schon oft
genutzt haben. Es muß daher mehr als nur
einen ROM-Bereich geben.
In der Tat gibt es 3 unterschiedliche
ROMbereiche. Von $ A000-$ BFFF liegt das
ROM des BASIC-Interpreters. Dieser
Interpreter sorgt dafür, daß Sie gleich
nach dem Einschalten des Computers das
BASIC verfügbar haben.
Zwischen $ D000-$ DFFF befinden sich die
I/ O-Bausteine, die für die Einund
Ausgaben verantwortlich sind.
Ab $ E000 bis zum Ende des Speichers
$ FFFF liegt das Betriebssystem-ROM.
Speicherbelegungsplan des C64 :
$FFFF ------------------------------ |Betriebssystem| RAM | $E000 ---------------------------------- | I/O | Zeichensatz |RAM| $D000 ---------------------------------- | RAM | $C000 ------------------------------ | BASIC-ROM | RAM | $A000 ------------------------------ | | | RAM | | | $0800 ---------------- | (RAM) | $0000 ----------------
Der mit " Zeichensatz" gekennzeichnete
Bereich enthält den Zeichensatz-Generator ( character generator), den ich
im Kursteil 8 mit der Erstellung selbstdefinierter Zeichen näher erläutern
werde.
Wenn Sie den Speicherbelegungsplan
ansehen, stellen Sie fest, daß einige
bereiche mit derselben Adresse mehrfach
belegt sind. So liegt z. B. von $ E000 bis
$ FFFF nicht nur das Betriebssystem," darunter" befindet sich auch noch ein
RAM-Bereich. Ähnlich verhält es sich mit
dem Bereich von $ D000-$ DFFF, der sogar
dreifach belegt ist.
Aber wie kann man zwischen den mehrfach
belegten bereichen auswählen?
Dazu dient die Speicherstelle $01, der
sogenannte Prozessorport. Je nachdem, welcher Wert in dieser Speicherstelle
steht, verändern sich die Zugriffsmöglichkeiten auf den Speicher.
Als Assembler-Programmierer könnten wir
zum Beispiel mit
LDA #$36 STA $01
das gesamte BASIC abschalten un das
darunterliegende RAM für unsere Zwecke
nutzen. Wir hätten somit einen
durchgehenden RAM-Speicher von $0800 bis
$ CFFF geschaffen. Leider können wir aber
nicht mehr auf die ROM-Routinen des
BASIC-Interpreters zugreifen.
LDA #$37 STA $01 stellt den Ausgangszustand wieder her und schaltet das BASIC-ROM an.
$01 $A000-$BFFF $D000-$DFFF $E000-$FFFF
$37 BASIC I/O ROM $36 RAM I/O ROM $35 RAM I/O RAM $34 RAM RAM RAM $33 BASIC Charset ROM $32 RAM Charset ROM $31 RAM Charset RAM $30 RAM RAM RAM
Diese Tabelle des Prozessorports zeigt
Ihnen die Möglichkeiten auf.
Auf den ersten Blick wirkt das mit der
Mehrfachbelegung un dem Umschalten
zwischen Bereichen alles etwas
umständlich. Anders geht es aber nicht.
Mit unserem maximal 2 Byte langem
Adressteil ( z. B. LDA $ FFFF) können wir
nur den Bereich von $0000-$ FFFF, also 64 KByte andressieren. Würde man alle
mehrfach belegten Bereiche
hintereinander schreiben, käme man aber
auf einen Speicherbereich von 64 KByte +24 KByte =88 KByte.
Als praktischen Anschauungsunterricht
laden Sie nun am Besten das Beispielprogramm aus dem Menü: ASSEMBLER-KURS 7 .
(rt/wk)