- 第一章 CPU 简介
- 第二章 Hello,world!
- 第三章 函数开始和结束
- 第四章 栈
- Chapter 5 printf() 与参数处理
- Chapter 6 scanf()
- CHAPER7 访问传递参数
- Chapter 8 一个或者多个字的返回值
- Chapter 9 指针
- Chapter 10 条件跳转
- 第 11 章 选择结构 switch()/case/default
- 第 12 章 循环结构
- 第 13 章 strlen()
- Chapter 14 Division by 9
- chapter 15 用 FPU 工作
- Chapter 16 数组
- Chapter 17 位域
- 第 18 章 结构体
- 19 章 联合体
- 第二十章 函数指针
- 第 21 章 在 32 位环境中的 64 位值
- 第二十二章 SIMD
- 23 章 64 位化
- 24 章 使用 x64 下的 SIMD 来处理浮点数
- 25 章 温度转换
- 26 章 C99 的限制
- 27 章 内联函数
- 第 28 章 得到不正确反汇编结果
- 第 29 章 花指令
- 第 30 章 16 位 Windows
- 第 31 章 类
- 三十二 ostream
- 34.2.2 MSVC
- 34.2.3 C++ 11 std::forward_list
- 34.3 std::vector
- 34.4 std::map and std::set
文章来源于网络收集而来,版权归原创者所有,如有侵权请及时联系!
14.4 得到除数
14.4.1 变形#1
通常,代码具有这样一种形式
#!bash
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
#!bash
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 位除法来说,原理是一样的,但是应该使用 2^64 来代替 2^32。
#!bash
uint64_t f1234(uint64_t a)
{
return a/1234;
};
清单 14.7:MSVC2012/Ox
#!bash
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
忽略算数移位的变形也是存在的
#!bash
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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论