Das Schneider CPC Systembuch

Grundlagen

Andere Zahlensysteme

Komplement-Darstellung negativer Zahlen

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 Z80
CPU
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: Bytes
Bytes
(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 Z80
Z80
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 Z80
CPU
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 Z80
Z80
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 Z80
Z80
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: Bytes
Bytes
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: Bytes
Bytes
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: Bytes
Byte
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: Bytes
Bytes
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: Bytes
Byte
10100010 = Datentypen: Bytes
Datenbreite: Bytes
Byte
00000000.01101011 = Datenbreite: WordsWord 11111111.10100010 = Datenbreite: WordsWord

Liegt das Datentypen: Bytes
Datenbreite: Bytes
Byte
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: Bytes
Byte
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: Bytes
Byte

Valid HTML   Valid CSS