Assemblersprache - Bedingte Verzweigung

Die bedingte Verzweigung ist der Grundstein der Programmsteuerungslogik. Assemblersprache implementiert Verzweigungslogik wie if-else, switch usw. durch Vergleichsbefehle und bedingte Sprungbefehle.


CMP - Vergleichsbefehl

CMPFührt eine Subtraktionsoperation an zwei Operanden aus (Ziel - Quelle), speichert das Ergebnis jedoch nicht, sondern aktualisiert nur die Flags.

Im WesentlichenCMP dest, srcÄquivalent zuSUB dest, srcVerwirft jedoch das Berechnungsergebnis.

Beispiel

; CMP-Vergleichsbefehlsbeispiel

section .text
    global _start

_start:
    mov eax, 10
    cmp eax, 10                 ; eax == 10?
    ; ZF = 1 (gleich, Ergebnis ist null)
    ; CF = 0 (kein Übertrag)
    ; SF = 0 (Ergebnis nicht negativ)

    mov eax, 5
    cmp eax, 10                 ; eax == 10?
    ; ZF = 0 (ungleich, Ergebnis ungleich null)
    ; CF = 1 (Übertrag: 5 < 10)

    mov eax, 20
    cmp eax, 10                 ; eax == 10?
    ; ZF = 0 (ungleich)
    ; CF = 0 (kein Übertrag: 20 >= 10)
    ; SF = 0 (Ergebnis nicht negativ: 10 > 0)

    mov eax, 1
    mov ebx, 0
    int 0x80

Bedingte Sprungbefehle

Bedingte Sprungbefehle bestimmen basierend auf dem Zustand der Flags, ob gesprungen werden soll. Wenn die Bedingung wahr ist, springe zur Zielmarke; andernfalls fahre mit der Ausführung des nächsten Befehls fort.

AnweisungBedeutungGeprüfte FlagsAnwendungsfall
JE / JZSpringe, wenn gleich / nullZF = 1cmp a, bÜberprüfe a == b nach CMP
JNE / JNZSpringe, wenn ungleich / nicht nullZF = 0cmp a, bÜberprüfe a != b nach CMP
JG / JNLESpringe, wenn größer (mit Vorzeichen)ZF=0 und SF=OFZahlen mit Vorzeichen a > b
JGE / JNLSpringe, wenn größer oder gleich (mit Vorzeichen)SF = OFZahlen mit Vorzeichen a >= b
JL / JNGESpringe, wenn kleiner (mit Vorzeichen)SF != OFZahl mit Vorzeichen a < b
JLE / JNGSpringe, wenn kleiner oder gleich (mit Vorzeichen)ZF=1 oder SF!=OFZahl mit Vorzeichen a <= b
JA / JNBESpringe, wenn größer (ohne Vorzeichen)CF=0 und ZF=0Zahl ohne Vorzeichen a > b
JAE / JNBSpringe, wenn größer oder gleich (ohne Vorzeichen)CF = 0Zahl ohne Vorzeichen a >= b
JB / JNAESpringe, wenn kleiner (ohne Vorzeichen)CF = 1Zahl ohne Vorzeichen a < b
JBE / JNASpringe, wenn kleiner oder gleich (ohne Vorzeichen)CF=1 oder ZF=1Zahl ohne Vorzeichen a <= b

Many instructions have two aliases (such as JE and JZ), which are exactly the same at the machine code level. Which one to use depends on the context: use JE/JNE after comparisons, and JZ/JNZ after checking operation results. This improves code readability.


Single-Branch IF Structure

Beispiel

; File path: if_demo.asm
; Implementation: if (x > 10) x = 10;

section .data
    x dd 15                     ; Test value
    limit dd 10

section .text
    global _start

_start:
    mov eax, [x]                ; Load x into eax
    cmp eax, [limit]            ; x > 10 ?
    jle skip_update             ; If x <= 10, skip update

    mov dword [x], 10           ; x = 10

skip_update:
    ; Program continues... (here x is already 10)

    mov eax, 1
    mov ebx, 0
    int 0x80

IF-ELSE Double-Branch Structure

Beispiel

; File path: if_else_demo.asm
; Implementation: if (score >= 60) grade = 'P' else grade = 'F'

section .data
    score dd 75                 ; Exam score
    grade db 0                  ; Grade
    PASS_SCORE equ 60

section .text
    global _start

_start:
    mov eax, [score]            ; Load score
    cmp eax, PASS_SCORE         ; score >= 60 ?
    jge pass_label              ; If >= 60, jump to pass

    ; else branch: fail
    mov byte [grade], 'F'       ; grade = 'F'
    jmp end_if                  ; skip if branch

pass_label:
    ; if branch: pass
    mov byte [grade], 'P'       ; grade = 'P'

end_if:
    ; grade variable is now set

    ; output grade
    mov eax, 4
    mov ebx, 1
    mov ecx, grade
    mov edx, 1
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

Run result:

$ nasm -f elf32 if_else_demo.asm -o if_else_demo.o
$ ld -m elf_i386 if_else_demo.o -o if_else_demo
$ ./if_else_demo
P

