我对如何在Risc-v汇编中将两个64位的数字相乘感到困惑。我想加载64位的数字,将它们相乘,并将其存储在变量中并打印结果。
根据我的理解,你必须将变量加载到一个寄存器中,使用mul和mulh存储upper和lower,然后将其存储回result变量中。这是我对mul和mulh的理解:
穆尔x12,x10,x11 mul x13,x10,x11
我把x10和x11相乘,并将它们存储在高位和低位。我对如何将64位加载到x10和x11感到困惑。我尝试使用ld x10,0(number 1)并对x11做同样的事情,但当乘以x10和x11时,它不会给予正确的结果。我将如何在RISC-V中做到这一点
1条答案
按热度按时间jjhzyzn01#
从数学上讲,一个64×64的乘法会产生一个128位的答案,保证没有溢出(对于某些输入,任何更少的溢出风险)。这被称为扩展乘法。
但是,正如Peter所说,如果您要将结果限制为64位并假设没有溢出,则可以简化计算。
如果你在32位机器上,64位值将占用两个寄存器。
对于算术,有两个操作数,因此,每个操作数有一对寄存器,总共有4个寄存器用于源操作数。
对于每个64位操作数,需要加载高位和低位。这取决于您的存储格式,但如果您使用的是RISC V上预期的小端字节,那么当存储在内存中时,低位先出现,高位4字节再出现。如果您已经在寄存器中有值,那就更好了,只需清楚哪些是高位,哪些是低位。
RISC V没有双寄存器加载(或存储),因此,您可以选择寄存器编号,例如,一对x10,x11或同一对x11,x10,高位/低位颠倒,完全取决于您,但您甚至不需要为寄存器对使用连续的寄存器编号(尽管这是预期的,并减少了程序员的认知负荷)。
然后,您需要将这两对相乘,如long multiplication中所示,它将较短的乘法相加以得到完整的答案。
让我们知道,在32位机器上,我们有32×32 =〉64位的答案。因此,我们将64×64 =〉128乘法分解为几个32×32 =〉64位的答案,并以适当的比例求和。
假设一个64位数是AB,其中A是高阶32位,B是低阶32位,而另一个是CD(类似地,两个32位的一半)。
AB × CD =(A × C〈〈64)+(A × D〈〈32)+(B × C〈〈32)+(B × D)
上面的每一个单独的乘法都需要一个
mul
和mulh
(如果是无符号操作数,则为mulhu
),从而产生64位的答案。这些64位的答案(其中4个)需要进行有效的移位,然后求和(移位是无、32或64,因此不需要实际的移位,只需在正确的位置使用正确的寄存器)。求和必须在考虑进位的情况下进行,因此增加了一些指令,但它们很简单。
一个配置正确的C编译器(例如godbolt)可以显示基本的内容,尽管由于标准C不支持扩展运算,不能显示真正的64×64 =〉128形式,尽管可能有一些编译器(例如gcc)扩展/内置支持扩展形式。