1:无符号乘法指令MUL
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
val1 WORD 2000 h
val2 WORD 0100 h
. code
main PROC
; 8 位乘法
mov al, 5 h ; 被乘数
mov bl, 10 h
mul bl ; AX = 0050 h , CF, OF = 0
; 16 位乘法
mov ax, val1
mul val2 ; DX: AX = 00200000 h ,CF , OF= 1 高部分不为零0 了,CF, OF= 1
mov eax, 12345 h
mov ebx, 1000 h
mul ebx ; EDX: EAX = 0000000012345000 , CF, OF = 0
INVOKE ExitProcess, 0
main ENDP
END main
2:有符号乘法指令IMUL 单个操作数情况
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. code
main PROC
mov al, 48
mov bl, 4
imul bl ; AX = 00 C0h , OF= 1 因为AH不是AL的符号扩展,因此OF = 1
mov al, - 4
mov bl, 4
imul bl ; AX = FFF0h, OF = 0 因为AH是AL的扩展,OF清零
mov ax, 48
mov bx, 4
imul bx ; DX: AX = 000000 C0h, OF = 0 ; 因为DX是AX的符号扩展,因此OF= 0
mov eax, + 4823424
mov ebx, - 423
imul ebx ; EDX: EAX = FFFFFFFF86635D80h, OF = 0 , 因为EDX是EAX的符号扩展, OF = 0
INVOKE ExitProcess, 0
main ENDP
END main
3:有符号乘法指令IMUL 两个操作数情况, 三个操作数情况
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
word1 SWORD 4
dword1 SDWORD 4
. code
main PROC
mov ax, - 16 ; AX = - 16
mov bx, 2 ; BX = 2
imul bx, ax ; BX = - 32
imul bx, 2 ; BX = - 64
imul bx, word1 ; BX = - 256
mov eax, - 16 ; EAX = - 16
mov ebx, 2 ; EBX = 2
imul ebx, eax ; EBX = - 32
imul ebx, 2 ; EBX = - 64
imul ebx, dword1; EBX = - 256
; 因为双操作数与三操作IMUL指令的目的操作数大小与乘积相同
; 因此会出现符号溢出
mov ax, - 32000
imul ax, 2 ; OF = 1 因为- 64000 不适合16 位目的操作数,换成32 就不会
; 三操作数
imul bx, word1, - 16 ; BX = word1 * - 16
imul ebx, dword1, - 16 ; EBX = dword1 * - 16
imul ebx, dword1, - 2000000000 ; 符号溢出
INVOKE ExitProcess, 0
main ENDP
END main
4:对比MUL乘法指令与SHL移位方式的执行时间对比 (在现在大部分处理器执行时间都差不多了)
include Irvine32. inc
. stack 4096
ExitProcee PROTO, dwExitCode: DWORD
LOOP_COUNT = 0FFFFFFFF h
. data
intval DWORD 5
startTime DWORD ?
. code
main PROC
call GetMseconds ; 获取开始时间
mov startTime, eax
mov eax, intval
call mult_by_shifting
call GetMseconds
sub eax, startTime
call WriteDec
call Crlf
call GetMseconds ; 获取开始时间
mov startTime, eax
mov eax, intval
call mult_by_MUL
call GetMseconds
sub eax, startTime
call WriteDec
INVOKE ExitProcess, 0
main ENDP
mult_by_shifting PROC
mov ecx, LOOP_COUNT
L1:
push eax ; 保存原始EAX
mov ebx, eax
shl eax, 5
shl ebx, 2
add eax, ebx
pop eax ; 恢复EAX
loop L1
ret
mult_by_shifting ENDP
mult_by_MUL PROC
mov ecx, LOOP_COUNT
L1:
push eax ; 保存原始EAX
mov ebx, 36
mul ebx
pop eax ; 恢复EAX
loop L1
ret
mult_by_MUL ENDP
END main
5:DIV 无符号除法指令
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
dividend QWORD 0000000800300020 h
divisor DWORD 00000010 h
. code
main PROC
; 8 位 AL商,AH余数
mov ax, 0083 h ; 被除数
mov bl, 2 ; 除数
div bl ; AL = 41 h ,AH = 01 h
; 16 位,AX商,DX余数
mov dx, 0 ; 清除被除数高16 位
mov ax, 8003 h
mov cx, 100 h
div cx ; AX= 0080 h DX= 0003 h
; 32 位 EAX商,EDX 余数
mov edx, DWORD PTR dividend + 4 ; 高双字
mov eax, DWORD PTR dividend ; 低双字
div divisor ; EAX = 08003000 h EDX = 00000020 h
INVOKE ExitProcess, 0
main ENDP
END main
6:符号位扩展指令,CBW,CWD,CDQ
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
byteVal SBYTE - 101
wordVal SWORD - 101
dwordVal SDWORD - 101
. code
main PROC
mov al, byteVal ; AL = 9 Bh
cbw ; AX = FF9Bh
mov ax, wordVal ; AX = FF9Bh
cwd ; DX: AX = FFFFFFF9Bh
mov eax, dwordVal ; EAX = FFFFFF9Bh
cdq ; EDX: EAX = FFFFFFFFFFFFFF9Bh
INVOKE ExitProcess, 0
main ENDP
END main
7:IDIV 有符号除法指令
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
byteVal SBYTE - 48
wordVal SWORD - 5000
dwordVal SDWORD + 50000
. code
main PROC
mov al, byteVal ; 被除数低字节
cbw ; 扩展到AH
mov bl, + 5
idiv bl ; AL = - 9 , AH = - 3
mov ax, wordVal ; 被除数低字
cwd ; 扩展到DX
mov bx, + 256
idiv bx ; 商AX = - 19 , 余DX = - 136
mov eax, dwordVal
cdq
mov ebx, - 256
idiv ebx ; EAX = - 195 EDX = + 80
INVOKE ExitProcess, 0
main ENDP
END main
8:进行除法时,检查除数不能为0
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
dividend WORD 0083 h
divisor BYTE 2
. code
main PROC
mov ax, dividend
mov bl, divisor
cmp bl, 0
je NoDivideZero ; 为零就不进行除
div bl
NoDivideZero:
INVOKE ExitProcess, 0
main ENDP
END main
9:计算算式 var4 = (var1 + var2)*var3
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
var1 DWORD 10
var2 DWORD 20
var3 DWORD 30
var4 DWORD ?
. code
main PROC
; var4 = ( var1 + var2) * var3
mov eax, var1
add eax, var2
mul var3
jc tooBig ; 判断EAX是否放得下
mov var4, eax
jmp next
tooBig:
next:
INVOKE ExitProcess, 0
main ENDP
END main
10:计算算式 var4 = (var1 * -5) / (-var2 % var3)
.386
. model flat, stdcall
. stack 4096
ExitProcess PROTO, dwExitCode: DWORD
. data
var1 DWORD 10
var2 DWORD 20
var3 DWORD 30
var4 DWORD ?
. code
main PROC
; var4 = ( var1 * - 5 ) / ( - var2 % var3)
mov eax, var2
neg eax
cdq
idiv var3 ; EDX= 余数
mov ebx, edx
mov eax, - 5
imul var1 ; EDX: EAX = 左边表达式结果
idiv ebx
mov var4, eax
INVOKE ExitProcess, 0
main ENDP
END main