ARM Wie wird die Verzweigung aufgerufen?

Ich habe einen Code in Bezug auf die Schleife durchgesehen.

loopinner ....
          SUBS R2,R2,#1 ; j--
          BGT loopinner ;in this case, loop should continue when j>1

In diesem Fall bin ich mir nicht sicher, wie BGT wieder zum Loopinner verzweigt. Muss ich nicht angeben, was es größer ist als? Da SUBS die Flags aufruft, nehmen wir an, wenn j-- der Wert 1 wird. Woher weiß der Zweig, welcher Wert größer ist als er?

Dies ist Ihre dritte einfache Frage zur ARM-Montage in den letzten 12 Stunden. Sie befinden sich mitten in einer Art Prüfung?
@ElliotAlderson nicht genau, aber ich habe gerade begonnen, dieses Modul vor dem geplanten Zeitplan im Voraus zu lernen, und bin daran interessiert, mehr über ARM zu erfahren.
Verzweigungsanweisungen betrachten den Zustand verschiedener Flags, die durch die vorherige Anweisung gesetzt wurden.
Beachten Sie, dass es tatsächlich eine Schleife durchläuft, wenn j>0 (unter Verwendung des Werts von j nach dem Dekrement), nicht j>1.
Welchen Teil der Armdokumentation verstehen Sie nicht? dies ist eindeutig dokumentiert.
@Meep Geht es dir gut? Hoffe bei dir läuft alles gut. Besten Wünsche!
@jonk Ja alles gut! Habe stetig selbstständig gelernt, danke für all die Hilfe hier!

Antworten (3)

Aus ARM-Bedingungen können Sie leicht entnehmen, dass die Anweisung die Z-, N- und V-Status-Flags untersucht und verzweigt, wenn Z = 0 und N = V. Da es das V-Status-Flag und nicht das C-Status-Flag untersucht, ist dies eindeutig als signierter Test gedacht. ( Das bedeutet für mich, dass dies für die vorzeichenlose Schleifensteuerung nicht nützlich ist - FYI. )

Ich habe dies vor nicht allzu langer Zeit geschrieben , mit genügend Informationen, um zu verstehen, was vor sich geht. Aber ich kann es hier zusammenfassen.

Lassen Sie uns einfachere 4-Bit-Wörter verwenden, bei denen es nur 16 Symbole gibt:

Word     Signed     Subtrahend
0000         0         1111
0001         1         1110
0010         2         1101
0011         3         1100
0100         4         1011
0101         5         1010
0110         6         1001
0111         7         1000
1000        -8         0111
1001        -7         0110
1010        -6         0101
1011        -5         0100
1100        -4         0011
1101        -3         0010
1110        -2         0001
1111        -1         0000

Oben ist die dritte Spalte, was die ALU tatsächlich verwendet, wenn sie um diesen Wert subtrahiert. Es invertiert einfach jedes Bit vor dem Hinzufügen. (Die ALU subtrahiert niemals etwas. Sie weiß nicht einmal, wie.) Der SUB-Befehl führt also tatsächlich eine Addition durch, indem er beim Addieren die Subtrahend-Form des Werts verwendet. (Wenn Sie die Statusbit-Semantik verstehen möchten, ist es ziemlich wichtig, dass Sie dieses Konzept beherrschen, da es Ihnen hilft, wenn Sie sonst verwirrt wären.)

Stempeln Sie es auf Ihre Stirn –

Eine CPU fügt nur hinzu. ES KANN NICHT SUBTRAHIEREN .

Wenn Sie jemals die Versuchung verspüren, den Primrose-Pfad zu gehen und zu glauben, dass jede Art von Subtraktionsbefehl tatsächlich subtrahiert, und dazu gehören alle Vergleichsbefehle, die Statusbits setzen, aber keine Registerwerte ändern, treten Sie sich einfach wirklich hart und sehr schnell. Es passiert nicht.

Eine CPU fügt nur hinzu. ES KANN NICHT SUBTRAHIEREN .

Alles muss in Additionssemantik gegossen werden. Alles.

