Die uns geläufige Methode, negative (und positive) Zahlen darzustellen, trennt jede Zahl in ihren Betrag und in ein Vorzeichen. Die Real: NullNull spielt eine Sonder-Rolle, da sie weder negativ noch positiv sein kann.
Diese Methode liesse sich auch Adressierungsarten der Z80: Relativrelativ schnell für die Speichung von Zahlen in einem Computer umsetzen, weil das Vorzeichen nur zwischen zwei Zuständen unterscheiden kann und somit in einem Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit darzustellen ist.
Diese Methode begünstigt Rechnen im Binärsystem: MultiplikationMultiplikation und Rechnen im Binärsystem: DivisionDivision, erschwert aber etwas die Rechnen im Binärsystem: AdditionAddition und Rechnen im Binärsystem: SubtraktionSubtraktion. Der Grund ist, dass man bei den Punkt-Rechenarten sowieso Vorzeichen und Betrag trennen muss, bei den Strich-Rechenarten aber nicht!
Da die meisten 8-Bit-Mikroprozessoren, wie auch Anhang: Die Z80die Z80, aber weder multiplizieren noch dividieren können, hat man in der Informatik eine Darstellungsweise für negative Zahlen eingeführt, die die Strich-Rechenarten bevorzugt: Das 'n-1-Komplement'.
Da der Computer binär rechnet und auch das Vorzeichen ein Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit beansprucht, ist es wahrscheinlich am besten, das 'n-1-Komplement' auch gleich im Binärsystem zu untersuchen.
Was ergäbe (11011)2 um Eins erniedrigt? Das ist bestimmt auch für notorisch dem Dezimal-System verhaftete Leser nicht schwer zu entscheiden:
11011
- 1
------
11010
Bei (11000) minus Eins wird es schon schwieriger, weil hier ein Übertrag auftaucht:
11000
- 1
------
10111
Was passiert aber, wenn man von Real: NullNull noch Eins abzieht, ohne hier das negative Vorzeichen einzuführen? Man erhält einen Übertrag bis in alle Ewigkeit:
0000
- 1
----------
...11111111
Wenn man jetzt aber von einer endlichen Register-Breite in der Die ICs im Überblick: Die CPU Z80 Das Innenleben der CPC-Rechner: Die CPU Z80 Die Anschlussbelegungen der wichtigsten ICs im CPC: Die CPU Z80CPU ausgeht, so wird der Übertrag irgendwann nicht mehr weiter berücksichtigt. Allenfalls wird er noch in einem Die Z80: Wirkung der Z80-Befehle auf die FlagsFlag angemerkt. Für -1 erhält man aber eine Darstellung, bei der alle Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bits gesetzt sind, also eine Binärzahl mit lauter Einsen.
Bei einem 8 Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit breiten Die Tonausgabe: Das Kontrollregister (Reg. 7) Die Tonausgabe: Die möglichen Hüllkurvenformen (Reg. 13)Register, wie zum Beispiel der Akku, entspricht (11111111)2 der negativen Zahl (-1)2. (11111111)2 ist das sogenannte 'n-1-Komplement'.
Woher kommt diese Bezeichnung? Nun, man bildet das 'n-Komplement' von der nächst-kleineren Zahl:
n-1-Komplement von 00000001
= n-Komplement von (00000001 - 1) = 00000000
= 11111111 (0 mit 1 mit 0 vertauschen)
Zum Beispiel das (n-1-) Komplement von 15 = (00001111)2:
15 = 00001111 - 1 = 00001110
-15 = 11110001
Das Kennzeichen, ob es sich um eine positive oder um eine negative Zahl in Komplement-Darstellung handelt, ist das oberste Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit: Ist es Real: NullNull, ist die Zahl positiv. Ist es Eins, so ist es eine negative Zahl. Das ist aber ausschließlich von der Interpretation des Betrachters abhängig. Es könnte genausogut eine besonders große, positive Zahl sein! Zahlen mit gesetztem oberstem Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit sind doppeldeutig!
Normalerweise werden Datentypen: Bytes Datenbreite: BytesBytes (8-Bit-Zahlen) nur als positive Zahlen interpretiert. Dann sind damit Zahlen von (00000000)2 = (0)10 bis (11111111)2 = (255)10 darstellbar.
Man kann sie aber auch als Zahlen in Komplementär-Schreibweise auffassen:
Die größte Zahl ist dann (01111111)2 = (127)10, die kleinste ist (10000000)2 = (-128)10.
(10000000)2 ist die kleinste, mit 8 Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit in Komplementär-Schreibweise darstellbare Zahl. Noch einmal erniedrigt kaeme es zu einem Übertrag durch alle Stellen, der das oberste Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit auf Real: NullNull setzen würde, was dann aber laut Definition eine positive (und zwar die größte) sein soll:
10000000
- 1
---------
01111111
Benutzt man für negative Zahlen immer die Komplement-Darstellung, so kann man ohne zusätzlichen Aufwand addieren und subtrahieren. Der Stetigkeits-Sprung beim Null-Durchgang (der bei der Darstellung mit Betrag und Vorzeichen auftritt), ist nicht mehr vorhanden!
Sollen zwei Zahlen addiert werden, so kann man sie mit Hilfe der in der Die ICs im Überblick: Die CPU Z80 Das Innenleben der CPC-Rechner: Die CPU Z80 Die Anschlussbelegungen der wichtigsten ICs im CPC: Die CPU Z80Z80 realisierten Voll-Addier-Schaltung addieren, ohne vorher Vorzeichen-Untersuchungen machen zu müssen.
Soll eine Zahl von einer anderen abgezogen werden, so wird der Minuend komplementiert und die beiden Zahlen dann addiert. Das geht bei jeder Die ICs im Überblick: Die CPU Z80 Das Innenleben der CPC-Rechner: Die CPU Z80 Die Anschlussbelegungen der wichtigsten ICs im CPC: Die CPU Z80CPU ebenfalls rein Hardware-mäßig. Auch so 'komplizierte' Sachen, wie beispielsweise zwei negative Zahlen voneinander abziehen, gehen so ganz einfach:
-10 - (-20) = +10
Umwandeln der Dezimalzahlen in binäre komplementäre Schreibweise:
---> (10)10 = (00001010)2 = n ---> n-1 = (00001001)2 ---> CPL = 11110110 = -10
(20)10 = (00010100)2 = n ---> n-1 = (00010011)2 ---> CPL = 11101100 = -20
Nun rechnen:
-20 wird abgezogen. Also komplementieren:
(11101100)2 = n ---> n-1 = (11101011)2 ---> CPL = 00010100 = +20
und dann addieren: 11110110 = -10
+ 00010100 = +20
----------------
100001010
Holla, was ist da passiert? Ein Übertrag über die achte Stelle fällt weg, es ergibt sich:
(00001010)2
und das ist, zurück in's dezimale gewandelt, +10.
Soweit ist die Komplement-Darstellung nun hoffentlich klar. Im Folgenden nur noch ein paar Queues als verkettete Liste: Anmerkung:Anmerkungen zum Umgang der Die ICs im Überblick: Die CPU Z80 Das Innenleben der CPC-Rechner: Die CPU Z80 Die Anschlussbelegungen der wichtigsten ICs im CPC: Die CPU Z80Z80 mit Komplement-Zahlen:
Die meisten Rechenbefehle der Die ICs im Überblick: Die CPU Z80 Das Innenleben der CPC-Rechner: Die CPU Z80 Die Anschlussbelegungen der wichtigsten ICs im CPC: Die CPU Z80Z80 setzen das Carry- und das Overflow-Flag entsprechend einem Überlauf bei der Die Fließkomma-Routinen: OperationenOperation. Im AnhangAnhang gibt es dazu eine Tabelle, in der die Z80-Befehle mit ihrer Wirkung auf die Die Z80: Wirkung der Z80-Befehle auf die FlagsFlags aufgelistet sind.
Anhang: Die Z80Die Z80 kennt also zwei Sorten 'Überlauf':
Das Carry-Flag (C/NC) signalisiert einen Überlauf, wenn die Zahlen als vorzeichenlos angesehen werden. Also: Datentypen: Bytes Datenbreite: BytesBytes von 0 bis 255 und Datenbreite: WordsWords von 0 bis 65535.
Das Overflow-Flag (PE/PO), das mit dem Paritäts-Flag kombiniert ist, liefert Information darüber, ob ein Überlauf stattfand, wenn die Zahlen als Vorzeichen-behaftet aufgefasst werden. Also: Datentypen: Bytes Datenbreite: BytesBytes von -128 bis +127 und Datenbreite: WordsWords von -32768 bis +32767. Dabei bedeutet PE = Überlauf.
Der Z80-Befehl CPL bildet das n-Komplement des Akkus. Er vertauscht also alle Real: NullNullen mit Einsen und umgekehrt. Betrachtet man die komplementierte Zahl als nur positiv (0 bis 255), so wird folgende Rechnung durchgeführt: Operationen: BD5B / 349A / 349A: FLO SUBA := 255-Operationen: BD5B / 349A / 349A: FLO SUBA. Bei Komplement-Darstellung: Operationen: BD5B / 349A / 349A: FLO SUBA := -1-Operationen: BD5B / 349A / 349A: FLO SUBA.
Demgegenüber bildet NEG das 'eigentliche' n-1-Komplement. Bei nur positiver Darstellung ist die durchgeführte Die Fließkomma-Routinen: OperationenOperation: Operationen: BD5B / 349A / 349A: FLO SUBA := 256-Operationen: BD5B / 349A / 349A: FLO SUBA. Bei komplementärer Interpretation: Operationen: BD5B / 349A / 349A: FLO SUBA := -Operationen: BD5B / 349A / 349A: FLO SUBA.
Muss ein Datentypen: Bytes Datenbreite: BytesByte in Komplement-Darstellung auf ein Datenbreite: WordsWord ausgeweitet werden, so muss man das oberste Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bit des Datentypen: Bytes Datenbreite: BytesBytes in alle Datenbreite: Bits Port B - Input: &F5xx: Bit 0: Port B - Input: &F5xx: Bit 4: Port B - Input: &F5xx: Bit 5: Port B - Input: &F5xx: Bit 6: Port B - Input: &F5xx: Bit 7: Port C - Output: &F6xx: Bit 4: Port C - Output: &F6xx: Bit 5:Bits des neu zu schaffenden High-Bytes kopieren:
positive Zahl: negative Zahl:
01101011 = Datentypen: Bytes Datenbreite: BytesByte 10100010 = Datentypen: Bytes Datenbreite: BytesByte
00000000.01101011 = Datenbreite: WordsWord 11111111.10100010 = Datenbreite: WordsWord
Liegt das Datentypen: Bytes Datenbreite: BytesByte in Operationen: BD5B / 349A / 349A: FLO SUBA vor, und soll dieses Die Tonausgabe: Das Kontrollregister (Reg. 7) Die Tonausgabe: Die möglichen Hüllkurvenformen (Reg. 13)Register vorzeichenrichtig gestreckt nach HL transportiert werden, so kann man folgende Routine benutzen:
; Operationen: BD5B / 349A / 349A: FLO SUBA ---> HL (Vorzeichenrichtig)
;
LD L,Operationen: BD5B / 349A / 349A: FLO SUBA ; niederwertiges Datentypen: Bytes Datenbreite: BytesByte L := Operationen: BD5B / 349A / 349A: FLO SUBA
ADD Operationen: BD5B / 349A / 349A: FLO SUBA,Operationen: BD5B / 349A / 349A: FLO SUBA ; Vorzeichenbit in's CY-Flag schieben
SBC Operationen: BD5B / 349A / 349A: FLO SUBA,Operationen: BD5B / 349A / 349A: FLO SUBA ; A-A gibt 0 wenn CY=0 sonst -1 = (11111111)2
LD H,Operationen: BD5B / 349A / 349A: FLO SUBA ; das ist der Wert für's höherwertige Datentypen: Bytes Datenbreite: BytesByte
|