- 第一章 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.3 工作原理
下面展示的是怎样用乘法来优化除法,其中借助了 2^n 的阶乘
M 是一个 magic 系数
M 的计算过程
因此这些代码片段通常具有这样的形式
n 可以是任意数,可能是 32(那么这样运算结果的高位部分从 EX 或者 RDX 寄存器中获取),可能是 31(这种情况下乘法结果的高位部分结果右移)
n 的选取是为了减少错误。
当进行有符号数除法运算,乘法结果的符号也会被放到输出结果中。
下面来看看不同之处。
#!bash
int f3_32_signed(int a)
{
return a/3;
};
unsigned int f3_32_unsigned(unsigned int a)
{
return a/3;
};
在无符号版本的函数中,magic 系数是 0xAAAAAAAB,乘法结果被 2^3*3 除。
在有符号版本的函数中,magic 系数是 0x55555556,乘法结果被 2^32 除。
符号来自于乘法结果:高 32 位的结果右移 31 位(将符号位放在 EAX 中最不重要的位置)。如果最后结果为负,则会设置为 1。
清单 14.4:MSVC 2012/OX
#!bash
_f3_32_unsigned PROC
mov eax, -1431655765 ; aaaaaaabH
mul DWORD PTR _a$[esp-4] ; unsigned multiply
shr edx, 1
mov eax, edx
ret 0
_f3_32_unsigned ENDP
_f3_32_signed PROC
mov eax, 1431655766 ; 55555556H
imul DWORD PTR _a$[esp-4] ; signed multiply
mov eax, edx
shr eax, 31 ; 0000001fH
add eax, edx ; add 1 if sign is negative
ret 0
_f3_32_signed ENDP
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

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