Ein SUBS R2, R2, #1 in diesem 4-Bit-Universum, das ich gerade erstellt habe, würde ebenfalls 1110 plus einen Übertrag von 1 hinzufügen. Es gibt nur 16 Möglichkeiten:

Actual Operation    Operation Result    Operation      Comparison
 R2     SUBS OP        Z N V C ALU       Semantics      Semantics   Z=0 & N=V?
0000 + 1110 + 1        0 1 0 0 1111     0 - 1 = -1       0 > 1 ?    False
0001 + 1110 + 1        1 0 0 1 0000     1 - 1 =  0       1 > 1 ?    False
0010 + 1110 + 1        0 0 0 1 0001     2 - 1 =  1       2 > 1 ?    True
0011 + 1110 + 1        0 0 0 1 0010     3 - 1 =  2       3 > 1 ?    True
0100 + 1110 + 1        0 0 0 1 0011     4 - 1 =  3       4 > 1 ?    True
0101 + 1110 + 1        0 0 0 1 0100     5 - 1 =  4       5 > 1 ?    True
0110 + 1110 + 1        0 0 0 1 0101     6 - 1 =  5       6 > 1 ?    True
0111 + 1110 + 1        0 0 0 1 0110     7 - 1 =  6       7 > 1 ?    True
1000 + 1110 + 1        0 0 1 0 0111    -8 - 1 = -9 E    -8 > 1 ?    False
1001 + 1110 + 1        0 1 0 1 1000    -7 - 1 = -8      -7 > 1 ?    False
1010 + 1110 + 1        0 1 0 1 1001    -6 - 1 = -7      -6 > 1 ?    False
1011 + 1110 + 1        0 1 0 1 1010    -5 - 1 = -6      -5 > 1 ?    False
1100 + 1110 + 1        0 1 0 1 1011    -4 - 1 = -5      -4 > 1 ?    False
1101 + 1110 + 1        0 1 0 1 1100    -3 - 1 = -4      -3 > 1 ?    False
1110 + 1110 + 1        0 1 0 1 1101    -2 - 1 = -3      -2 > 1 ?    False
1111 + 1110 + 1        0 1 0 1 1110    -1 - 1 = -2      -1 > 1 ?    False

Unter Operationsergebnis habe ich eine Spalte für ALU . Das ALU- Feld geht zurück in R2, nachdem der SUBS-Befehl abgeschlossen ist. (Das V- Status-Flag wird durch ein XOR des Übertrags des zweithöchstwertigen Bits während der Operation und des Übertragsbits selbst generiert.) Beachten Sie auch, dass es einen mit E markierten Einzelfall gibt, bei dem ein vorzeichenbehafteter Überlauf aufgetreten ist .

Sie können jetzt leicht erkennen, warum der BGT-Befehl diese bestimmten Statusbits genau so anwendet, wie er es tut. Allerdings werden hier 4-Bit-Wörter verwendet. Aber die gleiche Idee gilt für viel größere Wortgrößen, ohne dass sich daran etwas ändert.

Wenn Sie sich die Tabelle noch einmal ansehen, können Sie sehen, dass die Bedingung genau dann wahr ist, wenn R2 vor der Subtraktion 2 oder größer war und nicht 1 oder 0 oder kleiner.

Ihre Frage:

Muss ich nicht angeben, was es größer ist als? Da SUBS die Flags aufruft, nehmen wir an, wenn j-- der Wert 1 wird. Woher weiß der Zweig, welcher Wert größer ist als er?

Beginnen wir mit der folgenden Tabelle aus dem ARMv6-M Architecture Reference Manual , Seite A6-99:

Geben Sie hier die Bildbeschreibung ein

Die GT- Bedingung wird als „ Vorzeichenbehaftet größer als “ beschrieben . Der Grund, warum die Dokumentation keine Konstante angibt, ist, dass dieser Test nach einer vorherigen Anweisung erfolgt. Diese vorherige Anweisung definiert den Kontext. Aber ohne diesen Kontext kann man nur ein allgemein signiertes > sagen .

Also, wenn die vorherige Anweisung CMP wäre:

Geben Sie hier die Bildbeschreibung ein

