Assemblersprache – Logische Anweisungen
Logische Anweisungen werden für Operationen auf Bit-Ebene in der Assemblerprogrammierung verwendet und sind weit verbreitet für Maskierung, Btextraktion, das Setzen von Flags und effiziente Multiplikation/Division.
AND - Bitweises UND
ANDFührt eine bitweise UND-Operation an zwei Operanden aus (das Ergebnis ist nur dann 1, wenn beide Bits 1 sind).
Beispiel
; Beispiel für AND-Anweisung
section .text
global _start
_start:
; Einfaches bitweises UND
mov eax, 0x0F0F ; 0000 1111 0000 1111
and eax, 0x00FF ; 0000 0000 1111 1111
; Ergebnis: eax = 0x000F ; 0000 0000 0000 1111
; Gängige Technik 1: Die unteren 4 Bits maskieren (die unteren 4 Bits behalten)
mov eax, 0xAB ; 1010 1011
and eax, 0x0F ; 0000 1111
; eax = 0x0B ; 0000 1011
; Gängige Technik 2: Parität prüfen (UND mit 1)
mov eax, 42 ; Gerade
and eax, 1 ; eax = 0 (gerade)
; Die Binärzahl von 42 endet auf 0, 42 & 1 = 0
mov eax, 43 ; Ungerade
and eax, 1 ; eax = 1 (ungerade)
; Die Binärzahl von 43 endet auf 1, 43 & 1 = 1
; Gängige Technik 3: Ein Register löschen
xor eax, eax ; Äquivalent zu mov eax, 0, aber schneller und kürzer
; AND setzt Flags: CF=0, OF=0, ZF und SF hängen vom Ergebnis ab
mov eax, 1
mov ebx, 0
int 0x80
OR - Bitweises ODER
ORFührt eine bitweise ODER-Operation an zwei Operanden aus (Ergebnis ist 1, wenn mindestens ein Bit 1 ist).
Beispiel
; Flag-Bits zusammenführen
mov eax, 0x0F00 ; 0000 1111 0000 0000
or eax, 0x00FF ; 0000 0000 1111 1111
; eax = 0x0FFF ; 0000 1111 1111 1111
; Ein spezifisches Bit setzen (Bit 3 auf 1 setzen)
mov eax, 0 ; 0000 0000
or eax, 0x08 ; 0000 1000
; eax = 0x8 ; 0000 1000
; Fallkonvertierung: Groß- in Kleinbuchstaben
mov al, 'A' ; al = 0x41 (0100 0001)
or al, 0x20 ; 0x20 = 0010 0000
; al = 0x61 = 'a' ; 0110 0001
NOT - Bitweises NICHT
NOTInvertiert jedes Bit des Operanden (0 wird zu 1, 1 wird zu 0).
Beispiel
mov eax, 0x0F0F0F0F ; 0000 1111 0000 1111 ...
not eax ; 1111 0000 1111 0000 ...
; eax = 0xF0F0F0F0
; NOT beeinflusst keine Flags (im Gegensatz zu AND/OR/XOR)
XOR - Bitweises EXKLUSIV-ODER
XORFührt eine bitweise XOR-Operation an zwei Operanden aus (Ergebnis ist 1, wenn die Bits unterschiedlich sind, und 0, wenn sie gleich sind).
Beispiel
; Beispiel für XOR-Anweisung
section .text
global _start
_start:
; Einfaches XOR
mov eax, 0x0F0F ; 0000 1111 0000 1111
xor eax, 0x00FF ; 0000 0000 1111 1111
; Ergebnis: eax = 0x0FF0 ; 0000 1111 1111 0000
; Klassische Technik 1: Ein Register löschen (effizienter als mov reg, 0)
xor eax, eax ; eax = 0, belegt nur 2 Bytes
xor ebx, ebx
xor ecx, ecx
; Klassische Technik 2: Zwei Register vertauschen (kein drittes temporäres Register erforderlich)
mov eax, 100 ; eax = 100
mov ebx, 200 ; ebx = 200
xor eax, ebx ; eax = 100 xor 200
xor ebx, eax ; ebx = 200 xor (100 xor 200) = 100
xor eax, ebx ; eax = (100 xor 200) xor 100 = 200
; Jetzt ist eax = 200, ebx = 100 (Tausch abgeschlossen!)
; Klassische Technik 3: Einfache Verschlüsselung/Entschlüsselung
mov al, 'A' ; Originalzeichen 'A' = 0x41
xor al, 0x55 ; Verschlüsselung: al = 'A' xor 0x55
; al hat nun einen unleserlichen Wert
xor al, 0x55 ; Entschlüsselung: Erneut XOR mit 0x55 zur Wiederherstellung
; al = 'A' ist wieder da!
mov eax, 1
mov ebx, 0
int 0x80
Der XOR-Swap-Trick ist cool, aber auf modernen CPUs weniger effizient als die Verwendung
XCHGeiner Instruktion oder eines temporären Registers. Gut zu wissen, aber man muss ihn nicht unbedingt verwenden.
Schiebebefehle (Shift-Instruktionen)
Schiebebefehle verschieben binäre Bits nach links oder rechts, was häufig für effiziente Multiplikation und Division verwendet wird (Multiplikation mit 2, Division durch 2 usw.).
| Anweisung | Funktion | Beispiel |
|---|---|---|
| SHL | Logischer Linksschub (Bits fallen links heraus, Nullen füllen rechts auf) | shl eax, 1(Multiplikation mit 2) |
| SHR | Logischer Rechtschub (Bits fallen rechts heraus, Nullen füllen links auf) | shr eax, 1(vorzeichenlose Division durch 2) |
| SAL | Arithmetischer Linksschub (identisch mit SHL) | sal eax, 1 |
| SAR | Arithmetischer Rechtschub (Bits fallen rechts heraus, Vorzeichenbit bleibt links erhalten) | sar eax, 1(vorzeichenbehaftete Division durch 2) |
Beispiel
; Beispiel für Schiebebefehle
section .text
global _start
_start:
; SHL: logischer Linksschub = Multiplikation mit einer Zweierpotenz
mov eax, 10 ; eax = 10 (1010)
shl eax, 1 ; eax = 20 (10100), d. h. 10×2
shl eax, 2 ; eax = 80 (1010000), d. h. 20×4
; SHR: logischer Rechtschub = vorzeichenlose Division durch eine Zweierpotenz
mov eax, 80 ; eax = 80
shr eax, 3 ; eax = 10, d. h. 80÷8
; SAR: arithmetischer Rechtschub = vorzeichenbehaftete Division durch eine Zweierpotenz (behält das Vorzeichenbit bei)
mov eax, -16 ; eax = -16 (0xFFFFFFF0)
sar eax, 2 ; eax = -4 (0xFFFFFFFC), d. h. -16÷4
; SAR vs. SHR:
; Wenn eax = 0xFFFFFFF0 (-16) ist, liefert SHR 0x3FFFFFFC (eine sehr große positive Zahl)
; während SAR 0xFFFFFFFC (-4) liefert und dabei das Vorzeichenbit beibehält
; Das letzte herausgeschobene Bit landet im CF-Flag
mov eax, 5 ; 0101
shr eax, 1 ; eax = 2, CF = 1 (die nachfolgende 1 wurde herausgeschoben)
jc carry_was_set ; Wenn CF=1, war die ursprüngliche Zahl ungerade
carry_was_set:
mov eax, 1
mov ebx, 0
int 0x80
Rotationsbefehle
Rotationsbefehle schieben das herausgeschobene Bit am anderen Ende wieder hinein, wodurch eine Rotation entsteht:
| Anweisung | Beschreibung |
|---|---|
| ROL | Nach links rotieren (umgeht CF) |
| ROR | Nach rechts rotieren (umgeht CF) |
| RCL | Über den Übertrag (Carry) nach links rotieren (bezieht CF mit ein) |
| RCR | Über den Übertrag (Carry) nach rechts rotieren (bezieht CF mit ein) |
Beispiel
; ROL: nach links rotieren
mov al, 0x85 ; 1000 0101
rol al, 1 ; Um 1 Bit nach links verschieben: 0000 1011
; CF = 1 (das höchstwertige Bit wird in CF herausgeschoben)
; Gleichzeitig wird die ursprüngliche 1 in CF in das niedrigste Bit geschoben, wodurch eine Rotation entsteht
; Tatsächliche Auswirkung von ROL: Um 1 Bit nach links verschieben, das höchstwertige Bit geht sowohl in CF als auch in das niedrigste Bit
; 1000 0101 -> ROL 1 -> 0000 1011
; RCL: über Carry nach links rotieren (CF nimmt an der Rotation teil)
clc ; CF löschen = 0
mov al, 0x85 ; 1000 0101
rcl al, 1 ; CF nimmt teil: CF Bit7...bit0 -> CF
; Ergebnis: 0000 1010, CF = 1
; Rotationsverschiebungen werden häufig in Verschlüsselungsalgorithmen und bei der Bit-Manipulation verwendet
Praktische Anwendungen logischer Operationen
Ein umfassendes Beispiel – Implementierung eines einfachen Bit-Flag-Systems mithilfe logischer Operationen:
Beispiel
; Implementierung eines Bit-Flag-Systems mithilfe logischer Operationen
section .data
flags db 0 ; 8 Flag-Bits, anfangs alle 0
; bit0: ob aktiv
; bit1: ob sichtbar
; bit2: ob Speicherung erforderlich
; bit3: ob modifiziert
FLAG_ACTIVE equ 1 ; 0000 0001
FLAG_VISIBLE equ 2 ; 0000 0010
FLAG_NEED_SAVE equ 4 ; 0000 0100
FLAG_MODIFIED equ 8 ; 0000 1000
section .text
global _start
_start:
; Flag-Bits setzen: OR
mov al, [flags]
or al, FLAG_ACTIVE ; Setze bit0
or al, FLAG_VISIBLE ; Setze bit1
; al = 0000 0011 = 3
mov [flags], al
; Flag-Bits überprüfen: AND + TEST
test byte [flags], FLAG_ACTIVE ; Teste, ob Bit 0 gleich 1 ist
jnz is_active ; ZF=0 bedeutet, das Bit ist 1
is_active:
; Flag-Bits löschen: AND + NOT
mov al, [flags]
and al, ~FLAG_VISIBLE ; Bit 1 löschen (andere Bits unverändert lassen)
; al = 0000 0001 = 1
mov [flags], al
; Flag-Bits umschalten: XOR
mov al, [flags]
xor al, FLAG_MODIFIED ; Bit 3 umschalten
; War es 0, wird es 1; war es 1, wird es 0
mov eax, 1
mov ebx, 0
int 0x80
Weitere ErweiterungenBit-Flag-Manipulation ist in der Systemprogrammierung äußerst verbreitet. Betriebssystemkern, Gerätetreiber und eingebettete Systeme nutzen diese Technik häufig zur Zustandsverwaltung.