Bedingten Sprüngen geht nahezu immer ein logischer Vergleich zweier Größen (eine Prüfung einer Bedingung) voraus, wie schon das Wort bedingt impliziert. Von großer Bedeutung in diesem Zusammenhang ist das Flag-Register, da bestimmte Flags in Abhängigkeit vom Ergebnis des Vergleichs gesetzt (Flag gleich 1) oder gelöscht (Flag gleich 0) werden. Auch setzen und löschen manche Befehle bestimmte Flags. Bei den 16-Bit Prozessoren waren nur die unteren 16 der folgenden 32 Bit vorhanden, deswegen wird dieses Register auch EFlags genannt.
Im folgenden eine Beschreibung der einzelnen Flags des i386.
[Da bestimmte Flags in dieser Arbeit keine Bedeutung haben, werde ich diese (IP, VIP, VIF, AC,VM) nicht erklären]
Carry (Übertrag; ab 8086)
Carry wird gesetzt, wenn ein Vorgang einen Übertrag für den Zieloperanden erzeugt. Dies ist beispielsweise der Fall, wenn bei einer 32-Bit Addition die Summe zweier 32-Bit-Zahlen ein Ergebnis größer als 4gByte-1 erzeugt. Carry kann durch den Befehl STC (Set Carry) gesetzt, durch CLC (Clear Carry) gelöscht und durch CMC (Complement Carry) komplementiert werden.
Parity (Parität; ab 8086)
Parity wird gesetzt, falls das Ergebnis der Operation eine gerade Zahl von gesetzten Bits aufweist. Parity wird vom Prozessor gesetzt.
Auxiliary Carry (zusätzlicher Übertrag; ab 8086)
Das Flag wird für Arithmetik mit BCD-Zahlen verwendet und wird gesetzt, wenn eine Operation einen Übertrag oder ein Borrow für die unteren vier Bits (BCD-Zahlen belegen nur die unteren vier Bits eines Byte) eines Operanden erzeugt.
Zero (Null; ab 8086)
Zero wird vom Prozessor gesetzt, falls das Ergebnis einer Operation Null ergibt. Ein Beispiel liefert die Subtraktion gleich großer Zahlen oder das bitweise logische AND eines Wertes mit Null.
Sign (Vorzeichen; ab 8086)
Sign ist gleich dem höchstwertigen Bit des Operationsergebnisses (0=positiv, 1=negativ) und hat damit nur einen Sinn für vorzeichenbehaftete Zahlen. Ist die Differenz zweier Zahlen negativ, so wird Sign vom Prozessor auf eins gesetzt. Damit können beispielsweise zwei Zahlen miteinander verglichen werden.
Trap (Einzelschritt; ab 8086)
Ist Trap gesetzt, so erzeugt der Prozessor nach jedem Schritt einen Interrupt 1. Trap gehört also zur Klasse der Exceptions. Viele Debug-Programme setzen Trap und fangen den Interrupt ab, um ein Programm schrittweise auszuführen.
Interrupt Enable (Interrupt erlauben; ab 8086)
Ist Interrupt Enable gesetzt, so akzeptiert der Prozessor Hardware-Interrupts. Dieses Flag kann explizit mit CLI gelöscht und mit STI gesetzt werden. Interrupts müssen bei Anwendungen gesperrt werden, die keine Unterbrechung erlauben. Eine zu lange Sperrung kann jedoch zu Problemen bei Echtzeitanwendungen führen. Normalerweise sollte nur das Betriebssystem dieses Flag verändern.
Direction (Richtung; ab 8086)
Direction bestimmt die Richtung von String-Operationen (z.B. MOVS). Ist Direction gesetzt, so werden die Zeichenketten von hoher zu niedriger Adresse bearbeitet, ansonsten von niedriger zu hoher Adresse. Das Direction-Flag kann mit STD gesetzt und mit CLD gelöscht werden.
Overflow (Überlauf; ab 8086)
Overflow wird vom Prozessor gesetzt, falls das Ergebnis einer Operation für den Zieloperanden zu groß oder zu klein ist. Beispielsweise kann die Addition zweier 16-Bit-Zahlen zu einem Wert führen, der nicht mehr in ein 16-Bit-Register paßt.
Die bisher beschriebenen Register waren bereits auf dem 8086 vorhanden, die folgenden sind mit dem 80286 dazugekommen, um den Protected Mode zu unterstützen und einen Schutz für den I/O-Adreßbereich zu implementieren.
I/O-Protection-Level (I/O-Schutzebene; ab 80286)
Dieses 2-Bit Flag gibt im Protected Mode die minimal benötigte Schutzebene für Ein- und Ausgabeoperationen für den I/O-Adreßraum an und wird vom Betriebssystem verwaltet. Im Real Mode hat das Flag keine Bedeutung.
Nested Task (verschachtelter Task; ab 80286)
Nested Task dient im Protected Mode zur Überwachung der Verkettung unterbrochener und aufgerufener Tasks und wird vom Betriebssystem verwaltet. Ein gesetztes NT-Flag zeigt an, daß mindestens ein Task-Switch aufgetreten ist und sich im Speicher ein inaktives Task-State-Segment befindet.
Beim i386 sind im Flag-Register noch zwei Einträge hinzugekommen, die einerseits die neu implementierte Debug-Unterstützung, andererseits den innovativen Virtual 8086 Mode betreffen (die jedoch beide für diese Arbeit nicht von all zu großer Bedeutung sind. Ich will sie nur der Vollständigkeit halber erwähnen).
Resume (Wiederanlauf; ab i386)
Das Resume-Flag steuert den Wiederanlauf eines Tasks nach einer Breakpoint-Unterbrechung über die Debug-Register des i386. Ist Resume gesetzt, so werden die Breakpoints temporär deaktiviert. Das bedeutet, daß die Programmausführung an der Unterbrechungsstelle wiederaufgenommen werden kann, ohne daß eine erneute Debug-Exception auftritt.
Virtual 8086 Mode (virtueller 8086-Modus; ab i386)
Um den i386 in den Virtual 8086 Mode umzuschalten muß das Betriebssystem das VM-Flag setzen. Das ist nur im Protected Mode und hier nur über ein Gate möglich. Ist das VM-Flag gesetzt, so arbeitet der Prozessor im Virtual 8086 Mode. Er führt dann die vom 8086 her bekannte einfache Real-Mode-Adreßberechnung aus und kann dadurch Real-Mode-Anwendungen ausführen. Das alles geschieht aber im Gegensatz zum Real Mode in einer geschützten Umgebung. Ist das VM-Flag dagegen gelöscht, so arbeitet der i386 im gewöhnlichen Protected Mode. Im Real Mode hat das Flag keine Bedeutung.
Nahezu alle Befehle zu bedingten Sprüngen testen die Werte des Flags, das das Ergebnis des vorherigen Vergleichs widerspiegelt. Das macht die besondere Bedeutung des Flag-Registers aus.
Beispiel: Ist der Wert des eax-Registers gleich 5 so soll zu Marke1 verzweigt werden:
CMP eax, 5 ;Register eax mit dem Wert 5 vergleichen
JE Marke1 ;Sprung zu Marke1, wenn der letzte Vergleich Gleichheit ergeben hat
Der i386 führt den Vergleich CMP eax, 5 aus, indem er den Wert 5 von eax subtrahiert und die Flags entsprechend setzt. In unserem Beispiel wird daher 5 vom Wert des Registers eax subtrahiert. Ist eax gleich 5, so wird das Zero-Flag gesetzt. Ist eax größer 5, so setzt der Prozessor die Flags Sign und Zero auf 0. Ist eax kleiner als 5, so wird Zero auf 0 und Sign auf 1 gesetzt.
Manche Befehle (wie zum Beispiel JBE = Jump if Below or Equal) testen mehrere Flags (hier: Sign und Zero) um zu ermitteln, ob die Sprungbedingung erfüllt ist oder nicht.
|