Dann wäre der Kontext der Vergleich zweier vorzeichenbehafteter Werte und die BGT-Anweisung würde dann bedeuten "verzweigen, wenn vorzeichenbehafteter Operand 1 größer als vorzeichenbehafteter Operand 2 ist".

Aber in Ihrem Fall ändert sich mit "SUBS R2, R2, #1" der Kontext und die BGT-Anweisung würde dann bedeuten "Verzweigung, während signiertes R2 immer noch größer als 0 bleibt".

Die bedingte Verzweigungsanweisung selbst weiß eigentlich nicht , was die vorherige Anweisung war. Es weiß auch nicht einmal, um welche Register es sich handelt. Dieses Wissen wird der Person (oder dem Compiler) überlassen, die den Befehlsstrom generiert. Der Verzweigungsbefehl hat also weder einen festen konstanten Wert noch ein Register, mit dem er verglichen werden kann. Es hängt vollständig davon ab, was frühere Befehle mit den Statusbits gemacht haben. Es untersucht nur den resultierenden Status und tut dann, was es tut. Es liegt an Ihnen, den Kontext zu kennen und ihn richtig zu verwenden.

(Apropos, der Kommentar zum Quellcode kann irreführend oder falsch sein.)

Notiz

Elliot erhebt das Problem (siehe Diskussion unten) ohne Beweise. Er schreibt: „Ich könnte genauso argumentieren, dass eine CPU nur subtrahieren kann.“ Er kann dieses Argument vorbringen, aber es ist nur akademisch. Tatsache ist, dass CPUs nicht subtrahieren. Sie fügen hinzu.

Während dies also teilweise meine Antwort ist, die klare, eindeutige Beweise dafür liefert, dass sogar Elliot die Situation vor Ort verstehen kann, ist es heute auch ein ausgezeichneter Übergang. Daher freue ich mich sehr über die Gelegenheit, die Elliot mir bietet, um die Diskussion zu erweitern.

Meine erste CPU bestand aus 7400 Teilen, die ich 1974 gebaut und erfolgreich fertiggestellt hatte. Zu meiner Überraschung tauchten Zeitungsreporter auf und schrieben einen Artikel darüber. Das ist meine erste Erfahrung. Seitdem habe ich beruflich bei Intel gearbeitet und Chipsatztests für den BX-Chipsatz durchgeführt, und, was für das Unterrichten dieses Fachs relevant ist, habe ich in den 1990er Jahren als außerordentlicher Professor an der Portland State University Kurse über Computerarchitektur mit Klassengrößen von etwa 65-75 Studenten. Dies ist die größte 4-jährige Universität im Bundesstaat Oregon.

Ich empfinde Zweideutigkeit (wobei ich Ambivalenz darüber ausdrücke, wie Berechnungen durchgeführt werden könnten ) darüber, wie Prozessoren ihre Statusbits generieren und wie sie berechnen, was die Schüler nur zu unnötiger Unsicherheit, Verwirrung und Schwierigkeiten führt, deren Korrektur Stunden, Wochen, Monate und manchmal sogar Jahre dauern kann. So wie das Unterrichten von gruppentheoretischer abstrakter Algebra, bevor die Grundlagen vermittelt werden, die meisten Algebrastudenten im ersten Jahr verwirren würde, so würde auch das Unterrichten von akademischen Abstraktionen darüber, wie Computer Dinge tun können , verwirrend sein. Es würden mehr Schüler geschädigt, als geholfen.

Die einfache Wahrheit ist, dass die Anweisungsdecodierung ein ADD ausgibt, selbst wenn der Anweisungstext (es ist schließlich nur Text – es ist nicht das, was tatsächlich vor sich geht) SUB sagt. Die Dekodierung gibt immer noch ein ADD aus. Dabei werden lediglich einige Operandendetails geändert.

Ähnlich, wie es auch im Fall des ARM-Prozessors sein muss, ist die obige Theorie alles, was Sie brauchen, um zu verstehen, wie die Dinge tatsächlich gemacht werden.

Bitte verwirren Sie sich nicht! Computer hinzufügen. Sie subtrahieren nicht. Sie fummeln nur ein bisschen herum, damit es so aussieht, als würden sie subtrahieren.

