在没有 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 的更快方法的主要内容,如果未能解决你的问题,请参考以下文章

十六进制颜色码的对照表

Java中负字节和短数据类型中的位操作

如何在没有验证码的情况下保护联系表格?

包含 1000 位数字的字符串,在没有数组的情况下找到最大的 5 位数字

C程序在16位处理器中获得2个数字的平均值

独热码的相关概念:数、码