Magic Disk 64

home to index to text: MD9005-KURSE-ASSEMBLER-KURS_1_TEIL_5.txt

Assembler-Kurs Teil 5 Das Thema, das wir diesmal behandeln, wird Sie sicherlich nicht in Verzückung geraten lassen, aber es ist leider notwendig: Das Rechnen in ASSEMBLER.
Wie Sie sicher schon ahnen, wird die Sache etwas komplizierter als in BASIC.
Mit einer Zeile, wie C = A + B ist es in ASSEMBLER leider nicht getan. Um diesen Kursteil nicht unnötig zu komplizieren, werden wir uns heute nur mit der Addition und Subtraktion von ganzzahligen Werten ( genannt: Integers) beschäftigen. Dabei kommt man allerdings um die Kenntnis der Flaggen des Statusregisters ( bekannt aus Kursteil 3) nicht herum.
Bevor wir munter addieren und subtrahieren, sollten Sie vielleicht doch erstmal einen Blick auf die dualen Zahlendarstellungen des C64 werfen. Das Verlassen des erlaubten Zahlenbereiches kann einige unschöne Nebeneffekte haben.
Unser Computer kennt die ganzzahlige Werte von -128 bis +127 bei 8- Bit-Zahlen und von -32768 bis +32767 bei 16- Bit-Zahlen. Positive Dualzahlen sind für uns ja kein Problem, aber wie stellt man den negative Zahlen dar?
Das soll an dem Beispiel der Zahl -18 erklärt werden:
Die Zahl +18 wird bekanntlich als 00010010 kodiert. Um die negative Zahl zu erhalten, muß man das Komplement der Zahl bilden ( d. h. die Zahl wird invertiert: aus jeder 0 wird eine 1 und umgekehrt) und +1 dazuaddieren. Das Komplement von +18 ist 11101101 . Nun muß noch +1 dazuaddiert werden und man kommt zu 11101110, was der Zahl -18 entspricht.
Das äußerste rechte Bit ( Bit 7) nennt man das Vorzeichenbit, wobei 0 eine positive und 1 eine negative Zahl kennzeichnet. Diese Darstellungsform, bei der die negativen Zahlen umgewandelt werden, die positiven aber wie gewohnt aussehen, nennt man ZWEIERKOMPLEMENT.

ADC (ADd with Carry)                    

Wenn zwei Zahlen addiert werden, dann muß die eine im Akkumulator stehen, die zweite kann unmittelbar oder als Inhalt einer Speicherstelle gegeben sein. Das Ergebnis der Rechenoperation steht wieder im Akkumulator. Dies gilt auch für die Subtraktion. Das Ergebnis sollte aus dem Akkumulator schnell in eine Speicherstelle geschrieben werden, da es sonst beim weiteren Programmablauf verlorengehen könnte.
Unser neuer Befehl ADC addiert aber nicht nur zwei Zahlen, sondern auch noch den Wert des Carry-Bits ( was uns bei 8- Bit-Additionen gar nicht recht sein kann) . Daher sollte vor dem ADC zuerst der Befehl CLC stehen, mit dem das Carry-Bit gelöscht wird. Nun erhalten wir auf jeden Fall des richtige Ergebnis.
Dualzahlen werden fast wie Dezimalzahlen addiert:

0 + 0 = 0                               
0 + 1 = 1                               
1 + 0 = 1                               
1 + 1 = 0 und zusätzlich enthält hier   
          das Carry-Bit den Übertrag 1, 
          der bei der nächsten Stelle   
          nicht berücksichtigt wird.    

Ein kleines Beispiel:

 CLC                                    
 LDA #$5D        01011101   (Dez. 93)   
 ADC #$0E      + 00001110   (Dez. 14)   
 STA $1500     ----------               
                 01101011   (Dez. 107)  

Das Ergebnis #$6 B (=107) steht jetzt im Akkumulator und in der Speicherstelle $1500 .
Ein weiteres Rechenbeispiel:

  115         01110011                  
 + 14       + 00001110                  
-----        ---------                  
  129         10000001                  