Ob gut oder schlecht, es ist wichtig zu verstehen, was ein Computer tatsächlich tut, um bestimmte Statusbits zu verstehen; was sie tun und warum sie es tun. Es gibt keinen anderen Weg daran vorbei. Das obige theoretische Modell ist die Art und Weise, wie die Dinge in modernen Prozessoren funktionieren und wie man die Statusbits richtig ausarbeitet und versteht. Es gibt einen guten Grund, warum die Dinge so sind, wie sie sind.

Ich hoffe, dass diese Details oben und die, die ich unten schreiben werde, nützlich sein werden. Jedes Versäumnis, hier zu kommunizieren, ist mein Eigentum, und ich werde gerne daran arbeiten, dieses Dokument zu reparieren, zu ergänzen und zu verbessern, wo immer ich kann.

Im Folgenden verwende ich das ARMv6-M Architecture Reference Manual als Referenz.

Beginnen wir auf Seite A6-187 (Registerkoffer):

Geben Sie hier die Bildbeschreibung ein

Hier können Sie sehen, dass sie dieses Verhalten eindeutig dokumentieren:

AddWithCarry(R[n], NOT(shifted), '1')

Dies ist eine Addition, bei der Operand 2 (der Subtrahend) invertiert und der Übertrag auf '1' gesetzt ist. Genauso, wie ich oben geschrieben habe. (So ​​wird es gemacht.)

Gehen Sie im Fall von Erweiterungen mit mehreren Wörtern zu Seite A6-173 und suchen Sie nach SBCS:

Geben Sie hier die Bildbeschreibung ein

Beachten Sie hier, dass sie wieder Addition verwenden:

AddWithCarry(R[n], NOT(shifted), APSR.C)

Anstatt dass der Carry-In eine hartcodierte „1“ ist, wie es bei der SUBS-Anweisung der Fall ist, verwendet er jetzt den zuletzt gespeicherten Carry-Out-Wert. In diesem Fall wird normalerweise erwartet, dass dies die Ausführung einer früheren SUBS- (oder SBCS-) Anweisung ist.

Für Mehrwortoperationen beginnt man mit SUBS (oder ADDS) und setzt dann den Prozess mit nachfolgenden SBCS (oder ADCS) fort, die die Ausführung früherer Befehle verwenden, um eine Mehrwortoperation zu unterstützen.

In der Mehrwortaddition kann dieses Carry-Out einfach als Carry-Out betrachtet werden , was es auch ist. Eine „1“ zeigt an, dass ein Übertrag aufgetreten ist und behandelt werden muss. Eine '0' zeigt an, dass kein Übertrag aufgetreten ist.

Im Falle einer Mehrwortsubtraktion wird dieser Übertrag besser als umgekehrter Übertrag angesehen . Eine '1' gibt an, dass keine Notwendigkeit bestand, von einem Wort höherer Ordnung zu leihen. Eine „0“ zeigt an, dass ein Kreditbedarf besteht. Da ein SUBS-Befehl dies immer auf „1“ setzt, bedeutet dies, dass es kein Borgen gibt (das Subtraktionsergebnis erfordert ein „Inkrement“, um den invertierten Operanden 2 zu kompensieren.) Aber für den SBCS-Befehl, wenn APSR.C ein „ 0', dann findet kein 'Inkrement' statt und dies ist dasselbe wie ein Ausleihen (da ein Inkrement erforderlich ist, wenn kein Ausleihen vorhanden ist.)

Der ADCS-Befehl, der auf Seite A6-106 zu finden ist, hier aber nicht angezeigt wird, verwendet ebenfalls die Durchführung früherer Befehlsausführungen. Es invertiert nicht den Carry-Out-Wert oder macht anderweitig etwas Seltsames oder Anderes, nur weil es ein ADCS-Befehl ist. Er macht genau dasselbe wie der SBCS-Befehl, außer und nur für ein kleines Detail – der SBCS-Befehl invertiert Operand 2 und ADCS nicht. Das ist es.

