簡體   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