在Intel机器上,整数除法需要一个由两条指令组成的序列:
- 将红利存储在a之后寄存器(例如,%eax)),您将股利的符号扩展到相应的d注册(% edx)。
- 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位的数字。