IF-ELSE IF-ELSE Multi-Branch Structure

Below uses a score grading system as an example to show the flow of multi-branch decision:

条件判断多分支流程图

Beispiel

; File path: multi_branch.asm
; Score grading: >=90 -> A, >=80 -> B, >=70 -> C, >=60 -> D, <60 -> F

section .data
    score dd 85
    result db 0
    newline db 0xA

section .text
    global _start

_start:
    mov eax, [score]            ; Load score

    ; Check >= 90
    cmp eax, 90
    jl check_80                 ; If < 90, continue checking
    mov byte [result], 'A'
    jmp print_result

check_80:
    cmp eax, 80
    jl check_70
    mov byte [result], 'B'
    jmp print_result

check_70:
    cmp eax, 70
    jl check_60
    mov byte [result], 'C'
    jmp print_result

check_60:
    cmp eax, 60
    jl fail_label
    mov byte [result], 'D'
    jmp print_result

fail_label:
    mov byte [result], 'F'

print_result:
    ; Output grade
    mov eax, 4
    mov ebx, 1
    mov ecx, result
    mov edx, 1
    int 0x80

    ; Output newline
    mov eax, 4
    mov ebx, 1
    mov ecx, newline
    mov edx, 1
    int 0x80

    mov eax, 1
    mov ebx, 0
    int 0x80

TEST - Non-Destructive Test Instruction

TESTPerforms bitwise AND but does not save the result, only updates flags.

TESTOften used to check whether a specific bit is 1, or whether a register is 0.

Beispiel

; TEST instruction example

    ; Check if eax is 0 (more efficient than CMP eax, 0)
    test eax, eax               ; eax & eax = eax, only updates ZF
    jz  eax_is_zero             ; If ZF=1, then eax=0

    ; Check a specific bit
    test al, 0x01               ; Check if bit0 is 1
    jnz bit0_is_set             ; If bit0=1, jump

    ; Check multiple bits
    test al, 0x03               ; Check if at least one of bit0 and bit1 is 1
    jnz some_bit_set

SETcc – Bedingte Setzanweisung

Anstatt zu springen, setzt das Zielbyte basierend auf der Bedingung auf 1 oder 0:

Beispiel

; SETcc Beispiel für bedingtes Setzen

    ; Speichere das Ergebnis von a > b in al
    mov eax, 10
    cmp eax, 5                  ; 10 > 5 ?
    setg al                     ; al = 1 (größer-als trifft zu)
    ; Wenn eax = 3, dann al = 0

    ; Andere SETcc-Anweisungen:
    ; sete / setz -> gleich/null
    ; setne / setnz -> ungleich/nicht null
    ; setl -> kleiner als (mit Vorzeichen)
    ; setb -> kleiner als (ohne Vorzeichen)
    ; setg -> größer als (mit Vorzeichen)
    ; seta -> größer als (ohne Vorzeichen)

; Vollständiges Beispiel: Gerade/Ungerade und Positiv/Negativ bestimmen

Beispiel

; Dateipfad: number_check.asm
; Bestimme, ob eine Zahl gerade/ungerade, positiv/negativ ist

section .data
    number dd -42
    msg_even db 'Even', 0xA
    msg_even_len equ $ - msg_even
    msg_odd db 'Odd', 0xA
    msg_odd_len equ $ - msg_odd
    msg_pos db 'Positive', 0xA
    msg_pos_len equ $ - msg_pos
    msg_neg db 'Negative', 0xA
    msg_neg_len equ $ - msg_neg
    msg_zero db 'Zero', 0xA
    msg_zero_len equ $ - msg_zero

section .text
    global _start

_start:
    mov eax, [number]

    ; Prüfe, ob Null
    cmp eax, 0
    jne check_sign
    ; ist Null
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_zero
    mov edx, msg_zero_len
    int 0x80
    jmp exit

check_sign:
    ; Prüfe positiv/negativ
    cmp eax, 0
    jg  is_positive             ; eax > 0

    ; negativ
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_neg
    mov edx, msg_neg_len
    int 0x80
    jmp check_parity

is_positive:
    ; positiv
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_pos
    mov edx, msg_pos_len
    int 0x80

check_parity:
    ; Bestimme gerade/ungerade (muss nur das unterste Bit prüfen)
    mov eax, [number]
    test eax, 1                 ; Prüfe bit0
    jnz is_odd

    ; gerade
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_even
    mov edx, msg_even_len
    int 0x80
    jmp exit

is_odd:
    ; ungerade
    mov eax, 4
    mov ebx, 1
    mov ecx, msg_odd
    mov edx, msg_odd_len
    int 0x80

exit:
    mov eax, 1
    mov ebx, 0
    int 0x80

Bedingte Sprunganweisungen können nur zu Sprungmarken innerhalb des aktuellen Codesegments springen; der Sprungbereich ist normalerweise auf etwa 128 Bytes (kurzer Sprung) bis 2 GB (naher Sprung) begrenzt. NASM wählt automatisch die passende Sprungcodierung.

Weitere Erweiterungen