【问题标题】:How to do division in ARM?如何在ARM中进行除法?
【发布时间】:2013-11-07 19:10:08
【问题描述】:

由于没有DIV 命令,我正在尝试查找如何在 ARM 中进行除法。如果这可以通过乘以浮点数[/9 = *0.09]、减法或使用库来完成。任何方式都可以。

目前我正在使用这样的循环使用减法进行除法,但我丢失了小数:

MOV R0,#70 ;Fahrenheit Temperature
SUB R1,R0,#32 ; Subtracting 32
MOV R4,#0 ;Counter

LOOP 

   ADD R4,R4,#1; Counter+1 ->Is the answer of the division without decimals
   SUB R1,#9
   CMP R1,#0
   BPL LOOP
   MOV R1,R4

所以基本上我所做的是我的温度为 70,我减去 32,我得到 38。然后在循环中我每次取 9,直到提醒小于 9。使用正常除法的答案是 4.22222。这里我得到 5。所以我的结果并不准确。

【问题讨论】:

标签: assembly arm division


【解决方案1】:

如果您只想将 r0 中的整数值除以 9,您可以使用以下方法进行近似:

ldr r3,=0x1C71C71D   # 1C71C71D == (2^32 / 9) + 1
umull   r9,r3,r0,r3

r3 现在包含商的整数部分,r9 包含按 2^32 缩放的小数部分。要获得余数,只需将商的整数部分乘以 9,然后从原始值中减去结果。

【讨论】:

  • 这是divide by multiply。阅读更多here
  • @AntreasSolou:umull 将两个 32 位数字相乘以形成 64 位结果(分成两个寄存器)。所以代码所做的是在r3(整个部分)和r9(小数部分)中形成一个等于(r0 << 32) / 9的32.32 fixed-point number
  • 对于适用于所有uint32_t 输入的精确除法,请参阅 GCC8.2 的输出:godbolt.org/z/-PVI_Q 使用不同的乘数,需要在 umull 后右移 1,但仅此而已。
【解决方案2】:

如果您将数字除以常数并且需要整数结果,Michael 的答案是正确的。你不会得到你想要的分数部分。

如果您需要浮点结果,则需要浮点除法函数,这在软件和没有 FPU 的架构上的 asm 中不容易实现。 ARMv7及以上默认有FPU/SIMD,部分ARMv6及以下也有FPU,可以直接在硬件上划分

定点解可能更简单,像普通整数除法一样只除数,但记得在计算后调整结果。当然,定点数不会像浮点数那样有大的动态范围,但在你的情况下,我认为范围就足够了。你也可以将余数乘以10nn是你需要的小数点后的位数,然后再用上面的除数除以得到小数部分

例如要获得 3 位精度的 22/9 的结果,请执行以下操作:

22/9   = 2 remains 4
4*10^3 = 4000
4000/9 = 444
→ 22/9 = 2.444

要获得更高的精度,只需将余数乘以 10 的更大幂

【讨论】:

猜你喜欢
  • 2012-01-10
  • 2021-09-24
  • 1970-01-01
  • 2014-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多