在没有 DIV 操作码的情况下,任何数字(16 位)在汇编中除以 3 的更快方法
Posted
技术标签:
【中文标题】在没有 DIV 操作码的情况下,任何数字(16 位)在汇编中除以 3 的更快方法【英文标题】:Faster way for any number(16bit) divide by 3 in assembly without DIV opcode 【发布时间】:2013-02-23 11:08:30 【问题描述】:我想将一个无符号整数除以 3,在 8086 汇编或类似程序中,我不想使用 DIV 操作码的任何更快的方法。
【问题讨论】:
DIV 将是最快的方式;你为什么不想使用它? 我希望至少使用DIV,就像乘法一样,我只使用左移和加法操作 【参考方案1】:阅读 Hacker's Delight 一书的第 10 章“整数除以常数”。 Bonus content 可用于该章节(但不能用于章节本身)。
或者使用libdivide,这是一个库,它会在第一步中应用已知算法来找到合适的常数,这样除以给定分母就会更快。
正如 libdivide 页面所指出的,编译器知道如何通过编译时常量将除法转换为乘法和移位,因此最简单的方法可能就是使用编译器。我会为你做,但我没有 16 位编译器。如果用32位编译器完成,结果如下:
movw $-21845, %ax
mulw 8(%ebp)
andl $65534, %edx
movl %edx, %eax
shrl %eax
对于 C 函数:
int f(unsigned short d)
return d / 3;
【讨论】:
为什么您使用的编译器会产生“AND”?似乎那位无论如何都会被移出。 @IraBaxter 你好,艾拉。对!这个编译器是“gcc 版本 4.2.1(基于 Apple Inc. build 5658)(LLVM build 2336.11.00)”。我的其他编译器“Apple clang version 4.1 (tags/Apple/clang-421.11.66) (based on LLVM 3.1svn)”不生成掩码。 John Regehr 的博客上有一篇不错的文章,主题是通过比较微基准上的编译器来检测此类次优序列的生成。该技术肯定会检测到这一点:blog.regehr.org/archives/320【参考方案2】:基本答案是“乘以所需常数的倒数”,使用移位和加法进行乘法运算,然后使用一些可能的后移位来正确定位二进制点。
诀窍在于弄清楚倒数的精度必须是多少,才能处理您期望的最大输入红利的大小。您显然可以确定最大的输入操作数是整个寄存器,但如果您知道更多,您可以使用位数更少的倒数,从而获得更快的移位加法乘法。
Cuoq 的回答提供了很好的参考资料。
【讨论】:
以上是关于在没有 DIV 操作码的情况下,任何数字(16 位)在汇编中除以 3 的更快方法的主要内容,如果未能解决你的问题,请参考以下文章