Das ist einer der wirklich coolen Aspekte der Funktionsweise dieser Details. Sehr wenig zusätzliche Logik ist erforderlich, um eine Addition in eine Subtraktion und/oder eine Mehrwortaddition in eine Mehrwortsubtraktion umzuwandeln.

Und schließlich, um die Geschichte zu vervollständigen, siehe Seite A2-35:

Geben Sie hier die Bildbeschreibung ein

In Übereinstimmung mit meinen obigen Beschreibungen, wie die Dinge tatsächlich funktionieren.

Es ist wirklich eine Freude zu sehen, wie das alles funktioniert. Es lohnt sich, mit verschiedenen vorzeichenbehafteten und vorzeichenbehafteten Werten herumzuspielen und Status-Flags von Hand zu setzen und zu verwenden. Es vertieft diese Ideen wirklich. Und es sind sehr gute!

Bei all dem Obigen geht es darum, die Statusbits zu verstehen und wie sie generiert werden und warum sie so generiert werden, wie sie sind. Wenn Sie sich darauf konzentrieren, was tatsächlich in einer CPU passiert , fällt der Rest nur als notwendige Konsequenzen heraus und ist dann sehr leicht zu verstehen.

Eine CPU fügt nur hinzu. Es kann nicht subtrahieren.

