繁体   English   中英

将有符号数乘以无符号数时应该使用“mul”还是“imul”?

[英]Should I use “mul” or “imul” when multiplying a signed number to an unsigned number?

我发现mulimul都可用于将有符号数乘以无符号数。

例如:

global _start

section .data
    byteVariable DB -5

section .text
_start:

mov al, 2
imul BYTE [byteVariable]

您可以用mul替换imul ,结果仍然相同( -10 )。

将有符号数乘以无符号数时mulimul是否完全相同,或者它们之间有区别吗?

如评论中所述,上半部分不同。 如果您不关心上半部分,则可以使用mulimul的所有形式(单操作数形式产生上半部分,但在这种情况下,您将忽略它)。

如果您确实关心上半部分,则mulimul本身都imul ,因为它们只是将 unsigned*unsigned 和 signed*signed 相乘,但您可以很容易地修复它。

考虑有符号字节的位权重为 -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 这里发生的事情是补偿-128 权重,首先通过将第 7 位的值相加 128 次来删除它,然后通过再次执行一直到 +128 权重,当然这可以一步完成。

无论如何,乘以由一些符号数y和工作出来给出256 x_7 y + xy ,其中xy是(双宽度)的结果imul256 x_7 y手段“添加y到上半如果的符号x是设置”,因此可能的实现是(未测试)

; al has some unsigned value
mov dl, al
sar dl, 7
and dl, [signedByte]
imul BYTE [signedByte]
add ah, dl

自然地,您可以对一个操作数进行符号扩展,对另一个操作数进行零扩展,并使用 16 位乘法(任意,因为上半部分与这种方式无关)。

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

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加宽乘法以相同的方式处理它们的输入,因此它们都不能工作(除非已知有符号输入是非负的,或者已知无符号输入没有其高位设置,所以你可以把它们都一样对待。)

mul 和 imul 还以不同方式设置 FLAGS:CF=OF= 完整结果是否适合下半部分。 (即完整结果是低半部分的零扩展或符号扩展)。 对于imul reg,r/mimul reg, r/m, imm ,“低半部分”是目标 reg; 上半部分没有写在任何地方。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM