1. 程式人生 > >乘除指令: MUL、IMUL、DIV、IDIV

乘除指令: MUL、IMUL、DIV、IDIV

MUL: 無符號乘
;影響 OF、CF 標誌位
;指令格式:
;MUL r/m  ;引數是乘數

;如果引數是 r8/m8,   將把  AL 做乘數, 結果放在 AX
;如果引數是 r16/m16, 將把  AX 做乘數, 結果放在 EAX
;如果引數是 r32/m32, 將把 EAX 做乘數, 結果放在 EDX:EAX

; Test27_1.asm
.386
.model flat, stdcall

include    windows.inc
include    kernel32.inc
include    masm32.inc
include    debug.inc
includelib
kernel32.lib includelib masm32.lib includelib debug.lib .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 ;把上面的例子稍作修改(mul -> imul), 得到了不同的結果: ; Test27_2.asm .386 .model flat, stdcall include windows.inc include kernel32.inc include masm32.inc include debug.inc includelib kernel32.lib includelib masm32.lib includelib
debug.lib .data   val dd 8 .code main proc ;8 位   mov al, 0FFh   imul byte ptr val   PrintHex ax ;FFF8   ;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

IMUL: 有符號乘
;影響 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)

;其中常數 i 的位數可以 <= 但不能 > 其他運算元

; Test27_3.asm
.386
.model flat, stdcall

include    windows.inc
include    kernel32.inc
include    masm32.inc
include    debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib

.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

;MUL 與 IMUL 結果的一致於不一致:

; Test27_4.asm
.386
.model flat, stdcall

include    windows.inc
include    kernel32.inc
include    masm32.inc
include    debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib

.data
    val db 7Fh
.code
main proc
    ;如果運算元都沒有符號位, 結果一致
    mov al, 7Fh
    mul val
    PrintHex ax ;3F01
    
    mov al, 7Fh
    imul val
    PrintHex ax ;3F01
    
    ;如果運算元的其中之一有符號位, 結果不一致
    mov al, 80h
    mul val
    PrintHex ax ;3F80
    
    mov al, 80h
    imul val
    PrintHex ax ;C080
    
    ;如果運算元都有符號位, 結果也一致
    inc val
    mov al, 80h
    mul val
    PrintHex ax ;4000
    
    mov al, 80h
    imul val
    PrintHex ax ;4000
    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

; DIV 測試
; Test27_5.asm
.386
.model flat, stdcall

include    windows.inc
include    kernel32.inc
include    masm32.inc
include    debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib

.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

;IDIV 測試
; Test27_6.asm
.386
.model flat, stdcall

include    windows.inc
include    kernel32.inc
include    masm32.inc
include    debug.inc
includelib kernel32.lib
includelib masm32.lib
includelib debug.lib

.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