Dieser ArtikelBenutzerSuche |
AVR-Tutorial: VergleicheVergleiche und Entscheidungen sind in jeder Programmiersprache ein zentrales Mittel um den Programmfluss abhängig von Bedingungen zu kontrollieren. In einem AVR spielen dazu 3 Komponenten zusammen:
Der Zusammenhang ist dabei folgender: Die Vergleichsbefehle führen einen Vergleich durch, zum Beispiel zwischen zwei Registern oder zwischen einem Register und einer Konstante. Das Ergebnis des Vergleiches wird in den Flags abgelegt. Die bedingten Sprungbefehle werten die Flags aus und führen bei einem positiven Ergebnis den Sprung aus. Besonders der erste Satzteil ist wichtig! Den bedingten Sprungbefehlen ist es nämlich völlig egal, ob die Flags über Vergleichsbefehle oder über sonstige Befehle gesetzt wurden. Die Sprungbefehle werten einfach nur die Flags aus, wie auch immer diese zu ihrem Zustand kommen. [bearbeiten] FlagsDie Flags residieren im Statusregister SREG. Ihre Aufgabe ist es, das Auftreten bestimmter Ereignisse, die während Berechnungen eintreten können festzuhalten. +---+---+---+---+---+---+---+---+ | I | T | H | S | V | N | Z | C | +---+---+---+---+---+---+---+---+ [bearbeiten] Carry (C)Das Carry Flag zeigt an, ob ein Überlauf oder Unterlauf bei einer 8-Bit Berechnung statt gefunden hat (Addition, Subtraktion). Ebenso ist es ein Zwischenspeicher bei Schiebe- und Rotationsoperationen. [bearbeiten] Zero (Z)Das Zero Flag hält fest, ob das Ergebnis der letzten 8-Bit Berechnung 0 war oder nicht. [bearbeiten] Negative (N)Spiegelt den Zustand des höchstwertigen Bits der letzten 8-Bit Berechnung wieder. In 2-Komplement Arithmetik bedeutet ein gesetztes 7. Bit eine negative Zahl, daher der Name. [bearbeiten] Overflow (V)Dieses Bit wird gesetzt, wenn bei einer Berechnung mit 2-Komplement Arithmetik ein Überlauf (Unterlauf) stattgefunden hat. Dies entspricht einem Überlauf von Bit 6 ins Bit 7 [bearbeiten] Signed (S)Das Signed Bit ist eine Verknüpfung aus dem N und dem V Flag. Es wird hauptsächlich für 'Signed' Tests benötigt. Daher auch der Name. [bearbeiten] Half Carry (H)Das Half Carry Flag hat die gleiche Aufgabe wie das Carry Flag, nur beschäftigt es sich mit einem Überlauf von Bit 3 nach Bit 4. Das Haupteinsatzgebiet ist der Bereich der BCD Arithmetik. [bearbeiten] Transfer (T)Das T-Flag wird von keiner Berechnung gesetzt, sondern steht zur ausschliesslichen Verwendung des Programmierers zur Verfügung. Damit können Bits von einer Stelle schnell an eine andere kopiert oder getestet werden. [bearbeiten] Interrupt (I)Das Interrupt Flag hat ebenfalls nichts mit Vergleichen zu tun, sondern steuert ob Interrupts systemweit zugelassen sind (siehe AVR-Tutorial: Interrupts). [bearbeiten] VergleicheUm einen Vergleich durchzuführen, wird intern eine Subtraktion der beiden Operanden durchgeführt. Das eigentliche Ergebnis der Subtraktion wird allerdings verworfen, es bleibt nur die neue Belegung der Flags übrig, die in weiterer Folge ausgewertet werden kann [bearbeiten] CP - CompareVergleicht den Inhalt zweier Register miteinander. Prozessorintern wird dabei eine Subtraktion der beiden Register durchgeführt. Das eigentliche Subtraktionsergebnis wird allerdings verworfen, das Subtraktionsergebnis beeinflusst lediglich die Flags. [bearbeiten] CPC - Compare with CarryVergleicht den Inhalt zweier Register, wobei das Carry Flag in den Vergleich mit einbezogen wird. Dieser Befehl wird für Arithmetik mit grossen Variablen (16/32 Bit) benötigt. Siehe AVR-Tutorial: Arithmetik. [bearbeiten] CPI - Compare ImmediateVergleicht den Inhalt eines Registers mit einer direkt angegebenen Konstanten. Der Befehl ist nur auf die Register r16..r31 anwendbar. [bearbeiten] Bedingte SprüngeDie bedingten Sprünge werten immer bestimmte Flags im Statusregister SREG aus. Es spielt dabei keine Rolle, ob dies nach einem Vergleichsbefehl oder einem sonstigen Befehl gemacht wird. Entscheidend ist einzig und alleine der Zustand des abgefragten Flags. Die Namen der Sprungbefehle wurden allerdings so gewählt, daß sich im Befehlsnamen die Beziehung der Operanden direkt nach einem Compare Befehl wiederspiegelt. Zu beachten ist auch, daß die Flags nicht nur durch Vergleichsbefehle verändert werden, sondern auch durch arithmetische Operationen, Schiebebefehle und logische Verknüpfungen. Da dieses Information wichtig ist, ist auch in der bei Atmel erhältlichen Übersicht über alle Assemblerbefehle bei jedem Befehl angegeben, ob und wie er Flags beeinflusst. Ebenso ist dort eine kompakte Übersicht aller bedingten Sprünge zu finden. Beachten muss man jedoch, dass die bedingten Sprünge maximal 64 Worte weit springen können. [bearbeiten] Bedingte Sprünge für vorzeichenlose Zahlen[bearbeiten] BRSH - Branch if Same or HigherDer Sprung wird durchgeführt, wenn das Carry Flag (C) nicht gesetzt ist. Wird dieser Branch direkt nach einer CP, CPI, SUB oder SUBI Operation eingesetzt, so findet der Sprung dann statt, wenn der erste Operand größer oder gleich dem zweiten Operanden ist. [bearbeiten] BRLO - Branch if LowerDer Sprung wird durchgeführt, wenn das Carry Flag (C) gesetzt ist. Wird dieser Branch direkt nach einer CP, CPI, SUB oder SUBI Operation eingesetzt, so findet der Sprung dann statt, wenn der erste Operand kleiner dem zweiten Operanden ist. [bearbeiten] Bedingte Sprünge für vorzeichenbehaftete Zahlen[bearbeiten] BRGE - Branch if Greater or EqualDer Sprung wird durchgeführt, wenn das Signed Flag (S) nicht gesetzt ist. Wird dieser Branch direkt nach einer CP, CPI, SUB oder SUBI eingesetzt, so findet der Sprung dann und nur dann statt, wenn der zweite Operand größer oder gleich dem ersten Operanden ist. [bearbeiten] BRLT - Branch if Less ThanDer Sprung wird durchgeführt, wenn das Signed Flag (S) gesetzt ist. Wird dieser Branch direkt nach einer CP, CPI, SUB oder SUBI Operation eingesetzt, so findet der Sprung dann und nur dann statt, wenn der zweite Operand kleiner als der erste Operand ist. [bearbeiten] BRMI - Branch if MinusDer Sprung wird durchgeführt, wenn das Negativ Flag (N) gesetzt ist, das Ergbnis der letzen Operation also negativ war. [bearbeiten] BRPL - Branch if PlusDer Sprung wird durchgeführt, wenn das Negativ Flag (N) nicht gesetzt ist, das Ergbnis der letzen Operation also positiv war (einschiesslich Null). [bearbeiten] Sonstige bedingte Sprünge[bearbeiten] BREQ - Branch if EqualDer Sprung wird durchgeführt, wenn das Zero Flag (Z) gesetzt ist. Ist nach einem Vergleich das Zero Flag gesetzt, lieferte die interne Subtraktion also 0, so waren beide Operanden gleich. [bearbeiten] BRNE - Branch if Not EqualDer Sprung wird durchgeführt, wenn das Zero Flag (Z) nicht gesetzt ist. Ist nach einem Vergleich das Zero Flag nicht gesetzt, lieferte die interne Subtraktion also nicht 0, so waren beide Operanden verschieden. [bearbeiten] BRCC - Branch if Carry Flag is ClearedDer Sprung wird durchgeführt, wenn das Carry Flag (C) nicht gesetzt ist. Dieser Befehl wird oft für Arithmetik mit grossen Variablen (16/32 Bit) bzw. im Zusammenhang mit Schiebeoperatioen verwendet. [bearbeiten] BRCS - Branch if Carry Flag is SetDer Sprung wird durchgeführt, wenn das Carry Flag (C) gesetzt ist. Die Verwendung ist sehr ähnlich zu BRCC. [bearbeiten] Selten verwendete bedingte Sprünge[bearbeiten] BRHC - Branch if Half Carry Flag is ClearedDer Sprung wird durchgeführt, wenn das Half Carry Flag (H) nicht gesetzt ist. [bearbeiten] BRHS - Branch if Half Carry Flag is SetDer Sprung wird durchgeführt, wenn das Half Carry Flag (H) gesetzt ist. [bearbeiten] BRID - Branch if Global Interrupt is Disabled (Cleared)Der Sprung wird durchgeführt, wenn das Interrupt Flag (I) nicht gesetzt ist. [bearbeiten] BRIS - Branch if Global Interrupt is Enabled (Set)Der Sprung wird durchgeführt, wenn das Interrupt Flag (I) gesetzt ist. [bearbeiten] BRTC - Branch if T Flag is ClearedDer Sprung wird durchgeführt, wenn das (T) nicht gesetzt ist. [bearbeiten] BRTS - Branch if T Flag is SetDer Sprung wird durchgeführt, wenn das (T) gesetzt ist. [bearbeiten] BRVC - Branch if Overflow ClearedDer Sprung wird durchgeführt, wenn das Overflow Flag (V) nicht gesetzt ist. [bearbeiten] BRVS - Branch if Overflow SetDer Sprung wird durchgeführt, wenn das Overflow Flag (V) gesetzt ist. [bearbeiten] Beispiele[bearbeiten] EntscheidungenIn jedem Programm kommt früher oder später das Problem, die Ausführung von Codeteilen von irgendwelchen Zahlenwerten, die sich in anderen Registern befinden abhängig zu machen. Sieht beispielweise die Aufgabe vor, daß Register r18 auf 0 gesetzt werden soll, wenn im Register r17 der Zahlenwert 25 enthalten ist, dann lautet der Code
In ähnlicher Weise können die anderen bedingten Sprungbefehle eingesetzt werden, um die üblicherweise vorkommenden Vergleiche auf Gleichheit, Ungleichheit, Größer, Kleiner zu realisieren. [bearbeiten] SchleifenkonstrukteEin immer wiederkehrendes Muster in der Programmierung ist eine Schleife. Die einfachste Form einer Schleife ist die Zählschleife. Dabei wird ein Register von einem Startwert ausgehend eine gewisse Anzahl erhöht, bis ein Endwert erreicht wird.
Sehr oft ist es auch möglich das Konstrukt umzudrehen. Anstatt von einem Startwert aus zu inkrementieren genügt es die Anzahl der gewünschten Schleifendurchläufe in ein Register zu laden und dieses Register zu dekrementieren. Dabei kann man von der Eigenschaft der Dekrementieranweisung gebrauch machen, das Zero Flag (Z) zu beeinflussen. Ist das Ergebnis des Dekrements 0, so wird das Zero Flag (Z) gesetzt, welches wiederum in der nachfolgenden BRNE Anweisung für einen bedingen Sprung benutzt werden kann. Das vereinfacht die Schleife und spart eine Anweisung sowie einen Takt Ausführungzeit.
|