if
跳转
特征
- 不满足向下跳转,汇编的跳转条件和源码中的逻辑取反。
if-else
->cmp-比较取反+jmp-标签
- 有可能使用
return
优化if
最后的jmp
跳转 - 单分支很难优化,双分支、多分支优化空间大。
单分支
#include <cstdio>#include <cstdint>
void test_if(uint32_t n1, int32_t n2){ // 单分支 if(n1 >= 10){ printf("n1 >= 10, n1: %u", n1); } if(n1 >= 20 && n2 < -15){ printf("n1 >= 20 && n2 < -15, n1: %u, n2: %d", n1, n2); } if(n1 >= 30 || n2 >= -15){ printf("n1 >= 20 && n2 < -15, n1: %u, n2: %d", n1, n2); } return;}
unsigned __int64 `__local_stdio_printf_options'::`2'::_OptionsStorage DQ 01H DUP (?) ; `__local_stdio_printf_options'::`2'::_OptionsStorage`string' DB 'n' DB '1 >= 20 && n2 < -15, n1: %u, n2: %d', 00H ; `string'`string' DB 'n1 >= 10, n1: %u', 00H ; `string'
_n1$ = 8 ; size = 4_n2$ = 12 ; size = 4void test_if(unsigned int,int) PROC ; test_if, COMDAT push esi mov esi, DWORD PTR _n1$[esp] push edi cmp esi, 10 ; 0000000aH jb SHORT $LN2@test_if push esi push OFFSET `string' call _printf add esp, 8$LN2@test_if: mov edi, DWORD PTR _n2$[esp+4] cmp esi, 20 ; 00000014H jb SHORT $LN3@test_if cmp edi, -15 ; fffffff1H jge SHORT $LN3@test_if push edi push esi push OFFSET `string' call _printf add esp, 12 ; 0000000cH$LN3@test_if: cmp esi, 30 ; 0000001eH jae SHORT $LN5@test_if cmp edi, -15 ; fffffff1H jl SHORT $LN4@test_if$LN5@test_if: push edi push esi push OFFSET `string' call _printf add esp, 12 ; 0000000cH$LN4@test_if: pop edi pop esi ret 0void test_if(unsigned int,int) ENDP ; test_if

- 跳转语句取反后是原本的
if
判断条件。
&&
连接

- 每个表达式都取反。
||
定式
最后一个||
中的条件取反。
逆向还原时,最后一个条件取反


双分支
三目运算符优化

代码外提-体积优化

提出公共部分,逆向时不需要管。


减少跳转


?_OptionsStorage@?1??__local_stdio_printf_options@@9@4_KA DQ 01H DUP (?) ; `__local_stdio_printf_options'::`2'::_OptionsStorage??_C@_08IDOHMDJP@not?5all?$CB@ DB 'not all!', 00H ; `string'??_C@_0BE@CAHAPFEI@n1?5?$DO?51?5?$CG?$CG?5n2?5?$DM?5100?6@ DB 'n1 > 1 && ' DB 'n2 < 100', 0aH, 00H ; `string'??_C@_0BE@MPEFODFA@n1?5?$DO?$DN?55?5?$HM?$HM?5n2?5?$DM?510?6@ DB 'n1 >= 5' DB ' || n2 < 10', 0aH, 00H ; `string'??_C@_0BG@KGLBGBHM@n1?5?$DO?$DN?510?5?$HM?$HM?5n2?5?$DM?5?915?6@ DB 'n1 >' DB '= 10 || n2 < -15', 0aH, 00H ; `string'
_n1$ = 8 ; size = 4_n2$ = 12 ; size = 4?test_if_else2@@YAXIH@Z PROC ; test_if_else2, COMDAT mov eax, DWORD PTR _n1$[esp-4] cmp eax, 10 ; 0000000aH jae SHORT $LN4@test_if_el mov ecx, DWORD PTR _n2$[esp-4] cmp ecx, -15 ; fffffff1H jl SHORT $LN4@test_if_el ; if(n1 >= 10 || n2 < -15) {printf("n1 >= 10 || n2 < -15\n"); return;}
cmp eax, 5 jae SHORT $LN7@test_if_el cmp ecx, 10 ; 0000000aH jl SHORT $LN7@test_if_el ; if(n1 >= 5 || n2 < 10) {printf("n1 >= 5 || n2 < 10\n"); return;}
cmp eax, 1 jbe SHORT $LN8@test_if_el cmp ecx, 100 ; 00000064H jge SHORT $LN8@test_if_el ; if(n1 > 1 && n2 < 100) {printf("n1 > 1 && n2 < 100\n"); return;}
mov eax, OFFSET ??_C@_0BE@CAHAPFEI@n1?5?$DO?51?5?$CG?$CG?5n2?5?$DM?5100?6@ push eax call _printf
; printf("not all!"); ; return;
pop ecx ret 0$LN8@test_if_el: mov eax, OFFSET ??_C@_08IDOHMDJP@not?5all?$CB@ push eax call _printf pop ecx ret 0$LN7@test_if_el: mov eax, OFFSET ??_C@_0BE@MPEFODFA@n1?5?$DO?$DN?55?5?$HM?$HM?5n2?5?$DM?510?6@ push eax call _printf pop ecx ret 0$LN4@test_if_el: mov eax, OFFSET ??_C@_0BG@KGLBGBHM@n1?5?$DO?$DN?510?5?$HM?$HM?5n2?5?$DM?5?915?6@ push eax call _printf pop ecx ret 0?test_if_else2@@YAXIH@Z ENDP ; test_if_else2
switch
分支
case
小于等于3个



大于3个分支
当大于三个分支且case
中最大值和最小值的差值在255
以内,此时会生成跳表。




跳表优化
双表优化
条件:最大值和最小值差值在0-255
之间。
增加新的跳表下标表。


折半优化-二叉树优化
条件:差值较大
先判断中间条件。



还原的时候也算是比较清晰的。
循环
所有循环的特征都是上跳。
do-while
循环
特征:先执行再判断,向上跳转。
优化空间:平坦优化(可能)。
Debug、Release区别:无。

while
循环
特征:先判断再执行,向上跳转。
Debug、Release区别:Release优化为if + do-while
循环(大部分情况)。

for
循环
MSVC+Debug版:1. 初始化 2. 步长 3. 比较 4. 循环体执行 5. 跳转2

MSVC+Release版:(初始值确定)优化为do-while
版。
