Magic Disk 64

home to index to text: MD9007-KURSE-ASSEMBLER-KURS_1_TEIL_7.txt

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)

Valid HTML 4.0 Transitional Valid CSS!