Da man es ja nunmal bei Rechnen öfters mit Zahlen zu tun hat, bietet es sich gelegentlich an, Vergleiche anzustellen. Man schaut sich also zwei Werte an und stellt dann fest, welcher der größere und welcher der kleinere ist, oder auch ob beide gleich sind. Vielleicht auch ob einer größer-gleich oder kleiner-gleich ist.
Ganz wie bei normalen Zahlen macht man das, indem beide voneinander subtrahiert werden.
Es wird also gerechnet
A - B
und dann das Ergebnis angeschaut; folgendes ist dabei möglich
A und B sind gleichgroß - es ergibt sich Null
A ist größer als B - es entsteht ein Ergebnis größer Null
A ist kleiner als B - es entsteht ein Ergebnis kleiner Null
Nun passiert eigentlich nicht anderes, als sonst auch, wenn Zahlen in der CPU besondere Werte annehmen: Es werden entsprechende Flags in der CPU gesetzt.
Am Besten verständlich ist das bei der "gleichgroß" Variante. Es ergibt sich als Subtraktionsergebnis "0", wenn A = B ist.
Folglich wird auch das Zero-Flag gesetzt ! (und das kennt man ja mittlerweile schon)
Das bedeutet auch, wenn man nun das Zero-Flag abfragt, dann kann man Zahlenpaare die gleichgroß sind von ungleichen Zahlenpaaren unterscheiden und unterschiedlich darauf reagieren.
Im Fall des Zero-Flags erhalten die beiden möglichen Zustände den Namen
EQ - wie Equal - wenn A = B
NE - wie Not-Equal - wenn A <> B
( da das so einfach ist, ist diese Bezeichnung auf fast allen CPUs quasi gleich )
Daneben werden noch zwei weitere Flags beeinflußt, beim 6502 nämlich noch das Negativ-Flag und das Carry-Flag. Auf anderen CPUs evtl. auch noch andere.
Das Carry-Flag ist ein bißchen "einfacher": Es bleibt ungesetzt, wenn die Subtraktion kleiner 0 wird, also wenn A < B ist. Es wird dagegen eingeschaltet, wenn beim Subtrahieren >= 0 herauskommt, also A >= B ist.
Dieses kennt dann die beiden Zustände
CS - Carry Set - wenn A >= B
CC - Carry Clear(ed) - wenn A < B
Das Negativ-Flag ist "komplexer": Es schaut darauf, ob ein Wert (virtuell) negativ ist. Das ist eine Konvention, die besagt, daß auf einem Rechner eine Zahl negativ ist, wenn das Bit mit der höchsten Wertigkeit gesetzt ist. In einem 8 Bit Rechner ist das also das Bit Nummer 7 (wenn man bei Bit 0 zu zählen beginnt) (bei einem 32 Bit Rechner wäre es eben das Bit 31). Die Zahl, die entsteht, wenn man bei 8 Bit das höchste Bit setzt, liegt genau in der Mitte der damit darstellbaren Zahlen; das gilt so auch für alle anderen Bitbreiten, wie 32 Bit. Bei 8 Bit ist die Mitte der Wert 128 bzw. $80. Oder anders gesagt: Man zählt links der $00 abwärts, also $FF, $FE, $FD ... bis $80 und stellt sich vor, daß das negative Zahlen sind. In die andere Richtung wird normal hochgezählt $01, $02, $03 ... bis $7F. Das bedeutet natürlich auch, daß man bei diesem Zahlenstrahl NICHT 255 natürliche Zahlen sehen, sondern im Positiven nur noch bis zur Mitte zählen kann, also bis 127 ($7F), die anderen Zahlen (über $80) sind ja als negativ definiert.
Wird nun A - B gerechnet, dann wird das Negativ-Flag immer dann gesetzt, wenn das Ergebnis > $7F ist ( (MI) wie Minus), also größer als die Mitte des Zahlenraums. Und hier dreht man sich dann im Kreis, weil das ja einfach nur bedeutet, das beim Ergebnis der Subtraktion das höchstwertige Bit gesetzt ist. Das Flag wird gelöscht, wenn A - B <= $7F ist ( (PL) wie plus).
Zum Testen reichen normalerweise die beiden ersten Flags gut aus.
Allerdings muß man sie teilweise kombinieren.
Es sind nämlich
A=B wenn das Zero-Flag gesetzt ist (EQ)
A<>B wenn das Zero-Flag gelöscht ist (NE)
A<B wenn das Carry-Flag gelöscht ist (CC)
A>=B wenn das Carry-Flag gesetzt ist (CS)
und
A>B wenn das Carry Flag gesetzt (CS) UND das Zero-Flag gelöscht ist (NE)
sowie
A<=B wenn das Carry Flag gelöscht (CC) ODER das Zero-Flag gesetzt ist (EQ)
Das "Testen" selbst funktioniert so wie in "Flaggen und Abzweige" für das Zero-Flag schon beschrieben.
Man benutzt einen Sprungbefehl (Branch), der entweder auf die gewünschte Aktion springt oder, wenn man auf das gegenteilige Ergebnis testet, eine solche überspringt.
Dabei können auch mehrere solche Sprünge hintereinander kommen, also mehrere "Tests auf Flags" gemacht werden, weil nämlich diese Sprünge selbst i.a. die Flags nicht(!) zusätzlich beeinflussen. Man testet daher mit dem zweiten Sprung die gleichen Flags aus dem gleichen Vergleich.
(Das funktioniert aber nur, wenn zwischen den beiden Sprüngen nicht noch Anweisungen liegen, die die Flags neu setzen.)
Vergleichen lassen sich neben Registern mit Registern, auch Werte aus Adressen mit Registern, oder fix vorgegebene Absolutwerte mit Registern.
Die Schreibweise ist oft so, daß der Befehl selbst den ersten Operanden (also das A) vorgibt und man nur noch den Vergleichswert, dann meist eine Adresse oder einen Absolutwert, angibt.
Bei RISC Prozessoren wird oft ein Register und der Vergleichswert benötigt, manchmal auch extra noch ein Ergebnisregister. Aufgrund ihrer Struktur sind dort Direktvergleiche mit RAM Inhalten i.a. nur nach einem vorherigen Ladebefehl durchführbar.