表达式求值也就是把各类加减乘除的运算都看一遍,这里主要记录的是Release版中的一些优化,各种优化手段我感觉有x86的逆向基础还是会比较好理解的,因为很多都很类似。
首先看一下加减的运算,这里主要可能会出现常量折叠和常量传播等优化手段
int main(int argc,char* argv[])
{
int n1 = argc;
int n2 = 0;
scanf("%d", &n2);
n1 = n1 - 100;
n1 = n1 + 5 - n2 ;
printf("n1 = %d \r\n", n1);
return 0;
}
汇编代码如下(armeabi-v7a)
.text:0000060C MOV R4, R0 ;n1 = argc
.text:00000610 MOV R1, SP ;scanf的参数二
.text:0000061A MOVS R0, #0
.text:0000061C STR R0, [SP] ;n2=0 初始化
.text:0000061E LDR R0, =(unk_768 - 0x624)
.text:00000620 ADD R0, PC ; unk_768 ; format
.text:00000622 BLX scanf
.text:00000626 LDR R0, [SP] ;r0 = n2
.text:00000628 SUBS R0, R4, R0 ;r0 = argc - n2
.text:0000062A SUB.W R1, R0, #0x5F //r1 = r0 - 0x5F = argc - n2 - 95
.text:0000062E LDR R0, =(aN1D - 0x634)
.text:00000630 ADD R0, PC ; "n1 = %d \r\n"
.text:00000632 BLX printf
通过上面可以看到,对于最后的n1的结果是可以优化的
n1 = n1 - 100
n1 = n1 + 5 - n2
= n1 - 100 + 5 - n2
= n1 - 95 - n2
= n1 - n2 - 95
而n1的值就是argc,所以上面的计算结果就使用argc减去n2,最后再减去95获取结果。
下面再来看乘法
int main(int argc,char* argv[])
{
int n1 = argc;
int n2 = 0;
scanf("%d", &n2);
printf("n1 * 15 = %d\n", n1 * 15); //变量乘常量 ( 常量值为非 2 的幂 )
printf("n1 * 16 = %d\n", n1 * 16); //变量乘常量 ( 常量值为 2 的幂 )
printf("2 * 2 = %d\n", 2 * 2); //两常量相乘
printf("n2 * 4 + 5 = %d\n", n2 * 4 + 5); //混合运算
printf("n1 * n2 = %d\n", n1 * n2); //两变量相乘
return 0;
}
汇编代码如下(armeabi-v7a)
.text:00000620 LDR R0, =(printf_ptr - 0x62A)
.text:00000622 RSB.W R1, R4, R4,LSL#4 //r1 = r4 << 4 - r4 = r4 * 16 - r4 = r4 * 15
.text:00000626 ADD R0, PC ; printf_ptr
.text:00000628 LDR R6, [R0] ; printf
.text:0000062A LDR R0, =(aN115D - 0x630)
.text:0000062C ADD R0, PC ; "n1 * 15 = %d\n"
.text:0000062E BLX R6 ; printf
.text:00000630 LDR R0, =(aN116D - 0x638)
.text:00000632 LSLS R1, R4, #4 //左移4位,相当于直接乘以16
.text:00000634 ADD R0, PC ; "n1 * 16 = %d\n"
.text:00000636 BLX R6 ; printf
.text:00000638 LDR R0, =(a22D - 0x640)
.text:0000063A MOVS R1, #4 //这里常量折叠直接得出结果4
.text:0000063C ADD R0, PC ; "2 * 2 = %d\n"
.text:0000063E BLX R6 ; printf
.text:00000640 LDR R1, [SP] ;获取n2
.text:00000642 MOVS R0, #5
.text:00000644 ADD.W R1, R0, R1,LSL#2 //r1 = 5 + n2 << 2 = 5 + n2*4
.text:00000648 LDR R0, =(aN245D - 0x64E)
.text:0000064A ADD R0, PC ; "n2 * 4 + 5 = %d\n"
.text:0000064C BLX R6 ; printf
.text:0000064E LDR R0, [SP]
.text:00000650 MUL.W R1, R0, R4 //n1*n2
.text:00000654 LDR R0, =(aN1N2D - 0x65A)
.text:00000656 ADD R0, PC ; "n1 * n2 = %d\n"
.text:00000658 BLX R6 ; printf
这里主要说的就是第一个表达式,使