【问题标题】:Reciprocal 1/x division in assembly汇编中的倒数 1/x 除法
【发布时间】:2022-11-26 21:39:43
【问题描述】:

有没有什么通用的(不是 ISA 特定的)方法,如何在不使用 div 函数的情况下获得汇编中任何正数的倒数?

我使用倒数值将未知数 x 除以常数 y。比如说,我想将 256 除以常数 3(这与将 256 乘以 1/3 相同)

  1. 手工计算1/3
  2. 手动将0.3333...从浮点数转换为Q32定点数(32位小数位无符号)1/3 * 2^32 = 0x55555555
  3. 将0x0x55555555常量作为立即数保存到汇编中的寄存器中
  4. 在汇编中乘以0x100 * 0x55555555 = 0x5555555500
  5. 在汇编中从 Q64 定点转换回 32 位整数 0x5555555500 >> 32 = 0x55 = 85

    这工作正常,但现在,我想将 2 个未知数除以彼此。为了做到这一点,使用上面的算法,首先我必须在汇编中计算 y 的倒数,而不是手工计算。

    还是有另一种通用方法,我可以用它来除法?由于我的代码的速度性能,我不想在循环中使用减法来计算除法。

【问题讨论】:

  • 你是说像Why does GCC use multiplication by a strange number in implementing integer division??如果您想为运行时变量执行此操作,请参阅 libdivide Repeated integer division by a runtime constant value 作为示例,或者您自己使用其中一种算法来查找定点倒数。或者你真的只是想要一个定点倒数直接用于定点数学,而不是精确的整数除法?如果是这样,请添加 [fixed-point] 标签,并可能删除 [integer-division]
  • 请注意,1 / 3 * 2^32 = 2^32 / 3。您还使用通常的“转换为二进制”算法,但用于小数部分(乘以 2,取整数部分,重复小数部分)。对于 a / b 形式的数字,您只需将分子加倍,如果 2a >= b 您有一个 1 并用 2a - b / b 重复。如果 2a < b 你有一个 0 并用 2a / b 重复。你一直循环使用你的数字是 0 或者你达到了完全精度。这些位从 MSb 进入 Q32 编号。
  • 您可以实现长除法的二进制版本。

标签: assembly integer-division


【解决方案1】:

Newton Raphson 算法是实现这一点的一种方法。使用基于除数的高位非零位的初始估计表可以加快该过程。第二张表可用于小数的倒数,例如 2 到 255。

https://en.wikipedia.org/wiki/Division_algorithm#Newton%E2%80%93Raphson_division

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-10-28
    • 2016-01-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多