Addieren und Subtrahieren
Addieren und Subtrahieren in ARM64-Assembler
In diesem Abschnitt werden wir einfache arithmetische Operationen wie Addieren und Subtrahieren in ARM64-Assembler beschreiben. Dabei werden wir die Befehle add und sub genauer betrachten, den Umgang mit Überlauf und Unterlauf erläutern und zeigen, wie man mit mehreren Registern und direkten Werten arbeitet.
Einfache arithmetische Operationen: add und sub
Der add-Befehl
Der add-Befehl wird verwendet, um zwei Werte zu addieren und das Ergebnis in einem Register zu speichern. Die grundlegende Syntax lautet:
add <Zielregister>, <Quellregister1>, <Quellregister2>
Beispiele:
Addieren der Inhalte von zwei Registern:
add x0, x1, x2 // x0 = x1 + x2
Addieren eines Registers und eines direkten Werts (Immediates):
add x0, x1, #5 // x0 = x1 + 5
Der sub-Befehl
Der sub-Befehl wird verwendet, um einen Wert von einem anderen zu subtrahieren und das Ergebnis in einem Register zu speichern. Die grundlegende Syntax lautet:
sub <Zielregister>, <Quellregister1>, <Quellregister2>
Beispiele:
Subtrahieren der Inhalte von zwei Registern:
sub x0, x1, x2 // x0 = x1 - x2
Subtrahieren eines direkten Werts von einem Register:
sub x0, x1, #5 // x0 = x1 - 5
Umgang mit Überlauf und Unterlauf
Überlauf und Unterlauf können auftreten, wenn das Ergebnis einer arithmetischen Operation größer oder kleiner als der darstellbare Wertebereich des Registers ist. ARM64-Assembler bietet spezielle Befehle und Bedingungen, um Überlauf und Unterlauf zu erkennen.
Überlauf erkennen
Der Befehl adds funktioniert wie add, setzt jedoch die Bedingungsflags einschließlich des Überlauf-Flags (V):
adds x0, x1, x2 // x0 = x1 + x2, setzt Bedingungsflags
bvs overflow // Verzweigt zu "overflow", wenn ein Überlauf aufgetreten ist
Unterlauf erkennen
Der Befehl subs funktioniert wie sub, setzt jedoch die Bedingungsflags einschließlich des Unterlauf-Flags:
subs x0, x1, x2 // x0 = x1 - x2, setzt Bedingungsflags
bvc no_overflow // Verzweigt zu "no_overflow", wenn kein Überlauf aufgetreten ist
Beispielcode zur Erkennung von Überlauf:
.global _start
_start:
mov x1, #9223372036854775807 // Setze x1 auf den größten positiven Wert (2^63 - 1)
adds x0, x1, #1 // Versuche, 1 zu x1 zu addieren
bvs overflow // Verzweigt zu "overflow", wenn ein Überlauf aufgetreten ist
no_overflow:
// Normaler Programmverlauf
// Code hierhin
b end
overflow:
// Behandeln des Überlaufs
// Code hierhin
end:
mov x8, #93 // exit system call
svc 0 // system call
Arbeiten mit mehreren Registern und direkten Werten
Sie können Additions- und Subtraktionsbefehle verwenden, um komplexere Berechnungen durchzuführen, indem Sie mit mehreren Registern und direkten Werten arbeiten.
Beispiel 1: Addieren und Subtrahieren mehrerer Register
.global _start
_start:
mov x1, #10 // Setze x1 auf 10
mov x2, #20 // Setze x2 auf 20
mov x3, #30 // Setze x3 auf 30
add x4, x1, x2 // x4 = x1 + x2 (10 + 20 = 30)
sub x5, x4, x3 // x5 = x4 - x3 (30 - 30 = 0)
// Addieren und Subtrahieren von direkten Werten
add x6, x5, #50 // x6 = x5 + 50 (0 + 50 = 50)
sub x7, x6, #20 // x7 = x6 - 20 (50 - 20 = 30)
// Programm beenden
mov x8, #93 // exit system call
svc 0 // system call
Diese Beispiele zeigen, wie man einfache arithmetische Operationen in ARM64-Assembler ausführt und sich mit Überlauf und Unterlauf bei diesen Operationen befasst.
Umgang mit Überlauf und Unterlauf bei 128-Bit-Arithmetik in ARM64-Assembler
Um Überlauf und Unterlauf bei 128-Bit-Arithmetik in ARM64-Assembler zu handhaben, können wir zwei 64-Bit-Register als ein einzelnes 128-Bit-Register behandeln. Dies bedeutet, dass man nacheinander die unteren 64-Bit (Least Significant Bits, LSB) und die oberen 64-Bit (Most Significant Bits, MSB) addieren oder subtrahieren muss und dabei den Übertrag (Carry) berücksichtigen muss.
Addieren zweier 128-Bit-Zahlen
Nehmen wir an, x0 und x1 enthalten die unteren und oberen 64-Bit der ersten Zahl, und x2 und x3 enthalten die unteren und oberen 64-Bit der zweiten Zahl. Das Ergebnis soll in x4 und x5 stehen.
Addiere die unteren 64-Bit und speichere das Ergebnis in x4. Verwende adds, um Bedingungsflags einschließlich Carry zu setzen.
Addiere die oberen 64-Bit zusammen mit dem Carry, das vom vorherigen Addieren übrig bleibt, und speichere das Ergebnis in x5.
.global _start
_start:
// Beispielwerte in den Registern setzen
// 128-Bit Zahl 1: 0xFFFFFFFFFFFFFFFF0000000000000001
mov x0, #0x0000000000000001 // LSB von Zahl 1
mov x1, #0xFFFFFFFFFFFFFFFF // MSB von Zahl 1
// 128-Bit Zahl 2: 0x0000000000000001FFFFFFFFFFFFFFFF
mov x2, #0xFFFFFFFFFFFFFFFF // LSB von Zahl 2
mov x3, #0x0000000000000001 // MSB von Zahl 2
// Addiere die unteren 64-Bit
adds x4, x0, x2 // x4 = x0 + x2, setzt das Carry-Flag falls ein Überlauf auftritt
// Addiere die oberen 64-Bit und das Carry
adc x5, x1, x3 // x5 = x1 + x3 + Carry-Flag
// Programm beenden
mov x8, #93 // exit system call
svc 0 // system call
Subtrahieren zweier 128-Bit-Zahlen
Für die Subtraktion folgt das Vorgehen einem ähnlichen Muster.
Subtrahiere die unteren 64-Bit und speichere das Ergebnis in x4. Verwende subs, um Bedingungsflags einschließlich Borrow zu setzen.
Subtrahiere die oberen 64-Bit zusammen mit dem Borrow, das von der vorherigen Subtraktion übrig bleibt, und speichere das Ergebnis in x5.
.global _start
_start:
// Beispielwerte in den Registern setzen
// 128-Bit Zahl 1: 0x0000000000000002FFFFFFFFFFFFFFFE
mov x0, #0xFFFFFFFFFFFFFFFE // LSB von Zahl 1
mov x1, #0x0000000000000002 // MSB von Zahl 1
// 128-Bit Zahl 2: 0x0000000000000001FFFFFFFFFFFFFFFF
mov x2, #0xFFFFFFFFFFFFFFFF // LSB von Zahl 2
mov x3, #0x0000000000000001 // MSB von Zahl 2
// Subtrahiere die unteren 64-Bit
subs x4, x0, x2 // x4 = x0 - x2, setzt das Borrow-Flag falls ein Unterlauf auftritt
// Subtrahiere die oberen 64-Bit und das Borrow
sbc x5, x1, x3 // x5 = x1 - x3 - Borrow-Flag
// Programm beenden
mov x8, #93 // exit system call
svc 0 // system call
Erklärung der Befehle
adds: Addiert zwei Register und setzt die Bedingungsflags (Carry-Flag bei Überlauf).adc: Addiert zwei Register zusammen mit dem Carry-Flag (Falls gesetzt).subs: Subtrahiert zwei Register und setzt die Bedingungsflags (Borrow-Flag bei Unterlauf).sbc: Subtrahiert zwei Register zusammen mit dem Borrow-Flag (Falls gesetzt).
Zusammenfassung
Durch die Verwendung der oben genannten Befehle können Sie 128-Bit-Zahlen, die in Paaren von 64-Bit-Registern gespeichert sind, addieren und subtrahieren. Diese Technik ermöglicht es Ihnen, den Überlauf oder Unterlauf korrekt zu behandeln, indem Sie die Carry- und Borrow-Flags zwischen den Operationen berücksichtigen. Indem Sie diese Methoden verstehen und anwenden, erhalten Sie die Fähigkeit, mit großen numerischen Werten auf der ARM-Architektur effizient zu arbeiten.