【发布时间】:2022-11-26 21:39:43
【问题描述】:
有没有什么通用的(不是 ISA 特定的)方法,如何在不使用 div 函数的情况下获得汇编中任何正数的倒数?
我使用倒数值将未知数 x 除以常数 y。比如说,我想将 256 除以常数 3(这与将 256 乘以 1/3 相同)
- 手工计算
1/3 - 手动将
0.3333...从浮点数转换为Q32定点数(32位小数位无符号)1/3 * 2^32 = 0x55555555 - 将
0x0x55555555常量作为立即数保存到汇编中的寄存器中 - 在汇编中乘以
0x100 * 0x55555555 = 0x5555555500 - 在汇编中从 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 编号。 -
您可以实现长除法的二进制版本。