Hier ist offensichtlich etwas schiefgegangen. Das Ergebnis hätte +129 lauten sollen; herausgekommen ist aber 10000001, was der Zahl -127 im Zweierkomplement entspricht. Das diese Rechnung nicht korrekt ist, liegt am Verlassen des erlaubten Zahlenbereiches. Der Computer gibt uns hier zwar keine Fehlermeldung aus, er warnt uns jedoch vor dem Ergebnis, indem er die V-Flagge setzt.
Diese Overfolw-Flagge wird immer dann gesetzt, wenn ein unbeabsichtigter Übertrag in das Vorzeichenbit stattfand.
Die gesetzte N-Flagge ( Vorzeichenflagge) sagt uns, daß das Ergebnis eine negative Zahl ist.
Die V-Flagge wird eigentlich automatisch gesetzt oder gelöscht. Dennoch gibt es den Befehl CLV, mitdem man die V-Flagge auch selbst wieder löschen kann, und somit das Warnsignal unterdrückt.
Bisher wurde nur die Addition von 1- Byte-(8- Bit) Zahlen geschildert.
Die Addition von 2- Byte-(16- Bit) Zahlen wird noch etwas komplizierter, da der Akkumulator nur 8 Bits aufnehmen kann.
Des Rätsels Lösung: Man addiert zunächst nur die niederwertigen Bytes der 16- Bit-Zahlen. Sollte dort ein Übertrag über das 8 . Bit hinaus vorliegen, so gelangt dieser ins Carry-Bit. Nun werden die beiden höherwertigen Bytes addiert, und der Inhalt des Carry-Bits hinzugezählt.
Das Abspeichern der beiden Bytes muß ebenfalls getrennt erfolgen. Erwähnt sei noch, daß bei 16- Bit-Zahlen das Bit 15 das Vorzeichen enthält.
Beispiel für eine 16- Bit-Addition:
$1000/$1001 enthalten die erste Zahl $1100/$1101 enthalten die zweite Zahl $1200/$1201 sollen das Ergebnis enthalten Das Programm dafür sieht folgendermaßen aus:

 CLC                                    
 LDA $1000                              
 ADC $1100  ; Addition des niederwerigen
 STA $1200    Bytes                     
 LDA $1001                              
 ADC $1101  ; Addition des höherwertigen
 STA $1201    Bytes ohne CLC            
SBC (SuBtract with Carry)               

Dieser Befehl, wer hätte es gedacht, subtrahiert zwei Zahlen voneinander.
Das Dumme ist nur: Unser Prozessor kann überhaupt nicht subtrahieren, er kann nur addieren! Um dennoch Zahlen voneinander abziehen zu können, wendet er einen Trick an. Eine der beiden Zahlen wird einfach zu einer negativen Zahl gemacht und dann werden beide Zahlen addiert. Diese Uwandlung nimmt uns der Befehl SBC jedoch schon ab. Es wird zu dem ersten Operanden nicht nur das Zweierkomplement der zweiten Zahl, sondern auch noch das Komplement des Carry-Bits addiert. D. h. wenn das Carry-Bit das Ergebnis bei der Subtraktion nicht verfälschen soll, muß es zuvor gesetzt sein. Dazu dient der Befehl SEC ( SEt Carry), der vor jedem SBC stehen sollte.
Ein Beispiel:

 SEC                                    
 LDA #$7D                               
 SBC #$0A                               
 STA $1500                              

Per Hand sieht die Rechnung so aus:

 Dezimal              Binär             
   125               01111101           
 -  10            +  11110110           
 -------          -----------           
   115           (1) 01110011           

Das Ergebnis $73(115) steht im Akku und in der Speicherstelle $1500 .
Wie Sie sehen, erhalten wir das richtige Ergebnis. Das Vorzeichen der Zahl ist positiv, da die N-Flagge nicht gesetzt ist. Das gesetzte "9 . Bit" steht im Carry und wird bei der 8- Bit-Subtraktion nicht benötigt. Auch bei der Subtraktion signalisiert die V-Flagge ein ubeabsichtigtes Verlassen des Zahlenbereichs.
Der SBC-Befehl hat also große Ähnlichkeit mit dem ADC, und so ist es nicht verwunderlich, daß eine 16- Bit-Subtrak- tion einer 16- Bit-Addition auch sehr verwandt ist.
Beispiel für eine 16- Bit-Subtraktion:
$1000/$1001 enthalten die erste Zahl $1100/$1101 enthalten die zweite Zahl $1200/$1201 sollen das Ergebnis enthalten Das Programm sieht folgendermaßen aus:

 SEC                                    
 LDA $1000                              
 SBC $1100  ; Subtraktion der           
 STA $1200    niederwertigen Bytes      
 LDA $1001                              
 SBC $1101  ; Subtraktion der höher-    
 STA $1201    wertigen Bytes ohne SEC   

