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

; Dateipfad: and_demo.asm
; 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

; Beispiel für OR-Anweisung

    ; 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

; Beispiel für NOT-Anweisung

    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

; Dateipfad: xor_demo.asm
; 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 VerwendungXCHGeiner 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.).

AnweisungFunktionBeispiel
SHLLogischer Linksschub (Bits fallen links heraus, Nullen füllen rechts auf)shl eax, 1(Multiplikation mit 2)
SHRLogischer Rechtschub (Bits fallen rechts heraus, Nullen füllen links auf)shr eax, 1(vorzeichenlose Division durch 2)
SALArithmetischer Linksschub (identisch mit SHL)sal eax, 1
SARArithmetischer Rechtschub (Bits fallen rechts heraus, Vorzeichenbit bleibt links erhalten)sar eax, 1(vorzeichenbehaftete Division durch 2)

Beispiel

; Dateipfad: shift_demo.asm
; 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:

AnweisungBeschreibung
ROLNach links rotieren (umgeht CF)
RORNach 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

; Beispiel für Rotationsbefehle

    ; 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

; Dateipfad: bit_flags.asm
; 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

Bit-Flag-Manipulation ist in der Systemprogrammierung äußerst verbreitet. Betriebssystemkern, Gerätetreiber und eingebettete Systeme nutzen diese Technik häufig zur Zustandsverwaltung.

Weitere Erweiterungen