14.4 得到除数
14.4.1 变形#1
通常,代码具有这样一种形式
mov eax, MAGICAL CONSTANT
imul input value
sar edx, SHIFTING COEFFICIENT ; signed division by 2^x using arithmetic shift right
mov eax, edx
shr eax, 31
add eax, edx
我们将32位的magic系数表示为M,移位表示为C,除数表示为D
我们得到的除法是
举个例子
清单14.5:优化模式 MSVC2012
mov eax, 2021161081 ; 78787879H
imul DWORD PTR _a$[esp-4]
sar edx, 3
mov eax, edx
shr eax, 31 ; 0000001fH
add eax, edx
即
比32位的数字大,为了方便,于是我们使用用Wolfram Mathematica软件。
In[1]:=N[2^(32+3)/2021161081]
Out[1]:=17.
因此例子中的代码得到结果是17。
对于64位除法来说,原理是一样的,但是应该使用264来代替232。
uint64_t f1234(uint64_t a)
{
return a/1234;
};
清单14.7:MSVC2012/Ox
f1234 PROC
mov rax, 7653754429286296943 ; 6a37991a23aead6fH
mul rcx
shr rdx, 9
mov rax, rdx
ret 0
f1234 ENDP
清单14.8:Wolfram Mathematica
In[1]:=N[2^(64+9)/16^^6a37991a23aead6f]
Out[1]:=1234.
14.4.2 变形#2
忽略算数移位的变形也是存在的
mov eax, 55555556h ; 1431655766
imul ecx
mov eax, edx
shr eax, 1Fh
更加简洁
在这个例子中
再用一次Wolfram Mathematica
In[1]:=N[2^32/16^^55555556]
Out[1]:=3.
得到的除数是3
当前内容版权归 Dennis Yurichev 或其关联方所有,如需对内容或内容相关联开源项目进行关注与资助,请访问 Dennis Yurichev .