Abschließend möchte ich noch zeigen, daß es dem Programmierer selbst überlassen bleibt, ob er die Zahlen wirklich als vorzeichenbehaftet ansieht, wie es eigentlich vorgesehen ist, oder ob er die Zahlen als vorzeichenlos betrachtet.
Dazu ein Beispiel:

 Dezimal                Binär           
   -6                 11111010          
  + 2               + 00000010          
 ----               ----------          
   -4                 11111100          

Das Ergebnis ist bei vorzeichenbehafteten Zahlen richtig, da -6($ FA) und -4($ FC) im Zweierkomplement gegeben sind.
Nun vergessen Sie mal das Zweierkomplement und betrachten Sie die Zahlen als vorzeichenlos. Dann hätten wir $ FA +$02=$ FC ( also dezimal 250+2=252) gerechnet. Auch dieses Ergebnis ist korrekt. Dieses Beispiel zeigt, daß es am Programmierer liegt, welches der beiden Ergebnisse er beabsichtigt.

BCD-Darstellung (Binary Coded Decimals) 

Da die Befehle ADC und SBC sowohl im Binär-, als auch im Dezimalmodus arbeiten, muß es wohl Befehle geben, die zwischen den beiden Modi umschalten.
Wenn es nicht vom Programm geändert wurde, ist automatisch der Binärmodus angeschaltet.
CLD: schaltet den Binärmodus an SED: schlaten auf Dezimalmodus um Bei deisen " binärkodierten" Dezimalzahlen gibt es nur die Ziffern 0 bis 9 . Es wird also jede Dezimalstelle für sich getrennt kodiert. Um diese 10 Ziffern kodieren zu können, benötigt man 4 Bits, mit denen bis zu 16 Kombinationen möglich wären. Sechs der Kombinationsmöglichkeiten bleiben daher ungenutzt. Die Dezimalzahl 0 wird als 0000, die 9 als 1001 kodiert. Die BCD-Dar- stellung der Zahl 128 lautet z. B. :

 0001   0010   1000       binär         
  1      2      8         dezimal       

Da jede Ziffer 4 Bits in Anspruch nimmt, fasst man je zwei BCD-Ziffern in einem Byte zusammen. Die Zahl 128 liegt folgendermaßen imnm SPeicher:0000000100101000 . Die BCD-Zahlen seien hier jedoch nur am Rande erwähnt, da Sie nur sehr selten verwendet werden. Rechnen werden wir nicht mit diesen Zahlen.
Das richtige Verständnis für die diesmal erlernten Befehle werden Sie erst durch eigenes Ausprobieren erhalten. Also nichts wie hingesetzt und losprogrammiert. Auch diesmal gibt es selbstverständlich wieder ein Begleitprogramm zu dem Kurs auf Diskette. Es nennt sich " ASSEMBLER-KURS 5" und enthält neben einer Joystickabfrage in ASSEMBLER auch noch einige nützliche Anwendungen der neuen Befehle.

Zusammenfassung der Befehle:            
---------------------------             
ADC (ADd with Carry)                    

Zwei Zahlen werden zusammen mit dem Inhalt des Carry-Bits addiert. Das Ergebnis steht wieder im Akkumulator.
Dieser Befehl gilt sowohl für die binäre, als auch für die dezimale ( BDC) Addition. Der ADC-Befehl kann die Flaggen N, V, Z und C beeinflussen.

SBC (SuBtract with Carry)               

Zwei Zahlen werden subtrahiert, indem das Zweierkomplement der zweiten Zahl zu der ersten dazuaddiert wird. Das Ergebis der Operation steht im Akkumulator. Auch SBC kann sowohl im Binär-, als auch im Dezimalmodus arbeiten.

CLC (CLear Carry)                       

Löscht die Übertragungsflagge. Dieser Befehl sollte immer vor einem ADC benutzt werden.

SEC (SEt Carry)                         

Setzt die Übertragsflagge. SEC sollte vor jedem SBC stehen.

CLD (CLear Decimal mode)                

Löscht die Dezimalflagge und schaltet somit den Binärmodus ein.

SED (SEt Decimal mode)                  

Setzt die Dezimalflagge auf 1 . Dadurch werden alle Rechenoperationen im Dezimalmodus ausgeführt.

CLV (CLear oVerflow flag)               

Löscht die Überlaufflagge.

                     (Ralf Trabhardt/wk)

Valid HTML 4.0 Transitional Valid CSS!