reverseenengineering:ветвления

Различия

Показаны различия между двумя версиями страницы.

Ссылка на это сравнение

Следующая версия
Предыдущая версия
reverseenengineering:ветвления [2025/06/23 23:56] – создано Lexreverseenengineering:ветвления [2025/07/16 21:39] (текущий) Lex
Строка 1: Строка 1:
 ====== Ветвления ====== ====== Ветвления ======
 +====== Ветвления в ассемблере: архитектуры 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. x86 (Intel) ====
 +
 +=== 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. Примеры кода и пояснения ===
 +
 +==== Безусловный переход ====
 +<code>
 +JMP somewhere
 +</code>
 +
 +==== Условный переход и работа флагов ====
 +
 +<code>
 +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:
 +</code>
 +
 +**Анализ флагов:**
 +
 +  * После '''cmp eax, ebx''':
 +    * ZF = 0 (результат не ноль)
 +    * SF = 1 (отрицательное)
 +    * OF = 0 (переполнения нет)
 +    * CF = 1 (был "заём" беззнаково)
 +  * '''jg''': требует ZF=0 и SF=OF (1 ≠ 0 -- не равно, перехода нет)
 +  * '''jl''': SF ≠ OF? (1 ≠ 0 — переход будет!)
 +
 +
 +==== Проверка на равенство ====
 +<code>
 +mov eax, 7
 +mov ebx, 7
 +cmp eax, ebx
 +je  eq_label  ; ZF=1, переход будет
 +jne neq_label ; ZF=0, переход не будет
 +</code>
 +
 +
 +==== Цикл ====
 +<code>
 +mov cx, 5
 +loop_start:
 + ; ... тело цикла
 +loop loop_start
 +</code>
 +
 +
 +==== Вызов функции ====
 +<code>
 +call my_function
 +; ...
 +my_function:
 + ; действия
 +ret
 +</code>
 +
 +==== Косвенный переход ====
 +<code>
 +jmp [ebx]   ; ebx — адрес новой инструкции
 +</code>
 +
 +
 +----
 +
 +==== 3. ARM ====
 +
 +=== 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. Примеры кода и пояснения ===
 +
 +==== Пример: ====
 +<code>
 +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 ?
 +</code>
 +
 +* После CMP:
 +  * N = 1 (отрицательное)
 +  * Z = 0 (не ноль)
 +  * V = 0
 +  * C = 0
 +
 +* BEQ — не сработает (Z=0)
 +* BNE — выполнится (Z=0)
 +* BLT — N ≠ V (1 ≠ 0) — выполнится
 +
 +==== Вызовы процедур ====
 +<code>
 +BL  myfunc     ; вызов с занесением адреса возврата в LR
 +; ...
 +myfunc:
 + ; ...
 + BX LR         ; возврат
 +</code>
 +
 +==== Табличный переход ====
 +<code>
 +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:
 +</code>
 +
 +----
 +
 +==== 4. MIPS ====
 +
 +=== 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. Пример кода и разбор ===
 +
 +==== Знаковое сравнение ====
 +<code>
 +li   $t0, -2
 +li   $t1,  1
 +slt  $at, $t0, $t1   # $at = ($t0 < $t1) ? 1 : 0
 +bnez $at, less_label # если $at != 0 — переход будет
 +</code>
 +
 +==== Вызов функции ====
 +<code>
 +jal my_func
 +# ...
 +my_func:
 + ; ...
 +jr $ra
 +</code>
 +
 +==== Табличный переход ====
 +<code>
 +sll $t1, $a0, 2
 +la  $t2, jumptable
 +addu $t1, $t1, $t2
 +lw   $t3, 0($t1)
 +jr   $t3
 +</code>
 +
 +----
 +
 +=== 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. Разбор переходов с анализом флагов (на примере x86, ARM, MIPS) =====
 +
 +=== 6.1. x86: знаковое сравнение ===
 +
 +<code>
 +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     ; равно?
 +</code>
 +
 +**Флаги:**
 +  - ZF = 0 (результат не ноль)
 +  - SF = 1 (отрицательное)
 +  - OF = 0 (нет переполнения)
 +  - CF = 1 (беззнаковый "заём")
 +
 +'''JG''' требует ZF=0 и SF=OF: 1 ≠ 0 — перехода НЕ будет.  
 +'''JL''' требует SF ≠ OF: 1 ≠ 0 — переход БУДЕТ!
 +
 +---
 +
 +=== 6.2. x86: проверка на равенство ===
 +<code>
 +mov eax, 7
 +mov ebx, 7
 +cmp eax, ebx
 +je  eq_label  ; ZF=1 — переход БУДЕТ!
 +jne neq_label ; ZF=0 — перехода не будет
 +</code>
 +
 +---
 +
 +=== 6.3. ARM: сравнение и разбор по флагам ===
 +
 +<code>
 +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?
 +</code>
 +
 +== После CMP: ==
 +  * N = 1 (отрицательно), V = 0, Z = 0  
 +  * BEQ — НЕ сработает; BNE — переход БУДЕТ; BLT — переход БУДЕТ.
 +
 +---
 +
 +=== 6.4. ARM: переполнение ===
 +<code>
 +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, было переполнение — БУДЕТ переход!
 +</code>
 +
 +---
 +
 +=== 6.5. MIPS: ветвление через регистр-посредник ===
 +<code>
 +li   $t0, -2
 +li   $t1,  1
 +slt  $at, $t0, $t1   # if $t0 < $t1, $at = 1
 +bnez $at, less_label # если 1 — переход БУДЕТ!
 +</code>
 +
 +---
 +
  • reverseenengineering/ветвления.1750697785.txt.gz
  • Последнее изменение: 2025/06/23 23:56
  • Lex