Es macht keinen Sinn, dogmatisch darauf zu bestehen, dass eine CPU nur addieren kann. Ich könnte ebenso argumentieren, dass eine CPU nur subtrahieren kann und dass sie zum "Addieren" den zweiten Operanden negiert und subtrahiert. Die ALU ist nur ein Klecks kombinatorischer Logik, optimiert für Timing, Fläche und Leistung. Wenn ich einen Addierer/Subtrahierer in einem FPGA implementiere, erhalte ich einen Multiplexer, der sowohl Addition als auch Subtraktion durchführt, und keine Operation ist grundlegender als die andere.
@ElliotAlderson Es war früher so, dass sie die Dinge auf verschiedene Weise tun konnten, und damals war es komplizierter, den Status zu verstehen, als es heute geworden ist. Sie mussten das Handbuch lesen und sehen, was irgendein Designer damals gemacht hat. Aber heutzutage ist das einzige, was sie tun, hinzufügen. Was gut ist , nicht schlecht. Der Grund, warum ich diese Betonung mache, ist, weil, sobald diese Idee tief in das Gehirn gebohrt ist, dann alles Sinn macht , immer , und man alles genau analysieren kann. Weniger Auswendiglernen, mehr Verstehen. Es ist besser so.
@ElliotAlderson Alles, was ich geschrieben habe, ist übrigens absolut korrekt.
Nun, dann einigen wir uns darauf, anderer Meinung zu sein. Nach meiner persönlichen Erfahrung wird die Annahme, dass ich absolutes Wissen habe, normalerweise nach hinten losgehen.
@ElliotAlderson Akzeptiert. Danke. Und Sie würden "damals" sehr viel Recht haben. Ich kann die Anzahl der seltsamen Entscheidungen, die von zufälligen CPU-Designern getroffen wurden, nicht zählen. Ich suchte ständig Details aus Handbüchern heraus, weil keine zwei Personen die gleiche Wahl zu treffen schienen. Da gibt es keine Meinungsverschiedenheiten. Aber ich habe Ende der 1990er Jahre bei Intel am Design und Testen von P II-Chipsätzen gearbeitet, und ich habe mir damals die Ohren darüber geärgert, dass jetzt alle auf derselben Seite bei dieser speziellen CPU-Designentscheidung stehen. Das ist wahr. Wenn Sie jemals eine moderne ALU-Ausnahme zu dem finden, was ich geschrieben habe, geben Sie sie an, und ich werde meine Antwort hier löschen.
@ElliotAlderson Auch und genauer gesagt, mit ARM ist es genau richtig.
Nun, dann entschuldige ich mich, ich wusste nicht, dass Sie die ALUs in allen ARM-Siliziumimplementierungen sowie die Softcores entworfen haben, die für die Implementierung in FPGAs vorgesehen sind. Trotzdem denke ich, dass mein Beispiel der Implementierung einer ALU auf einem FPGA immer noch steht, und ich habe gelernt, dass diese Diskussionen wirklich nicht fruchtbar sind. Frieden.
@ElliotAlderson Du weißt, dass ich Recht habe. Bei diesem Thema ist es besser, unmissverständlich zu sein. Und wenn Sie mit „fruchtbar sein“ meinen, mich zu argumentieren, eine korrekte Ansicht zu ändern, für die es keine Gegenbeweise als Zeitverschwendung gibt, dann ist das wahr genug. Aber noch einmal, wenn Sie mir ein einziges modernes Beispiel als Beweis liefern, werde ich mein Versagen zugeben und den Beitrag auch löschen. Sie werden alles bekommen, was Sie wollen. Finden Sie einfach die Beweise. Ich bin sehr offen für Fehler. Ich weiß nur, dass ich es nicht bin. Und dir gefällt meine Gewissheit nicht. Nun ja.
Im Kontext von Arm (gemäß Frage) ist @jonk architektonisch korrekt. Die verschiedenen ArmARMs definieren SUBSals AddWithCarry(R[n], NOT(imm32), '1')(ich kann dies erweitern, wenn es hilfreich wäre), was diese Antwort abdeckt.
@ElliotAlderson Bitte sehen Sie sich das Update an. awjlogan hat mir gezeigt, wie ich die richtigen Dokumente finde. (Geschätzt.) Es ist alles da.
@jonk - genau das ist es, sorry, zu langsam von meiner Seite :)
"Ich könnte genauso argumentieren, dass eine CPU nur subtrahieren kann" - Vielleicht, aber Sie wären auf sich allein gestellt. Die Subtraktion in ALUs wurde mindestens seit dem 6502 als "Negiere den zweiten Operanden, dann addiere" implementiert, wahrscheinlich zurück zum 8008, vielleicht sogar zum 4004 oder früher. Die beteiligte grundlegende Schaltung wird als "Addierer" bezeichnet. Jede vergleichbare "Subtrahierer" -Schaltung ist komplexer als ein Addierer und im Grunde ein Addierer mit einem Negator (der auch ein Addierer ist) davor (da die Zweierkomplement-Negation "Bits invertieren" und eins addieren ist ) . Tut mir leid, Mann, im Grunde ist das alles Addition.
@ElliotAlderson Ich schrieb: "Wenn Sie mir ein einziges modernes Beispiel als Beweis liefern, werde ich mein Versagen zugeben ...", weil es mir wichtig ist, gute Beweise zu akzeptieren und Fehler zuzugeben, und definiert, was ich für andere sein möchte. Ihre Antwort "Nun, dann entschuldige ich mich, ich wusste nicht, dass Sie die ALUs in allen ARM-Siliziumimplementierungen entworfen haben, ..." Ich wäre nicht in der Lage gewesen, sie zu schreiben. Es steckt mir nicht in den Knochen. Würde sich der Spieß umdrehen, würde ich mich laut und deutlich entschuldigen, einen Fehler zugeben und versprechen, es besser zu machen. Lässt du dies zu dem Verhalten werden, das dich definiert? Ich hoffe nicht.
Fragt sich jemand ernsthaft, ob Additionslogik zum Subtrahieren verwendet wird, dachte ich an dieser Stelle, dass jeder, der tatsächlich daran arbeitet oder sich ein paar Minuten Zeit genommen hat, um nachzuschauen, das weiß. Es ist nicht wirklich relevant, ob der technische Autor für einige Dokumente dies angegeben hat oder nicht, es ist wichtig, was der Sprachcompiler, die Zellbibliothek oder der Autor des Codes direkt getan hat.
@old_timer Ja. Elliot hat mich abgestempelt und sich dann verteidigt, indem er dumme Argumente vorgebracht hat, die keine tatsächliche Grundlage haben. Er hat mich nur gemobbt. Aber Elliot und ich haben grundlegend widersprüchliche Weltanschauungen über das Unterrichten (aus früheren Diskussionen). Wir waren beide Lehrer – er sagt, er ist immer noch einer. Und er möchte, dass ich mich auch hier an seine persönlichen Regeln für den Unterricht halte. Lange Diskussion, bei der wir anderer Meinung sein mussten und es dabei belassen mussten. Ich vermute, es ging mehr um mich und seine fortwährenden Bemühungen, mich zu schikanieren. Und nicht viel mehr, um ehrlich zu sein. Er hat sich jetzt bloßgestellt.
@jonk ahh, ja ich es gibt andere Benutzer mit denen ich ähnliche Probleme habe. Ja ziemlich exponiert.

