Различия
Показаны различия между двумя версиями страницы.
| Предыдущая версия справа и слева Предыдущая версия | |||
| reverseenengineering:ветвления [2025/07/16 21:34] – Lex | reverseenengineering:ветвления [2025/07/16 21:39] (текущий) – Lex | ||
|---|---|---|---|
| Строка 6: | Строка 6: | ||
| Ветвление (branching) — это переход исполнения программы на другую инструкцию, | Ветвление (branching) — это переход исполнения программы на другую инструкцию, | ||
| - | Безусловный переход: | + | * **Безусловный переход**: :: '' |
| - | Условный переход по флагам: | + | * **Условный переход по флагам**: :: '' |
| - | Переход с возвратом: | + | * **Переход с возвратом**: :: '' |
| - | Циклические переходы: | + | * **Циклические переходы**: :: '' |
| - | Косвенные переходы: | + | * **Косвенные переходы**: :: '' |
| - | Табличные переходы: | + | * **Табличные переходы**: :: через адресацию перехода по таблице (jump table) |
| - | Прерывания и возврат из них: :: '' | + | * **Прерывания и возврат из них**: :: '' |
| Желающие подробности по архитектурам — читайте далее. | Желающие подробности по архитектурам — читайте далее. | ||
| + | |||
| + | |||
| + | ---- | ||
| ==== 2. x86 (Intel) ==== | ==== 2. x86 (Intel) ==== | ||
| Строка 21: | Строка 25: | ||
| После арифметической/ | После арифметической/ | ||
| - | ^ Название | Описание | | ZF (Zero Flag) | Результат 0? (1 если да) | | SF (Sign Flag) | Знак результата (1=минус) | | CF (Carry Flag) | Перенос (важно при беззнаковых) | | OF (Overflow Flag) | Переполнение (важно при знаковых) | | PF (Parity Flag) | Четность (не часто используется) | | + | ^ Название | Описание | |
| + | | ZF (Zero Flag) | Результат 0? (1 если да) | | ||
| + | | SF (Sign Flag) | Знак результата (1=минус) | | ||
| + | | CF (Carry Flag) | Перенос (важно при беззнаковых) | | ||
| + | | OF (Overflow Flag) | Переполнение (важно при знаковых) | | ||
| + | | PF (Parity Flag) | Четность (не часто используется) | | ||
| === 2.2. Основные команды ветвления === | === 2.2. Основные команды ветвления === | ||
| - | ^ Инструкция | Условие | Обозначение | | JE/JZ | ZF = 1 | Равно ("Jump if Equal" | + | ^ Инструкция | Условие | Обозначение | |
| + | | 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. Примеры кода и пояснения === | === 2.3. Примеры кода и пояснения === | ||
| - | ==== Безусловный переход ==== < | + | ==== Безусловный переход ==== |
| + | < | ||
| + | JMP somewhere | ||
| + | </ | ||
| ==== Условный переход и работа флагов ==== | ==== Условный переход и работа флагов ==== | ||
| - | < | + | < |
| - | mov ecx, 123 jmp end | + | mov eax, -3 |
| + | mov ebx, 1 ; ebx = 00000001h | ||
| + | cmp eax, ebx ; вычитание: | ||
| + | jg | ||
| + | jl | ||
| + | je | ||
| - | more_label: | + | mov ecx, 123 |
| + | jmp end | ||
| - | less_label: mov ecx, 2 jmp end | + | more_label: |
| + | mov ecx, 1 | ||
| + | jmp end | ||
| - | equal_label: mov ecx, 3 | + | less_label: |
| + | mov ecx, 2 | ||
| + | jmp end | ||
| - | end: </ | + | equal_label: |
| + | mov ecx, 3 | ||
| - | Анализ флагов: | + | end: |
| + | </ | ||
| - | После ''' | + | **Анализ флагов:** |
| - | ZF = 0 (результат | + | |
| - | SF = 1 (отрицательное) | + | |
| - | OF = 0 (переполнения нет) | + | |
| - | CF = 1 (был "заём" беззнаково) | + | |
| - | ''' | + | |
| - | ''' | + | |
| - | ==== Проверка на равенство ==== < | + | |
| - | ==== Цикл ==== < | + | * После ''' |
| + | * ZF = 0 (результат не ноль) | ||
| + | * SF = 1 (отрицательное) | ||
| + | * OF = 0 (переполнения нет) | ||
| + | * CF = 1 (был " | ||
| + | * ''' | ||
| + | * ''' | ||
| - | ==== Вызов функции ==== < | ||
| - | ==== Косвенный переход ==== < | + | ==== Проверка на равенство ==== |
| + | < | ||
| + | mov eax, 7 | ||
| + | mov ebx, 7 | ||
| + | cmp eax, ebx | ||
| + | je eq_label | ||
| + | jne neq_label ; ZF=0, переход не будет | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Цикл ==== | ||
| + | < | ||
| + | mov cx, 5 | ||
| + | loop_start: | ||
| + | ; ... тело цикла | ||
| + | loop loop_start | ||
| + | </ | ||
| + | |||
| + | |||
| + | ==== Вызов функции ==== | ||
| + | < | ||
| + | call my_function | ||
| + | ; ... | ||
| + | my_function: | ||
| + | ; действия | ||
| + | ret | ||
| + | </ | ||
| + | |||
| + | ==== Косвенный переход ==== | ||
| + | < | ||
| + | jmp [ebx] | ||
| + | </ | ||
| + | |||
| + | |||
| + | ---- | ||
| ==== 3. ARM ==== | ==== 3. ARM ==== | ||
| Строка 65: | Строка 133: | ||
| === 3.1. Флаги === | === 3.1. Флаги === | ||
| - | ^ Флаг | Назначение | | N (Negative) | Результат отрицательный? | + | ^ Флаг | Назначение | |
| + | | N (Negative) | Результат отрицательный? | ||
| + | | Z (Zero) | Результат 0? | | ||
| + | | C (Carry) | Перенос/ | ||
| + | | V (Overflow) | Переполнение для знаковых | | ||
| Инструкции, | Инструкции, | ||
| Строка 73: | Строка 145: | ||
| Любая инструкция ветвления (и почти любая другая) может иметь суффикс условия: | Любая инструкция ветвления (и почти любая другая) может иметь суффикс условия: | ||
| - | ^ Суффикс | Условие | Описание | | 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 | Беззнаково < | | + | ^ Суффикс | Условие | Описание | |
| + | | 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. Примеры кода и пояснения === | === 3.3. Примеры кода и пояснения === | ||
| - | ==== Пример: | + | ==== Пример: |
| + | < | ||
| + | MOV R0, #5 | ||
| + | MOV R1, #8 | ||
| + | CMP R0, R1 ; R0 - R1 = -3 (Negative) | ||
| + | BEQ label_eq | ||
| + | BNE label_ne | ||
| + | BLT label_lt | ||
| + | </ | ||
| - | После CMP: | + | * После CMP: |
| + | * N = 1 (отрицательное) | ||
| + | * Z = 0 (не ноль) | ||
| + | * V = 0 | ||
| + | * C = 0 | ||
| - | N = 1 (отрицательное) | + | * BEQ — не сработает (Z=0) |
| - | Z = 0 (не ноль) | + | * BNE — выполнится (Z=0) |
| - | V = 0 | + | * BLT — N ≠ V (1 ≠ 0) — выполнится |
| - | C = 0 | + | |
| - | BEQ — не сработает (Z=0) | + | |
| - | BNE — выполнится (Z=0) | + | ==== Вызовы процедур ==== |
| + | < | ||
| + | BL myfunc | ||
| + | ; ... | ||
| + | myfunc: | ||
| + | ; ... | ||
| + | BX LR ; возврат | ||
| + | </ | ||
| - | BLT — N ≠ V (1 ≠ 0) — выполнится | + | ==== Табличный переход ==== |
| + | < | ||
| + | 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 | ||
| - | .word case0 .word case1 .word case2 .word case3 | + | default: |
| + | </ | ||
| - | case0: ; ... BX LR | + | ---- |
| - | + | ||
| - | default: </ | + | |
| ==== 4. MIPS ==== | ==== 4. MIPS ==== | ||
| Строка 107: | Строка 212: | ||
| Всё ветвление идёт по значению регистров. | Всё ветвление идёт по значению регистров. | ||
| - | ^ Инструкция | Что выполняет | | beq | + | ^ Инструкция | Что выполняет | |
| - | a | + | | beq $a, $b, label | Переход, |
| - | , | + | | bne $a, $b, label | Переход, |
| - | a,b, label | Переход, | + | | slt $r, $a, $b | $r = 1, если |
| - | a | + | | sltu $r, $a, $b | $r = 1, если |
| - | = | + | | jal, jr $ra |
| - | a=b) | | bne | + | |
| - | a | + | |
| - | , | + | |
| - | a,b, label | Переход, | + | |
| - | r | + | |
| - | , | + | |
| - | r,a, | + | |
| - | b | + | |
| - | ∣ | + | |
| - | b∣r = 1, если | + | |
| - | a | + | |
| - | < | + | |
| - | a<b (signed), иначе 0 | | sltu | + | |
| - | r | + | |
| - | , | + | |
| - | r,a, | + | |
| - | b | + | |
| - | ∣ | + | |
| - | b∣r = 1, если | + | |
| - | a | + | |
| - | < | + | |
| - | a<b (unsigned) | | jal, jr $ra | Вызов/ | + | |
| === 4.2. Пример кода и разбор === | === 4.2. Пример кода и разбор === | ||
| - | ==== Знаковое сравнение ==== < | + | ==== Знаковое сравнение ==== |
| - | t | + | < |
| - | 0 | + | li $t0, -2 |
| - | , | + | li $t1, 1 |
| - | − | + | slt $at, $t0, $t1 |
| - | 2 | + | bnez $at, less_label # если |
| - | l | + | </ |
| - | i | + | |
| - | t0,−2lit1, 1 slt | + | |
| - | a | + | |
| - | t | + | |
| - | , | + | |
| - | at,t0, t1 # at = ( | + | |
| - | t | + | |
| - | 0 | + | |
| - | < | + | |
| - | t0<t1) ? 1 : 0 bnez at, less_label # если at != 0 — переход будет </ | + | |
| - | ==== Вызов функции ==== < | + | ==== Вызов функции ==== |
| + | < | ||
| + | jal my_func | ||
| + | # ... | ||
| + | my_func: | ||
| + | ; ... | ||
| + | jr $ra | ||
| + | </ | ||
| - | ... | + | ==== Табличный переход ==== |
| - | my_func: ; ... jr $ra </ | + | < |
| + | sll $t1, $a0, 2 | ||
| + | la $t2, jumptable | ||
| + | addu $t1, $t1, $t2 | ||
| + | lw $t3, 0($t1) | ||
| + | jr | ||
| + | </ | ||
| - | ==== Табличный переход ==== < | + | ---- |
| - | t | + | |
| - | 1 | + | |
| - | , | + | |
| - | t1,a0, 2 la | + | |
| - | t | + | |
| - | 2 | + | |
| - | , | + | |
| - | j | + | |
| - | u | + | |
| - | m | + | |
| - | p | + | |
| - | t | + | |
| - | a | + | |
| - | b | + | |
| - | l | + | |
| - | e | + | |
| - | a | + | |
| - | d | + | |
| - | d | + | |
| - | u | + | |
| - | t2, | + | |
| - | t | + | |
| - | 1 | + | |
| - | , | + | |
| - | t1,t2 lw | + | |
| - | t | + | |
| - | 3 | + | |
| - | , | + | |
| - | 0 | + | |
| - | ( | + | |
| - | t3,0(t1) jr $t3 </ | + | |
| === 5. Краткий итог сравнения ветвлений === | === 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< | + | | x86 | EFLAGS (ZF, SF, OF, CF, PF) | JE, JNE, JL, JG, JA, JB... |
| - | MIPS Нет флагов, | + | | ARM | CPSR (N, Z, C, V) | B< |
| - | a | + | | MIPS |
| - | t | + | |
| - | , | + | |
| - | at, | + | |
| - | a | + | ---- |
| - | 1 | + | |
| - | ; | + | |
| - | b | + | |
| - | n | + | |
| - | e | + | |
| - | z | + | |
| - | a1;bnezat, l | + | |
| ===== 6. Разбор переходов с анализом флагов (на примере x86, ARM, MIPS) ===== | ===== 6. Разбор переходов с анализом флагов (на примере x86, ARM, MIPS) ===== | ||
| === 6.1. x86: знаковое сравнение === | === 6.1. x86: знаковое сравнение === | ||
| - | < | + | < |
| - | Флаги: | + | mov eax, -3 |
| + | mov ebx, 1 ; 00000001 | ||
| + | cmp eax, ebx ; -3 - 1 = -4 (FFFFFFFC) | ||
| + | jg more_label | ||
| + | jl less_label | ||
| + | je equal_label | ||
| + | </ | ||
| - | ZF = 0 (результат не ноль) | + | **Флаги: |
| - | SF = 1 (отрицательное) | + | - ZF = 0 (результат не ноль) |
| - | OF = 0 (нет переполнения) | + | |
| - | CF = 1 (беззнаковый " | + | |
| - | ''' | + | |
| + | |||
| + | ''' | ||
| ''' | ''' | ||
| - | === 6.2. x86: проверка на равенство === < | + | --- |
| + | |||
| + | === 6.2. x86: проверка на равенство === | ||
| + | < | ||
| + | mov eax, 7 | ||
| + | mov ebx, 7 | ||
| + | cmp eax, ebx | ||
| + | je eq_label | ||
| + | jne neq_label ; ZF=0 — перехода не будет | ||
| + | </ | ||
| + | |||
| + | --- | ||
| === 6.3. ARM: сравнение и разбор по флагам === | === 6.3. ARM: сравнение и разбор по флагам === | ||
| - | < | + | < |
| + | MOV R0, #5 | ||
| + | MOV R1, #8 | ||
| + | CMP R0, R1 ; результат -3, N=1, Z=0, V=0 | ||
| + | BEQ label_eq | ||
| + | BNE label_ne | ||
| + | BLT label_lt | ||
| + | </ | ||
| == После CMP: == | == После CMP: == | ||
| + | * N = 1 (отрицательно), | ||
| + | * BEQ — НЕ сработает; | ||
| + | |||
| + | --- | ||
| + | |||
| + | === 6.4. ARM: переполнение === | ||
| + | < | ||
| + | MOV R2, #0x7FFFFFFF | ||
| + | ADD R2, R2, #1 ; R2 = 0x80000000 (отрицательное по знаку) | ||
| + | CMP R2, #0 | ||
| + | BEQ label_zero | ||
| + | BMI label_negative | ||
| + | BVS label_o | ||
| + | </ | ||
| + | |||
| + | --- | ||
| + | |||
| + | === 6.5. MIPS: ветвление через регистр-посредник === | ||
| + | < | ||
| + | li $t0, -2 | ||
| + | li | ||
| + | slt $at, $t0, $t1 # if $t0 < $t1, $at = 1 | ||
| + | bnez $at, less_label # если 1 — переход БУДЕТ! | ||
| + | </ | ||
| - | N = 1 (отрицательно), | + | --- |
| - | BEQ — НЕ сработает; | + | |
| - | === 6.4. ARM: переполнение === < | + | |
| - | === 6.5. MIPS: ветвление через регистр-посредник === < | ||
| - | t | ||
| - | 0 | ||
| - | , | ||
| - | − | ||
| - | 2 | ||
| - | l | ||
| - | i | ||
| - | t0, | ||
| - | a | ||
| - | t | ||
| - | , | ||
| - | at,t0, t1 # if t0 < | ||
| - | t | ||
| - | 1 | ||
| - | , | ||
| - | t1,at = 1 bnez $at, less_label # если 1 — переход БУДЕТ! </ | ||