为什么idivx86汇编指令EDX:EAX被给定寄存器除(64位)而其他数学运算(包括乘法)只能在单个输入和输出寄存器上运行?
乘法:
mov eax, 3
imul eax, 5
Run Code Online (Sandbox Code Playgroud)
师:
mov edx, 0
mov eax, 15
mov ebx, 5
idiv ebx
Run Code Online (Sandbox Code Playgroud)
我知道这EDX用于存储余数,但为什么没有单独的指令用于此行为?这对我来说似乎不一致.
指令集提供了有效实现任意宽度整数运算所必需的指令.对于加法和减法,除了固定宽度结果之外,您需要知道的是操作是否导致进位(用于加法)或借用(用于减法).这就是进位标志的原因.对于乘法,您需要能够将两个单词相乘并获得双字结果.这就是imul产生结果的原因edx:eax.对于除法,您需要能够划分双倍宽度数并获得商和余数.
要了解为什么需要这些特定操作,请参阅Knuth的"计算机编程艺术"第2卷,其中详细介绍了实现任意宽度算法的算法.
至于为什么x86指令集中没有更多不同形式的乘法和除法指令,乘法和除法不是2的幂,比其他指令要少得多,因此英特尔可能不想使用可用于更频繁使用的指令的操作码.通用程序中的大多数乘法和除法都是2的幂; 对于这些,您可以使用位移或lea指令代替.
还有一个“双宽度”乘法(单操作数或mul)imul。
如果你问“为什么没有两个操作数idiv只给出商”,那么我真的不知道(我有一个理论,但我不为英特尔工作),我也希望它存在..
当您想要使用不是 2 的幂的模数进行模乘法时,效果很好,您可以执行 amul并直接用 a 进行后续操作div,并且所有内容都已在正确的位置。这是一个结果,而不是一个原因,出于这个原因,我们必须询问英特尔……但这是一个理论。早在 8086 时代,就只有双角乘法(而且是一种缓慢的迭代乘法,与在软件中所做的一样,会提前退出)。后来添加了一些更灵活的乘法,但除法从未发生过这种情况。也许它并不那么紧迫 - 毕竟,除法相对较少,而您经常需要乘以小常量,例如索引结构数组。