现在我们来逐步分析每一条代码的作用
push ecx 这条代码实际上是为了将esp-4,腾出一个局部变量的栈空间
lea eax,dword ptr ss:[esp] 将刚刚增加的栈空间的地址放入eax中
mov dword ptr ss:[esp],0 初始化这个变量
push eax 将变量地址作为第二个参数入栈
push 0xE47160 将字符串常量"%d"的首地址作为第一个参数入栈
call scanf 调用scanf函数,获取一个整数值
mov eax,dword ptr ss:[esp+8] 将获取到的整数值翻入eax寄存器
cdq 将eax扩展为 edx:eax eax的值保持不变,当eax为正数时edx为0,当eax为负数时, edx为0xFFFFFFFF.
and edx,3 当edx为0xFFFFFFFF时,执行这条语句后 edx为3,当edx为0时执行这条语句 后 edx为0
add eax,edx 将edx与eax向加,并将结果保存到eax
sar eax,2 将eax算术右移2位
neg eax 将eax取负
上面的一系列语句实际上是一个除法,设被除数位x,除数为c,且c为2的幂,那么
\(\frac{x}{c}=x>>2^n\),由于右移是取下整,而当
\(\frac{x}{c}\)为负数时要转成上整,所以要在右移之前加上
\(2^n-1\),之所以能转成上整的原因是$\frac{x}{c}$的余数最小是
-($2^n-1) $,所以只要加上$2^n-1$就能到上一个整数区间,再取下整就能原来取上整一样了。然后再取负,就能得到c为-2的幂的的除法结果了
当c小于0,且为-2的幂
\[\frac{x}{c}向零取整 = -(\frac{x}{-c}向零取整) \]证:
\[当x>=0时,\lceil\frac{x}{c}\rceil = -\lfloor\frac{x}{-c}\rfloor \] \[当x<0时,\lfloor\frac{x}{c}\rfloor=-\lceil\frac{x}{-c}\rceil \]所以上面的除法实际上时x/-4
参考书籍:C++反汇编与逆向分析技术揭秘 第二版