除数为无符号2的幂

快速识别
x >> n(无符号右移)
快速还原
x2n由于n=4,所以例子中的除法是x16
除数为无符号非2的幂

快速识别
xc=x∗M>>n,且使用无符号乘法时
快速还原
c=2nM
本例中n=33,M=0xAAAAAAAB
c=2330xAAAAAAAB=2.9999999996507540345598531381041
向上取整为3,所以这里的除法是x3
通用还原
由于xc=x∗2nc∗12n所以2nc=M
c=2nM=2330xAAAAAAAB=2.9999999996507540345598531381041
向上取整为3,所以这里的除法是x3
除数为无符号非2的幂第二种

快速识别
xc={[x−(x∗M>>32)>>n1]+x∗M>>32}>>n2,且使用无符号乘法时
快速还原
M=2nc−232,n=n1+n2+32
c=2nM+232
在本例中n=n1+n2+32=1+2+32=35,M=0x24924925
c=2nM+232=2350x24924925+232=6.9999999993888195604619552997935
向上取整为7,所以这里的除法是x7
通用还原
上面的代码所为用下面的数学公式表达
x−x∗M2322+x∗M23222=x∗232+M235
由于xc=x∗2nc∗12n所以2nc=232+M
c=2nM+232=2350x24924925+232=6.9999999993888195604619552997935
向上取整为7,所以这里的除法是x7
除数为有符号2的幂

快速识别
如果x≥0,则x2n=x>>n,如果x<0,则x2n=[x+(2n−1)]>>n
快速还原
c=2n=23=8,所以这里的除法是x8
通用还原
由于sar
是向下取整,而xc为负数需要向上取整,所以需要加上2n−1,为什么是加上2n−1呢,因为 2n=c,而xc余数的最小值为−c−1c,所以加上c−1就能起到加1的效果,加一后取下整,等于原来的值取上整。
除数为有符号非2的幂第一种

快速识别
如果x≥0,则xc=x∗M>>n,如果x<0,则xc=[x∗M>>n]+1
快速还原
c=2nM=23338E38E39=8.9999999989522621036795594143123
向上取整为9,所以这里的除法是x9
通用还原
由于xc=x∗2nc∗12n所以2nc=M
c=2nM=23338E38E39=8.9999999989522621036795594143123
向上取整为9,所以这里的除法是x3
除数为有符号非2的幂第二种

快速识别
如果x≥0,则xc=[x∗M+x∗232]>>n,如果x<0,则xc={[x∗M+x∗232]>>n}+1
快速还原
c=2nM=2350x88888889=14.999999996944097802665530336711
向上取整为9,所以这里的除法是x15
通用还原
上面的代码所为用下面的数学公式表达
x∗M+x∗232235=x∗(M+232)∗1235
由于xc=x∗2nc∗12n所以2nc=232+M
c=2nM+232=23588888889+232=2350x88888889=14.999999996944097802665530336711
注:上面的88888889
是有符号数
向上取整为9,所以这里的除法是x15
除数为有符号负2幂

快速识别
如果x≥0,则xc=−(x>>n),如果x<0,则x2n=−{[x+(2n−1)]>>n}
快速还原
c=−2n=−22=−4
通用还原
仔细观察,这里无非就是将除数为2的幂取负而已,只要把除数为2的幂的除数求出来,再取负就行
除数为有符号非负2的幂的第一种

快速识别
如果x≥0,则xc=x∗M>>n,如果x<0,则xc=[x∗M>>n]+1,但此时注意 这里的M是个负数,这一点是用来区分除数为有符号非2的幂的第一种的优化的
快速还原
c=2nM=23399999999=−23366666667=−⌈4.9999999982537701732058415050132⌉=−5
所以这里的除法是x−5
通用还原
由于xc=x∗2nc∗12n所以2nc=M
c=2nM=23399999999=−23366666667=−⌈4.9999999982537701732058415050132⌉=−5
所以这里的除法是x−5
除数为有符号非负2的幂的第一种Gcc版

快速识别
如果x≥0,则xc=−(x∗M>>n),如果x<0,则xc=−[(x∗M>>n)+1]
快速还原
−c=2nM=23366666667=⌈4.9999999982537701732058415050132⌉=5
c=−5所以这里的除法是x−5
通用还原
上面的代码所为用下面的数学公式表达
−x∗M2n=x∗−M∗12n
由于xc=x∗2nc∗12n所以2nc=−M
c=2n−M=23399999999=−23366666667=−⌈4.9999999982537701732058415050132⌉=−5
所以这里的除法是x−5
除数为有符号非负2的幂的第二种

快速识别
如果x≥0,则xc=(x∗M−X∗232)>>n,如果x<0,则xc=[(x∗M−X∗232)>>n]+1
快速还原
c=2nM−232=2346DB6DB6D−232=234FFFFFFFF6DB6DB6D=−23492492493=−⌈6.9999999979627318686215638099758⌉=−7
$c = -7 所以这里的除法是\frac{x}{-7}$
通用还原
上面的代码所为用下面的数学公式表达
x∗M−x∗2322n=x∗(M−232)∗12n
由于xc=x∗2nc∗12n所以2nc=M−232
c=2nM−232=2346DB6DB6D−232=234FFFFFFFF6DB6DB6D=−23492492493=−⌈6.9999999979627318686215638099758⌉=−7
所以这里的除法是x−7
除数为有符号非负2的幂的第二种Gcc版

快速识别
如果x≥0,则xc=−[(x∗M+x∗232)>>n],如果x<0,则xc=−{[(x∗M+x∗232)>>n]+1}
快速还原
−c=2nM+232=23492492493+232=2340x92492493=⌈6.9999999979627318686215638099758⌉=7
c=−7所以这里的除法是x−7
通用还原
上面的代码所为用下面的数学公式表达
−x∗M+x∗2322n=x∗(−M−232)∗12n
由于xc=x∗2nc∗12n所以2nc=−M−232
c=2n−M−232=2346DB6DB6D−232=234FFFFFFFF6DB6DB6D=−2340x92492493=−⌈6.9999999979627318686215638099758⌉=−7
所以这里的除法是x−7
至此除法优化完毕,一共有11中优化,除了2的幂(包括无符号)和-2的幂这三种,其他都是xc=x∗2nc∗12n的变种优化,通过比对代码和公式,即可还原
参考资料:c++汇编与逆向分析技术解密
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步