匯編語言MUL指令無符號數乘法的使用

32 位模式下,MUL(無符號數乘法)指令有三種類型:

  • 第一種執行 8 位操作數與 AL 寄存器的乘法;
  • 第二種執行 16 位操作數與 AX 寄存器的乘法;
  • 第三種執行 32 位操作數與 EAX 寄存器的乘法。

乘數和被乘數的大小必須保持一致,乘積的大小則是它們的一倍。這三種類型都可以使用寄存器和內存操作數,但不能使用立即數:

MUL reg/mem8
MUL reg/meml6
MUL reg/mem32

MUL 指令中的單操作數是乘數。下表按照乘數的大小,列出瞭默認的被乘數和乘積。由於目的操作數是被乘數和乘數大小的兩倍,因此不會發生溢岀。

被乘數 乘數 乘積
AL reg/mem8 AX
AX reg/mem16 DX:AX
EAX reg/mem32 EDX:EAX

如果乘積的高半部分不為零,則 MUL 會把進位標志位和溢出標志位置 1。因為進位標志位常常用於無符號數的算術運算,在此我們也主要說明這種情況。例如,當 AX 乘以一個 16 位操作數時,乘積存放在 DX 和 AX 寄存器對中。其中,乘積的高 16 位存放在 DX,低 16 位存放在 AX。如果 DX 不等於零,則進位標志位置 1,這就意味著隱含的目的操作數的低半部分容納不瞭整個乘積。

有個很好的理由要求在執行 MUL 後檢查進位標志位,即,確認忽略乘積的高半部分是否安全。

MUL 示例

下述語句實現 AL 乘以 BL,乘積存放在 AX 中。由於 AH(乘積的高半部分)等於零,因此進位標志位被清除(CF=0):

mov al, 5h
mov bl, 10h
mul bl          ; AX = 0050h, CF = 0

下圖展示瞭寄存器內容的變化:

下述語句實現 16 位值 2000h 乘以 0100h。由於乘積的高半部分(存放於 DX)不等於零,因此進位標志位被置 1:

.data
val1 WORD 2000h
val2 WORD 0l00h
.code
mov ax, val1      ; AX = 2000h
mul val2        ; DX:AX = 00200000h, CF = 1

下述語句實現 12345h 乘以 1000h,產生的 64 位乘積存放在 EDX 和 EAX 寄存器對中。EDX 中存放的乘積高半部分為零,因此進位標志位被清除:

mov eax, 12345h
mov ebx, 1000h
mul ebx          ; EDX:EAX = 0000000012345000h, CF = 0

下圖展示瞭寄存器內容的變化:

在 64 位模式下使用 MUL

64 位模式下,MUL 指令可以使用 64 位操作數。一個 64 位寄存器或內存操作數與 RAX 相乘,產生的 128 位乘積存放到 RDX:RAX 寄存器中。下例中,RAX 乘以 2,就是將 RAX 中的每一位都左移一位。RAX 的最高位溢出到 RDX 寄存器,使得 RDX 的值為 0000 0000 0000 0001h:

mov rax, 0FFFF0000FFFF0000h
mov rbx, 2
mul rbx           ; RDX:RAX = 0000000000000001FFFE0001FFFE0000

下面的例子中,RAX 乘以一個 64 位內存操作數。該寄存器的值乘以 16,因此,其中的每個十六進制數字都左移一位(一次移動 4 個二進制位就相當於乘以 16)。

.data
multiplier QWORD 10h
.code
mov rax, OAABBBBCCCCDDDDh
mul multiplier    ; RDX:RAX = 00000000000000000AABBBBCCCCDDDDOh

到此這篇關於匯編語言MUL指令無符號數乘法的使用的文章就介紹到這瞭,更多相關匯編語言MUL指令內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!