Programmablauf steuern: Unterschied zwischen den Versionen

Aus C und Assembler mit Raspberry
KKeine Bearbeitungszusammenfassung
Zeile 117: Zeile 117:
** NEGS (Negation und setzen des Flags)
** NEGS (Negation und setzen des Flags)


Beispiel:
<syntaxhighlight lang="asm">
.section .text
.globl _start


_start:
    MOV X0, #5      // X0 = 5
    MOV X1, #3      // X1 = 3
   
    ADD X2, X0, X1  // X2 = X0 + X1 = 8, keine Flags gesetzt
    ADDS X3, X0, X1  // X3 = X0 + X1 = 8, Flags gesetzt


    CMP X2, X3      // Vergleich X2 und X3 (Flags gesetzt)
    B.NE not_equal  // Springe zu not_equal, wenn nicht gleich


    SUBS X4, X0, X1  // X4 = X0 - X1 = 2, Flags gesetzt


* CMP Xn,Operand2
    B end            // Springe zu end
-> subtrahiert Operand2 von Xn


* Schleifen
not_equal:
** FOR NEXT
    NEG X5, X1      // X5 = -X1 = -3, keine Flags gesetzt
 
end:
    // Endlosschleife um das Programm nicht sofort zu beenden
    B end
</syntaxhighlight>
 
== Schleifen ==
In diesem Abschnitt beschreibe ich Beispiele, wie man unter Assembler bestimmte Kontrollstruckturen umsetzen kann, die man auch verschiedenen Hochsprachen, wie zum Beispiel C oder Pascal, kennt.
=== FOR NEXT ===
Pseudocode:
<syntaxhighlight lang="C">
  for i = 1 to 10
  for i = 1 to 10
   Mache etwas
   Mache etwas
  next i
  next i
</syntaxhighlight>


In Assembler:
In Assembler:
<syntaxhighlight lang="asm">
   mov w2,#1  //i=1
   mov w2,#1  //i=1
  loop:
  loop:
Zeile 137: Zeile 162:
   cmp w2,#10  // if i<10
   cmp w2,#10  // if i<10
   b.le loop    // then goto loop
   b.le loop    // then goto loop
** WHILE
</syntaxhighlight>
=== WHILE ===
Pseudocode:
<syntaxhighlight lang="C">
  while x < 10
  while x < 10
   Mache etwas
   Mache etwas
  end while
  end while
</syntaxhighlight>


In Assembler:
In Assembler:
<syntaxhighlight lang="asm">
   // w2 zuvor initialisiert -> x
   // w2 zuvor initialisiert -> x
  // Beispiel: mov w2,#0
   loop:
   loop:
     cmp w2,#10
     cmp w2,#10
     b.ge loopend
     b.ge loopend
     // Mache etwas
     // Mache etwas
    // Beispiel: add w2,w2,#1
     b loop
     b loop
   loopend:
   loopend:
</syntaxhighlight>


** if/then/else
** if/then/else

Version vom 3. April 2025, 11:52 Uhr

Grundsätzlich besteht die Programmierung aus vielen wenn/dann Abfragen. Der Ablauf des Programms wird auf bestimmte Bedingungen gesteuert. hier gibt es unter dem ARM-64-Assembler einige BEfehle, wie Bedingte und unbedingte Sprungbefehle: b, bl, cbz, cbnz, die für solche Zwecke verwendet werden können. In diesem Abschnitt erkläre ich, wie diese Verwendet werden kann. In Beispielen erkläre ich noch, wie man bestimmte Anforderungen, wie FOR/NEXT-, WHILE-, DO/UNTIL-Schleifen und IF/ELSE-Abfragen in Assembler abbilden kann.

Bedingungsloser Sprung

b (Branch)

Der Bedingunslose Sprung wird mit "b" (Branch) durchgeführt. Dies bedeutet, dass der Programmablauf an der mit Label bezeichnetet Stelle springt.

Syntax: b label

Beispiel:

.global _start

_start:
    mov x0, #5       // Setze x0 auf 5
    mov x1, #6       // Setze x1 auf 6
    b Label1
    mov x1,#10       //wird übergangen, da Branch auf Label1 springt
Label1:
    // x1 bleibt auf #6
    // Programm beenden
    mov x8, #93      // exit system call
    svc 0            // system call

bl (Branch with link)

Ein anderer bedingungsloser Sprung ist bl. Dieser wird verwendet, wenn man in ein Unterprogramm springen möchte. Wenn dieser Befehl aufgerufen wird, wird in x30 der darauffolgende Befehl (Adresse) übergeben. Dies ist sehr nützlich, um in Unterprogrammen, wieder zurück zu kommen.

Syntax: bl label

Beispiel:

.global _start

_start:
    mov x0, #5       // Setze x0 auf 5
    mov x1, #6       // Setze x1 auf 6
    bl Unterprogramm1 // Springe in das Unterprogramm
    // Programm beenden
    mov x8, #93      // exit system call
    svc 0            // system call

Unterprogramm1:
    mov x1, #100      // Überschreibe x1 mit 100
    ret            // springe zurück zum Hauptprogramm

Bedingter Sprung