In Ihrem Codebeispiel SUBhat die Anweisung ein SSuffix. Dies bedeutet, dass die Unteranweisung die Bedingungsflags setzt, die BGTausgewertet werden. Damit die Verzweigung genommen werden kann, Zmuss das Flag 0 sein und das NFlag muss gleich seinV

Ich weiß, dass der Unterbefehl die Bedingungs-Flags setzt, wobei N = nicht negativ, Z = nicht Null, C/V = unsigned/signed overflow. Aber woher weiß der Zweig in diesem Fall, wann er zur inneren Schleife gehen soll, wenn zum Beispiel j = 2, nach dem Dekrement 1 ist, also N = 0, Z = 0, C/V = 0, wie BGT (größer als ?) geht wieder zurück zur Schleife?
Warum wird es Null sein, wenn R2 immer noch einen Wert von 1 hat? Womit wird BGT verglichen? Größer als? Entschuldigung für diese Fragen, neu bei ARM.
Befehle ändern Flags. Das Überprüfen von Flags ermöglicht bedingtes Testen. Verwenden Sie das C, um den Prüfer zu erklären. Wenn j > 0, verzweige.
@Meep Wenn es gleich wäre, wäre Z 1, wenn es kleiner wäre, dann bin ich mir nicht ganz sicher, aber wahrscheinlich wäre C 1. Da beide Null sind, muss es größer sein.
Dies ist richtig. Es prüft, ob größer als Null, in diesem Szenario haben beide C- und V-Flags denselben Wert und Z ist 0.

Die Armdokumentation besagt eindeutig, dass GT ein vorzeichenbehaftetes größer als ist, es wird verzweigt, wenn Z==0,N==V.

Wenn r2 = 2. Erinnern Sie sich aus der Grundschule daran, dass x - y = x + (-y) und vom ersten Tag (oder kurz danach) in Computertechnik/Wissenschaft/was auch immer Zweierkomplement-Negation ist, invertieren und eins addieren, also x - y = x + (~y) + 1. Das spart Logik und ist die Art und Weise, wie wir subtrahieren

      1  add one
   0010 
 + 1110  invert
==========

vier Bits sind mehr als genug, um zu sehen, was vor sich geht, das Ergebnis ist dasselbe wie 32 Bits.

   11101
    0010 
  + 1110
 ==========
    0001

Also N = 0 und Z = 0 aus dem Ergebnis. Der Übertrag in und der Übertrag des msbit sind gleich, also ist V = 0 (xor des Übertrags in und des übertrags des msbit, kann dies auch durch Inspektion der msbits der Operanden und des Ergebnisses tun).

Wir brauchen Z == 0 und N == V, um die Verzweigung durchzuführen, und das sind sie, also findet die Verzweigung statt.

Sie werden feststellen, dass dies bei positiven Zahlen der Fall ist, da dies ein vorzeichenbehafteter Größer als ist. Wenn Sie einen vorzeichenlosen Größer als verwenden möchten, verwenden Sie bcs / bhs. Die Logik funktioniert genauso, sie optimiert nur die Verwendung von Carry Out (kann dies auch sehen, wenn Sie sehen sich die von Jonk generierte Tabelle an oder erstellen selbst eine)

Wenn r2 = 1

   11111
    0001
 +  1110
 ==========
    0000

Z = 1, N = 0, V = 0

N == V, aber Z != 0, sodass die Verzweigung nicht stattfindet.

Kurzversion der Antwort von Jonks, die zeigt, wie wir N, V, Z erhalten. upvote jonks wenn/wann/stattdessen du diesen upvotest.