1. 程式人生 > >Win32ASM學習[16] :乘除指令: MUL、IMUL、DIV、IDIV

Win32ASM學習[16] :乘除指令: MUL、IMUL、DIV、IDIV

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

一. 無符號數乘法指令 MUL(MULtiply) 

 格式: MUL OPRD  
 功能: 乘法操作.

 說明: 1. OPRD為通用暫存器或儲存器運算元.
           2. OPRD為源運算元,即作乘數.目的運算元是隱含的,即被乘數總是指定為累加器AX 或AL的內容.

           3. 16位乘法時,AX中為被乘數.8位乘法時,AL為被乘數.當16位乘法時,32位的乘積存於DX及AX中;8位乘法的16位乘積存於AX中.

           4. 操作過程: 位元組相乘:(AX)<--(AL)*OPRD,當結果的高位位元組(AH)不等於0時,則CF=1、OF=1.字相乘: (DX)(AX)<--(AX)*OPRD,當(DX)不等0時,則CF=1、OF=1

           5. 示例 1: MUL BETA[BX]
                              MUL DI
                              MUL BYTE PTR ALFA 
                  
               示例 2: 設在W1和W2字單元中各有一個16位數,若求其乘積並存於W3開始的字單元中,可用以下指令組實現:
                              MOV AX,W1
                              MUL W2
                              MOV W3,AX 
                              MOV W3+2,DX

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

.data
    val dd 8
.code
main proc
    ;8 位
    mov al, 0FFh
    mul byte ptr val
    PrintHex ax  ;07F8
   
    ;16 位
    mov ax, 0FFFFh
    mul word ptr val
    PrintHex dx ;0007
    PrintHex ax ;FFF8
   
    ;32 位
    mov eax, 0FFFFFFFFh
    mul val
    PrintHex edx ;00000007
    PrintHex eax ;FFFFFFF8
    ret
main endp
end main

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

二. 帶符號數乘法指令 IMUL(Integer MULtiply)

 格式: IMUL OPRD 
 功能: 完成兩個帶符號數的相乘

 說明: 1. 其中OPRD為任一通用暫存器或儲存器運算元.
           2. MUL指令對帶符號相乘時,不能得到正確的結果.
          例如: (AL)=255
                (CL)=255

                 MUL CL
                (AX)=65025
          注意: 這對無符號數講,結果是正確的,但對帶符號數講,相當於(-1)*(-1)結果應為+1,而65025對應的帶符號數為-511,顯然是不正確的.

          3. 8088/8086指令系統提供了專用的帶符號數乘法和除法指令.IMUL即為帶符號乘法指令,它能保證得到正確的帶符號數的乘積. 

操作過程:位元組相乘:(AX)<--(AL)*OPRD 
                     字相乘: (DX)(AX)<--(AX)*OPRD

          4. 本指令影響標誌位CF、OF.

;影響 OF、CF 標誌位;第一種指令格式:

;IMUL r/m ;單運算元;如果引數是 r8/m8, 將把 AL 做乘數, 結果放在 AX

;如果引數是 r16/m16, 將把 AX 做乘數, 結果放在 EAX

;如果引數是 r32/m32, 將把 EAX 做乘數, 結果放在 EDX:EAX

;以上這些都是和 MUL 一樣的, 只是運算結果有時一樣、有時不一樣.

;IMUL 還有另外兩種指令格式:

;IMUL r16/r32, r16/r32/m16/m32/i

;雙運算元, (1)*(2) -> (1)

;IMUL r16/r32, r16/r32/m16/m32, i

;三運算元, (2)*(3) -> (1)

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

.data
    val dd 8
.code
main proc
    ;8 位
    mov al, 0FFh
    PrintDec al
    imul byte ptr val
    PrintHex ax  ;FFF8
    PrintDec ax  ;-8
;-------------------------   
    mov al,-8 ;F8
    mul byte ptr val
    PrintDec ax ;1984
    PrintHex ax ;07C0
;-------------------------   
    ;16 位
    mov ax, 0FFFFh
    imul word ptr val
    PrintHex dx ;FFFF
    PrintHex ax ;FFF8
   
    ;32 位
    mov eax, 0FFFFFFFFh
    imul val
    PrintHex edx ;FFFFFFFF
    PrintHex eax ;FFFFFFF8
    ret
main endp
end main

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

.data
    val dd 8
.code
main proc
    ;IMUL 兩個運算元
    mov eax, 7
    imul eax, val
    PrintDec eax ;56
   
    ;IMUL 三個運算元
    imul eax, val, 9
    PrintDec eax ;72
    ret
main endp
end main

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

DIV、IDIV: 無符號除、有符號除

;它們沒有定義對 EFLAGS 的影響
;它們的指令格式:
;DIV r/m  ;引數是除數

;如果引數是 r8/m8,   將把 AX      做被除數; 商 -> AL,  餘數 -> AH
;如果引數是 r16/m16, 將把 DX:AX   做被除數; 商 -> AX,  餘數 -> DX
;如果引數是 r32/m32, 將把 EDX:EAX 做被除數; 商 -> EAX, 餘數 -> EDX

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

.code
main proc
    ;除數是 8 位
    mov ax, 17   ;被除數
    mov cl, 3    ;除數
    div cl
    PrintDec al  ;5 - 商
    PrintDec ah  ;2 - 餘數
   
    ;除數是 16 位
    mov dx, 0    ;
    mov ax, 17   ;dx:ax 是被除數
    mov cx, 3    ;cx    是除數
    div cx
    PrintDec ax  ;5 - 商
    PrintDec dx  ;2 - 餘數
   
    ;除數是 32 位
    mov edx, 0   ;
    mov eax, 17  ;edx:eax 是被除數
    mov ecx, 3   ;ecx     是除數
    div ecx
    PrintDec eax ;5 - 商
    PrintDec edx ;2 - 餘數
    ret
main endp
end main

----------------------------------------------------------------------------------------------------------------------------------------------------------------------

.code
main proc
    ;除數是 8 位
    mov al, -17  
    cbw          ;ax 是被除數
    mov cl, 3    ;除數
    idiv cl
    PrintDec al  ;-5 - 商
    PrintDec ah  ;-2 - 餘數
   
    ;除數是 16 位
    mov ax, -17  
    cwd          ;dx:ax 是被除數
    mov cx, 3    ;cx    是除數
    idiv cx
    PrintDec ax  ;-5 - 商
    PrintDec dx  ;-2 - 餘數
   
    ;除數是 32 位
    mov eax, -17 
    cdq          ;edx:eax 是被除數
    mov ecx, 3   ;ecx     是除數
    idiv ecx
    PrintDec eax ;-5 - 商
    PrintDec edx ;-2 - 餘數
    ret
main endp
end main

----------------------------------------------------------------------------------------------------------------------------------------------------------------------