Bedingte Sprünge werden verwendet, wenn auf bestimmte Ergebnisse reagiert werden soll. Hierfür wird das NZCV-Systemregister verwendet, welches Flags enthält, auf die hier getestet werden können.

Bedingungsflags

  • negativ: N gesetzt, wenn Ergebnis negativ ist
  • zero: z gesetzt wenn Ergebnis null ist
  • carry: c gesetzt, wenn es einen Überlauf gab. add -> wenn größer als Zahlenbereich (Überlauf), Subtraktion gesetzt, wenn Ergebnis keine Ausleihe. bei Verschieben letzte Bit herausgeschoben.
  • overflow: o gesetzt bei addition und subtraktion, wenn Ergebnis größer oder gleich 2^31, oder kleiner -2^31

Verzweigung bei Bedingung

Für die Verzweigung mit Bedingungen, wird wiederrum "b" verwendet, allerdings wird im eine Bedingung mit übergeben:

Syntax: b.{condition} label

Folgende "conditions" sind möglich:

condition
{condition} FLAGs Bedeutung
EQ Z gesetzt gleich
NE Z nicht gesetzt ungleich
CS oder HS C gesetzt größer oder gleich (Vorzeichenlos)
CC oder LO C nicht gesetzt kleiner (Vorzeichenlos)
MI N gesetzt negativ
PL N nicht gesetzt positiv oder Null
VS V gesetzt Überlauf
VC V nicht gesetzt Kein Überlauf
HI C gesetzt
Z nicht gesetzt
größer (Vorzeichenlos)
LS C nicht gesetzt
Z gesetzt
kleiner oder gleich (Vorzeichenlos)
GE N und V gleich größer oder gleich (Vorzeichen)
LT N und V nicht gleich kleiner (Vorzeichen)
GT Z nicht gesetzt
N und V gleich
größer (Vorzeichen)
LE Z gesetzt
N und V nicht gleich
kleiner oder gleich (Vorzeichen)
AL Alles Immer (gleiches wie ohne Suffix)

Damit die Bedingungen gesetzt werden, muss vor der Verzweigung die Condition-Flags gesetzt werden. Dies erfolgt Beispielsweise mit folgenden Befehlen:

  • Arithmetische Befehle:
    • ADDS (Addition mit setzen des Flag)
    • SUBS (Subtraktion mit setzen des Flag)
    • ADCS (Addition mit Carry und setzen des Flags)
    • SBCS (Subtraktion mit Carry und setzen des Flags)
  • Logische Befehle
    • ANDS (Logisches UND und setzen des Flags)
    • ORR (Logisches ODER)
    • EOR (Logisches Exklusiv-ODER)
    • TST (Test, Setzt Flags basierend auf AND)
  • Weitere Befehle
    • CMP (Vergleichen, Setzt Flags basierend auf SUB)
    • CMN (Vergleichen mit Negation, Setzt Flags basierend auf ADD)
    • MOV (Kopieren)
    • MVN (Kopiere und negiere)
    • NEGS (Negation und setzen des Flags)

Beispiel:

.section .text
.globl _start

_start:
    MOV X0, #5       // X0 = 5
    MOV X1, #3       // X1 = 3
    
    ADD X2, X0, X1   // X2 = X0 + X1 = 8, keine Flags gesetzt
    ADDS X3, X0, X1  // X3 = X0 + X1 = 8, Flags gesetzt

    CMP X2, X3       // Vergleich X2 und X3 (Flags gesetzt)
    B.NE not_equal   // Springe zu not_equal, wenn nicht gleich

    SUBS X4, X0, X1  // X4 = X0 - X1 = 2, Flags gesetzt

    B end            // Springe zu end

not_equal:
    NEG X5, X1       // X5 = -X1 = -3, keine Flags gesetzt

end:
    // Endlosschleife um das Programm nicht sofort zu beenden
    B end

Schleifen

In diesem Abschnitt beschreibe ich Beispiele, wie man unter Assembler bestimmte Kontrollstruckturen umsetzen kann, die man auch verschiedenen Hochsprachen, wie zum Beispiel C oder Pascal, kennt.

FOR NEXT

Pseudocode:

 for i = 1 to 10
   Mache etwas
 next i

In Assembler:

   mov w2,#1  //i=1
 loop:
   //Mache etwas
   add w2,w2,#1 // i=i+1
   cmp w2,#10   // if i<10
   b.le loop    // then goto loop

WHILE

Pseudocode:

 while x < 10
   Mache etwas
 end while

In Assembler:

  // w2 zuvor initialisiert -> x
  // Beispiel: mov w2,#0
  loop:
    cmp w2,#10
    b.ge loopend
    // Mache etwas
    // Beispiel: add w2,w2,#1
    b loop
  loopend:
    • if/then/else
if x < 10 then
   If ist okay
else
   else kommt zum zuge
end if

In Assembler:

 // wert x in w2
 cmp w2,#10
 b.ge label_else
   //If ist okay
   b label_EndIf

label_else:

   //else kommt zum zuge

label_EndIf:

    • do/until
do
  Mache etwas
until a==0

In Assembler:

  mov w0,#1
loop:
  //mache etwas
  cmp w0,#0
  b.ne loop