1. 乘法指令
分类: 无符号数乘法、有符号数乘法
寻址方式: 隐含寻址
操作数: 隐含目标操作数AX(DX),源操作数由指令给出。
功能: 两字节数相乘或两字相乘。两字节相乘结果放在AX,两字相乘结果高位放DX、低位放AX。
指令格式: MUL(IMUL) reg/mem
无符号数乘法指令与有符号数乘法指令的区别:
1) 操作数的性质不同,前者无符号,后者两乘数必须有符号。
2)对无符号数乘法,如果乘积的高半部分不为0,则CF=0F=1,代表AH或DX中包含乘积的有效数字;否则CF=OF=0。对有符号数乘法,若乘积的高半部分是低半部分的符号位的扩展,则CF=OF=0;否则CF=OF=1。对其他标志均无定义。
3)无符号数乘法指令中的源操作数应满足无符号数的表示范围,而有符号数乘法指令中给出的源操作数应满足带符号数的表示范围。
1.1 无符号数乘法(示例代码)
1)乘积的高半部分为0
① 09H*09H
code segment
start:
MOV CL,09H
MOV AL,09H
MUL CL
MOV AX,4C00H
INT 21H
code ends
end start ;
两字节相乘,观察下述结果中AH为0,代表AH中不包含乘积的有效字,并且标志位CF=0F=0。
② 0010H*0101H
code segment
start:
MOV CX,0101H
MOV AX,0010H
MUL CX
MOV AX,4C00H
INT 21H
code ends
end start ;
两字相乘,观察下述结果中的DX为0,代表DX中不包含乘积的有效数字,并且标志位CF=OF=0。
2)乘积的高半部分不为0
①10H*FFH
code segment
start:
MOV CL,0FFH
MOV AL,10H
MUL CL
MOV AX,4C00H
INT 21H
code ends
end start ;
两字相乘时,观察下述结果中AH=0FH,代表AH中包含乘积的有效位,并且CF=OF=1。
②0010H*FFFFH
code segment
start:
MOV CX,0FFFFH
MOV AX,0010H
MUL CX
MOV AX,4C00H
INT 21H
code ends
end start ;
两字相乘时,观察图中DX为000FH,代表DX包含有乘积的有效,且CF=OF=1。
1.2 有符号数乘积(示例代码)
1)乘积的高半部分是低半部分的符号位的扩展
FEH * 0FH ( -2 * 15 = -30)
code segment
start:
MOV CL,0FH
MOV AL,0FEH
IMUL CL
MOV AX,4C00H
INT 21H
code ends
end start ;
两字节相乘,观察结果中AX的高半部分DE为FF,即低半部分的符号位的扩展,则CF=0F=0;
2)乘积的高半部分不是低半部分的符号位的扩展
80H * 10H (-128*16 = -2048)
code segment
start:
MOV CL,080H
MOV AL,10H
IMUL CL
MOV AX,4C00H
INT 21H
code ends
end start ;
两字节相乘,观察结果AX的高半部分不是低半部分的符号位的扩展,则CF=OF=1。
1.3 例题
设AL=0FEH,CL=11H,两数均为无符号数,求AL与CL的乘积。
分析: 无符号数乘积指令为MUL,操作数为寄存器CL。
关键部分: MUL CL;
完整代码:
code segment
start:
MOV CL,11H
MOV AL,0FEH
MUL CL
MOV AX,4C00H
INT 21H
code ends
end start ;
运行结果:
由于两无符号数相乘,其乘积高半部分不等于0,所以CF=OF=1。
2. 除法指令
分类: 无符号数除法指令、有符号数除法指令
寻址方式: 隐含寻址
操作数: 隐含了被除数,除数由指令给出
要求: 被除数的字长必须为除数字长的两倍。
功能: 两数相除。若除数为8位,则被除数为16位,放在AX中。若除数为16位,则被除数为32位,并放在DX和AX中。得到的余数放高半部分,得到的商放低半部分。
格式: DIV (IDIV) reg/mem
若除法运算的结果大于寄存器可保存的值,即超出了8位或16位无符号数的可表达单位,则CPU内部会产生一个类型0中断。
2.1 字节除法(示例代码)
40H / 05H (64/5 = 12 余 4 )
code segment
start:
MOV CL,05H
MOV AX,40H
DIV CL
MOV AX,4C00H
INT 21H
code ends
end start ;
运行结果:
结果表明:
余数放在高半部分,商放在低半部分。
2.2 字除法(示例代码)
00080005H / 8000H (65541/32768=2余5)
code segment
start:
MOV CX,8000H
MOV AX,0005H
CWD
MOV DX,0008H
DIV CX
MOV AX,4C00H
INT 21H
code ends
end start ;
运行结果:
结果表明:
两字相除,余数放在高半部分,商放在低半部分。
2.3 0中断(示例代码)
当除法运算的结果大于寄存器可保存的值。
0001 0000 H / 0001H (商大于1个字能表示的范围)
code segment
start:
MOV CX,0001H
MOV AX,0000H
CWD
MOV DX,0001H
DIV CX
MOV AX,4C00H
INT 21H
code ends
end start ;
运行结果:产生一个类型0中断