reverseenengineering:ветвления

Ветвления

Ветвления в ассемблере: архитектуры x86 (Intel), ARM, MIPS

1. Основные функции ветвления в ассемблере

Ветвление (branching) — это переход исполнения программы на другую инструкцию, обычно по условию. Вот основные виды ветвления (на примере x86):

  • Безусловный переход: :: JMP label
  • Условный переход по флагам: :: Jcc label (JE, JNE, JL, JG и др.)
  • Переход с возвратом: :: CALL label, RET
  • Циклические переходы: :: LOOP label, LOOPE, LOOPNE
  • Косвенные переходы: :: JMP [reg]
  • Табличные переходы: :: через адресацию перехода по таблице (jump table)
  • Прерывания и возврат из них: :: INT N, IRET

Желающие подробности по архитектурам — читайте далее.


2.1. Работа флагов

После арифметической/логической операции процессор выставляет флаги в регистре EFLAGS:

Название Описание
ZF (Zero Flag) Результат 0? (1 если да)
SF (Sign Flag) Знак результата (1=минус)
CF (Carry Flag) Перенос (важно при беззнаковых)
OF (Overflow Flag) Переполнение (важно при знаковых)
PF (Parity Flag) Четность (не часто используется)

2.2. Основные команды ветвления

Инструкция Условие Обозначение
JE/JZ ZF = 1 Равно («Jump if Equal»)
JNE/JNZ ZF = 0 Не равно
JL (SF ≠ OF) Меньше (signed)
JLE (ZF=1 or SF ≠ OF) Меньше или равно (signed)
JG (ZF=0 and SF=OF) Больше (signed)
JGE (SF=OF) Больше или равно (signed)
JB CF = 1 Меньше (unsigned)
JBE CF=1 or ZF=1 Меньше или равно (unsigned)
JA (CF=0 and ZF=0) Больше (unsigned)
JAE CF = 0 Больше или равно (unsigned)
CALL, RET Вызов и возврат процедуры
JMP [рег] Косвенный переход

2.3. Примеры кода и пояснения

JMP somewhere
mov  eax, -3         ; eax = FFFFFFFDh (32-битный -3)
mov  ebx, 1          ; ebx = 00000001h
cmp  eax, ebx        ; вычитание: -3 - 1 = -4 (0xFFFFFFFCh)
jg   more_label      ; если eax > ebx (signed)?
jl   less_label      ; если eax < ebx (signed)?
je   equal_label     ; если eax == ebx?

mov ecx, 123
jmp end

more_label:
mov ecx, 1
jmp end

less_label:
mov ecx, 2
jmp end

equal_label:
mov ecx, 3

end:

Анализ флагов:

  • После 'cmp eax, ebx':
    • ZF = 0 (результат не ноль)
    • SF = 1 (отрицательное)
    • OF = 0 (переполнения нет)
    • CF = 1 (был «заём» беззнаково)
  • 'jg': требует ZF=0 и SF=OF (1 ≠ 0 – не равно, перехода нет)
  • 'jl': SF ≠ OF? (1 ≠ 0 — переход будет!)
mov eax, 7
mov ebx, 7
cmp eax, ebx
je  eq_label  ; ZF=1, переход будет
jne neq_label ; ZF=0, переход не будет
mov cx, 5
loop_start:
 ; ... тело цикла
loop loop_start
call my_function
; ...
my_function:
 ; действия
ret
jmp [ebx]   ; ebx — адрес новой инструкции

3.1. Флаги

Флаг Назначение
N (Negative) Результат отрицательный? (MSB=1)
Z (Zero) Результат 0?
C (Carry) Перенос/заём для беззнаковых
V (Overflow) Переполнение для знаковых

Инструкции, которые изменяют флаги — обычно с S: 'ADDS', 'SUBS', 'CMP', 'ANDS' и др.

3.2. Ветвления по суффиксам

Любая инструкция ветвления (и почти любая другая) может иметь суффикс условия:

Суффикс Условие Описание
EQ Z=1 Равно
NE Z=0 Не равно
LT N ≠ V Меньше (signed)
GT Z=0 и N=V Больше (signed)
GE N=V Больше или равно (signed)
LE Z=1 или N ≠ V Меньше или равно (signed)
CS/HS C=1 Беззнаково >=
CC/LO C=0 Беззнаково <

3.3. Примеры кода и пояснения

