学 Win32 汇编[27] - 乘除指令: 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, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? val dd 8.codemain 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? retmain endpend main;把上面的例子稍作修改(mul -> imul), 得到了不同的结果:; Test27_2.asm.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? val dd 8.codemain 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? retmain endpend 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, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? val dd 8.codemain proc ;IMUL 两个操作数? mov eax, 7? imul eax, val? PrintDec eax ;56? ;IMUL 三个操作数? imul eax, val, 9? PrintDec eax ;72? retmain endpend main;MUL 与 IMUL 结果的一致于不一致:; Test27_4.asm.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.data? val db 7Fh.codemain 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? retmain endpend 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, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain 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 - 余数? retmain endpend main;IDIV 测试; Test27_6.asm.386.model flat, stdcallinclude windows.incinclude kernel32.incinclude masm32.incinclude debug.incincludelib kernel32.libincludelib masm32.libincludelib debug.lib.codemain 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 - 余数? retmain endpend main