当将有符号数与无符号数相乘时,我应该使用“mul”还是“imul”?

7
我发现mulimul都可以用于将有符号数乘以无符号数。
例如:
global _start

section .data
    byteVariable DB -5

section .text
_start:

mov al, 2
imul BYTE [byteVariable]

你可以将imul替换为mul,结果仍然相同(-10)。
在将有符号数乘以无符号数时,mulimul是否完全相同,还是它们之间存在区别?

3
不,结果并不相同,可能您只是检查了结果的低半部分,而那部分是相同的。无符号的“mul”应该在“ax”中产生“502”的结果。 - Jester
@Jester 你是对的,当使用 mul 时,ax0x01F6 (502),而当使用 imul 时,它是 0xFFF6 (-10)。 - user8315006
1
如果您不需要高位结果,则始终使用imul reg,r/m32imul reg,r/m32,imm;它在现代CPU上更有效率(1 uop),因为它不必在任何地方写入高半部分。https://agner.org/optimize/ - Peter Cordes
3个回答

4
上半部分与评论中提到的不同。如果您不关心上半部分,可以使用mulimul,以它们所有的形式(单操作数形式产生上半部分,但在这种情况下您将忽略它)。
如果您关心上半部分,则mulimul都不能单独工作,因为它们只是无符号*无符号和有符号*有符号相乘,但您可以很容易地修复它。
考虑到有符号字节具有位权重-128、64、32、16、8、4、2、1,而无符号字节具有位权重+128、64、32、16、8、4、2、1。因此,您可以用有符号格式表示x的无符号值(我知道这很困惑,但这是我能做的最好的),如x + 256 x_7(其中x_7x的第7位)。最简单的方法可能是将其拆分:x + 2 * 128 * x_7。这里发生的事情是通过添加第7位的值128次来补偿-128权重,首先去除它,然后再通过再次执行它一直到+128权重,当然这可以一步完成。
无论如何,将其乘以一些有符号数字y并计算出来,得到256 x_7 y + xy,其中xyimul的(双宽度)结果,256 x_7 y表示“如果设置了x的符号,则将y添加到上半部分”,因此可能的实现是(未经测试)。
; al has some unsigned value
mov dl, al
sar dl, 7
and dl, [signedByte]
imul BYTE [signedByte]
add ah, dl

通常情况下,您可以对一个操作数进行符号扩展,对另一个操作数进行零扩展,并使用16位乘法(任何一种都可以,因为这种方式上半部分不相关)。


1

x86有一条指令可以将有符号字节乘以无符号字节:SSSE3 pmaddubsw

您可以将其视为将一个操作数符号扩展为16位,将另一个操作数零扩展为16位,然后进行NxN -> N位乘法。(对于每个SIMD元素)。

它还可以水平添加相邻字节的字产品对,但如果您使用零(punpcklbwpmovzxbw)解包输入,则可以单独获取每个产品。

当然,如果您具有SSE4.1,则可以只pmovsxbw一个输入,pmovzxbw另一个输入,以提供常规的16位pmullw,如果您不想添加成对的产品。


但如果你只想要一个标量结果,movsx/movzx来提供给常规的非扩展imul reg,reg是最好的选择。 正如Harold所指出的,mul r/mimul r/m扩展乘法会以相同的方式处理它们的输入,因此两者都无法工作(除非已知有符号输入为非负数或无符号输入未设置其高位,因此您可以将它们都视为相同)。 mulimul还会以不同的方式设置FLAGS:CF = OF = 是否完全适合于低半部分。 (即,完整的结果是低半部分的零扩展或符号扩展)。对于imul reg,r/mimul reg,r/m,imm,“低半部分”是目标寄存器;高半部分不写入任何地方。

-1

标志位的另一种行为。对于MUL:当进位位改变上半部分时,OF=CF=1;对于IMUL:当进位位在低位中改变符号位(或2个或3个操作数形式的结果中仅改变符号位)时,OF=CF=1。


这不是一个非常清晰的描述。Intel的手册解释得更好:mul如果上半部分非零,则设置CF和OF。 imul如果上半部分不是低半部分的符号扩展,则设置CF和OF。否则它们被清除。因此,在两种情况下,CF = OF =结果是否适合低半部分。(imul的2个和3个操作数形式仅产生完整乘法的低半部分,但标志仍然设置为单操作数形式相同。) - Peter Cordes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接