MOV R0, #5
MOV R1, #8
CMP R0, R1      ; R0 - R1 = -3 (Negative)
BEQ label_eq    ; Z=1 ?
BNE label_ne    ; Z=0 ?
BLT label_lt    ; N ≠ V ?

* После CMP:

  • N = 1 (отрицательное)
  • Z = 0 (не ноль)
  • V = 0
  • C = 0

* BEQ — не сработает (Z=0) * BNE — выполнится (Z=0) * BLT — N ≠ V (1 ≠ 0) — выполнится

BL  myfunc     ; вызов с занесением адреса возврата в LR
; ...
myfunc:
 ; ...
 BX LR         ; возврат
CMP R0, #3
BHI default
LDR PC, [PC, R0, LSL #2]  ; PC ← (таблица адресов: case0, case1...)

.word case0
.word case1
.word case2
.word case3

case0:
; ...
BX LR

default:

4.1. Нет регистра флагов!

Всё ветвление идёт по значению регистров.

Инструкция Что выполняет
beq $a, $b, label Переход, если равны ($a = $b)
bne $a, $b, label Переход, если не равны
slt $r, $a, $b $r = 1, если $a < $b (signed), иначе 0
sltu $r, $a, $b $r = 1, если $a < $b (unsigned)
jal, jr $ra Вызов/возврат процедуры

4.2. Пример кода и разбор

li   $t0, -2
li   $t1,  1
slt  $at, $t0, $t1   # $at = ($t0 < $t1) ? 1 : 0
bnez $at, less_label # если $at != 0 — переход будет
jal my_func
# ...
my_func:
 ; ...
jr $ra
sll $t1, $a0, 2
la  $t2, jumptable
addu $t1, $t1, $t2
lw   $t3, 0($t1)
jr   $t3

5. Краткий итог сравнения ветвлений

Архитектура Флаги/Механизм Условные переходы Рабочий пример
————-——————————-—————————————–——————–
x86 EFLAGS (ZF, SF, OF, CF, PF) JE, JNE, JL, JG, JA, JB… cmp ax, bx; jl label
ARM CPSR (N, Z, C, V) B<cond> (BEQ, BNE, BLT и др.) cmp r0, r1; blt label
MIPS Нет флагов, сравн. в регистре beq, bne, slt+bnez slt $at, $a0, $a1; bnez $at, l

6.1. x86: знаковое сравнение

mov eax, -3         ; FFFFFFFD
mov ebx, 1          ; 00000001
cmp eax, ebx        ; -3 - 1 = -4 (FFFFFFFC)
jg  more_label      ; больше? (signed)
jl  less_label      ; меньше? (signed)
je  equal_label     ; равно?

Флаги:

  1. ZF = 0 (результат не ноль)
  2. SF = 1 (отрицательное)
  3. OF = 0 (нет переполнения)
  4. CF = 1 (беззнаковый «заём»)

'JG' требует ZF=0 и SF=OF: 1 ≠ 0 — перехода НЕ будет. 'JL' требует SF ≠ OF: 1 ≠ 0 — переход БУДЕТ!

6.2. x86: проверка на равенство

mov eax, 7
mov ebx, 7
cmp eax, ebx
je  eq_label  ; ZF=1 — переход БУДЕТ!
jne neq_label ; ZF=0 — перехода не будет

6.3. ARM: сравнение и разбор по флагам

MOV R0, #5
MOV R1, #8
CMP R0, R1      ; результат -3, N=1, Z=0, V=0
BEQ label_eq    ; Z=1?
BNE label_ne    ; Z=0?
BLT label_lt    ; N ≠ V?
После CMP:
  • N = 1 (отрицательно), V = 0, Z = 0
  • BEQ — НЕ сработает; BNE — переход БУДЕТ; BLT — переход БУДЕТ.

6.4. ARM: переполнение

MOV R2, #0x7FFFFFFF
ADD R2, R2, #1             ; R2 = 0x80000000 (отрицательное по знаку)
CMP R2, #0
BEQ label_zero             ; Z=0
BMI label_negative         ; N=1 — БУДЕТ переход!
BVS label_o                ; V=1, было переполнение — БУДЕТ переход!

6.5. MIPS: ветвление через регистр-посредник

li   $t0, -2
li   $t1,  1
slt  $at, $t0, $t1   # if $t0 < $t1, $at = 1
bnez $at, less_label # если 1 — переход БУДЕТ!

  • reverseenengineering/ветвления.txt
  • Последнее изменение: 2025/07/16 21:39
  • Lex