二进制补码除法算法(英特尔)



在Intel机器上,整数除法需要一个由两条指令组成的序列:

  1. 将红利存储在a之后寄存器(例如,%eax)),您将股利的符号扩展到相应的d注册(% edx)。
  2. idivdiv或指令本身然后执行除法并将商放入a寄存器和d中的余数登记。但是为什么操作需要符号扩展呢?对于符号扩展值,算法实际上做了什么?剩下的是如何在相同的空间结束的?

我不是在问如何在英特尔上做整数除法,或者如果你不遵守规则会发生什么。我想知道为什么是这些规则。我想知道算法是如何工作的,这样它就必须以某种方式使用符号扩展的寄存器空间。

让我们举一个具有8位操作数的可管理示例-十进制-65/3。

-------------------
00000011 ) 11111111 10111111

如果它是65/3(有一个正的红利),我可以看到左边的填充将如何为减法提供空间-

00010101
-----------------------
00000011 ) 00000000 01000001
0000 0011
---------
0000 000100
00 000011
---------
00 00000101
00000011
--------
00000010  (R)

(我在上面通过不显示减去0的实例来简化)。此外,我还展示了减法本身,而不是除数的两个补负的加法,但基本的要点将保持不变。)在这里,0填充为减去每个位留出了空间。然而,我不明白这将如何工作,当红利是一个二补负整数。而且,即使在这种正的情况下,除了它已经可用的方便之外,为什么其余部分应该结束在容纳填充的空间中,这并不明显。

谢谢!

这两个步骤用于将一个32位有符号值除以另一个32位有符号值。idiv指令将64位带符号整数除以32位整数。因此,如果您拥有的是32位整数,则需要先将其转换为64位整数。

为什么idiv被设计成64位乘32位的除法?出于同样的原因,mul被设计为从32位乘32位产生64位结果:这样你就可以实现任意精度算术使用这些原语在32位组上工作


编辑: 任意精度的算术需要它吗?让我们来看一个十进制长除法问题:

512 / 7 = ?

对于结果的第一个数字,我们需要计算7适合51的次数;我们计算truncate(51/7) = 7,所以下一位数字将是7,我们将其相乘,移位,相减,得到:

512 / 7 = 7?
490
---
22

truncate(22/7) = 3重复此操作,得到:

512 / 7 = 73
490
---
22
21
---
1   (remainder)

请注意,我们使用的是一个'oracle'来除以一个两位数的数字;并在不同的两位数组上重复使用,逐个生成结果的数字。同样地,如果你的"数字"是32位的单词,你需要一个oracle来将64位的数字除以32位的数字。

最新更新