逆向-除法优化上

本文介绍了除法优化的几种情况,重点讨论了除数为2的幂和非2的幂时的优化策略。通过数学公式和汇编代码解析,解释了如何在正数和负数情况下进行优化,包括右移运算在不同情况下的应用,以及如何处理负数右移导致的向下取整问题。文章还提到了Magic Number的概念及其在优化中的作用。
摘要由CSDN通过智能技术生成

上一篇说完加减乘的优化,这篇来说说除法,首先先打个铺垫,除法的优化涉及到各种数学公式,这里我们主要探讨一下结论,具体的证明可以参考《C++反汇编与逆向分析技术揭秘》,这里做一个总结。

首先,如果除数为变量时,是没有任何的优化空间的,所以老老实实的上对应的汇编代码即可,所以就不讨论了。下面主要来讨论下除数为常量的情况,并且这个常量还是正数,负数情况下一篇博客介绍。

首先,先来看一下需要讨论的情况

除数为常量-除数为正数情况
    1.除数为2的幂-被除数无符号
    2.除数为2的幂-被除数有符号
    3.除数为非2的幂 - 被除数无符号	
    	根据Magic Number的是否需要进位(下面简称M)
            3.1 M值无进位
            3.2 M值有进位
    4.除数为非2的幂 - 被除数有符号
    	根据Magic Number的正负情况(下面简称M)
            4.1 M值为正数
            4.2 M值为负数

这个情况是有那么点多,不过其实总体算下来,应该就两套公式,分别为除数为2的幂和除数为非2的幂两套,只是情况不同,有些公式的变种而已。还有对于Magic Number这个概念,后面会提的,这里留个先个印象就好

首先,先来打一些基础的铺垫

1.乘法有无符号混合为有符号乘法(IMUL)
2.除法有无符号混合为无符号除法(DIV)
3.计算机中的除法为向零取整
4.移位运算是向下取整(不大于的关系)

首先对于向上取整和向下取整,对于计算机的同学应该十分熟悉了,其实对于向零取整其实就是往中间的零值靠齐

3 / 2 = 1.5   //往零靠齐取1    3/2=1
-3 / 2 = -1.5 //往零靠齐取-1  -3/2=-1

还有对于第四点一定要理解,因为在下面会有用到,移位运算,这里说的更细一点吧,对于除法需要用到的就是右移运算,你可以这样想,当二进制往右移动,那么肯定有一些位需要丢失,那么肯定是不大于的关系。

假设我们需要计算-5/2,那么我们很容易想到,使用右移一位,那么如下结果计算出来为-3(因为向下取整的原因),如果此时可以向上取整(向零取整),那么就符合我们的数学运算结果了。

-5>>1
FFFFFFFB     >> 1
.......1011  >> 1
.......1101  -> FFFFFFFD = -3

首先,先来说下除数为2的幂的情况,这里我们可以使用右移,但是右移,对于负数的情况就会出现上面的问题,如下代码

	for(int i=-20;i <= 20;++i)
	{
		printf("%d / 8 = %d\r\n",i,i/8);
		printf("%d >> 3 = %d\r\n\r\n",i,i>>3);
	} 

打印运算结果,其实可以发现,在负数中的确会有问题,那么我们可以这样子来调整一下,加上n-1的值,n为除数

	for(int i=-20;i <= 20;++i)
	{
		printf("%d / 8 = %d\r\n",i,i/8);
		if(i >= 0)
			printf("%d >> 3 = %d\r\n\r\n",i,i>>3);
		else
			printf("%d >> 3 = %d\r\n\r\n",i,(i+8-1)>>3);
	} 

部分结果

-13 / 8 = -1
-13 >> 3 = -1

-12 / 8 = -1
-12 >> 3 = -1

-11 / 8 = -1
-11 >> 3 = -1

-10 / 8 = -1
-10 >> 3 = -1

此时可以发现,结果吻合了,那么为什么加上n-1呢,你可以这样子想,负数右移与实际数学运算不符合的原因是因为右移向下取整了,那么如何才能向上取整呢,其实我们先来加上一个n值,你会发现大部分情况是对的

printf("%d >> 3 = %d\r\n\r\n",i,(i+8)>>3);

不正确的情况如下:

-16 / 8 = -2
-16 >> 3 = -1

-8 / 8 
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值