【汇编语言】乘法(MUL/IMUL)

这篇博客详细讲解了汇编语言中乘法指令MUL和IMUL的区别及使用。IMUL用于有符号数乘法,涉及符号扩展和溢出判断,而MUL则处理无符号数乘法。通过实例分析了乘法过程、标志位响应,并解释了如何确定是否溢出。博客还讨论了不同溢出条件对结果的影响以及无符号数乘法的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

乘法(MUL/IMUL)

麻!属实是被这个有符号乘法给整麻了,教材就一行例子直接不解释了,关于标志位溢出的一概不谈,屁用没有。然后去网上查了查好像说明白了但又没完全明白,以至于我刚刚才明白

先说这有符号乘法!

IMUL(signed multiply)有符号数乘法

格式:MUL SRC

操作:

  • 当操作数为字节时, ( A X ) ← ( A L ) × ( S R C ) (AX)\gets (AL)\times (SRC) (AX)(AL)×(SRC)
  • 当操作数为字时, ( D X , A X ) ← ( A X ) × ( S R C ) (DX, AX)\gets (AX)\times(SRC) (DX,AX)(AX)×(SRC)

标志位响应:

  • 当乘积的高半部分是低半部分的符号扩展时,表示未溢出, O F = C F = 0 OF=CF=0 OF=CF=0
  • 当乘积的高半部分不是低半部分的符号扩展时,表示溢出, O F = C F = 1 OF=CF=1 OF=CF=1

符号扩展

微机系统中,有时需要将一个数据从位数较少扩展到位数较多,例如,在执行除法指令时,由于对字节除数相除要求被除数为16位,对字除数要求被除数为32位,即被除数必须为除数的倍长数据,因此就涉及数据的位数扩展问题,具体的扩展有符号扩展与零扩展两种方法

  1. 当要扩展的数据是无符号数时可采用零扩展。即在最高位前扩展0,补充够位数即可
  2. 当要扩展的数据是有符号数时需采用符号扩展。由于采用补码形式表示的整数具有固定的长度,因此在汇编指令系统中,经常有一些指令需要将其中的操作数进行符号位扩展。譬如两个8位或16位数据进行相加或者相减运算时,当有不足位数要求的数据时,需要将少位数据扩展成与位数要求相一致的数据;两个数据相除时,被除数应必须是除数的倍数等。 符号扩展的方法是将需要扩展的数据的符号位填入到扩展的每一位,以保持其作为有符号数的值的大小不变。这里要注意,要扩展的数须是用补码形式表示的有符号数,符号扩展后。其结果仍是该数的补码。 因此,对于补码表示的数,其正数的符号扩展是将其符号位0向左扩展(补0);其负数的符号扩展是将其符号位1向左扩展(补1)

有符号数相乘的步骤

  1. 符号位扩展,将两个乘数都扩展至原来的两倍大(例如,字节数据 1000   1101 1000\ 1101 1000 1101扩展为字数据 1111   1111   1000   1101 1111\ 1111\ 1000\ 1101 1111 1111 1000 1101
  2. 扩展后的数据相乘
  3. 取有效位(即为原乘数位数的两倍)

举例:

F 1 H × F 1 H F1H\times F1H F1H×F1H ( − 15 ) × ( − 15 ) = ( + 225 ) (-15)\times (-15)=(+225) (15)×(15)=(+225)

  1. 符号位扩展
    1111   0001 → 1111   1111   1111   0001 1111\ 0001\to {\color{Blue} 1111\ 1111} \ 1111\ 0001 1111 00011111 1111 1111 0001

  2. 扩展后的数据相乘
    1111   1111   1111   0001 × 1111   1111   1111   0001 1111   1111   1110   0010   0000   0000   1110   0001 \begin{array}{r} {\color{Blue} 1111\ 1111} \ 1111\ 0001\\ \times {\color{Blue} 1111\ 1111} \ 1111\ 0001\\ \hline {\color{Gray} 1111\ 1111\ 1110\ 0010} \ 0000\ 0000\ 1110\ 0001 \end{array} 1111 1111 1111 0001×1111 1111 1111 00011111 1111 1110 0010 0000 0000 1110 0001

  3. 取有效位
    保留低16位有效位 0000   0000   1110   0001 0000\ 0000\ 1110\ 0001 0000 0000 1110 0001
    A H = 00 H AH=00H AH=00H A L = E 1 H AL=E1H AL=E1H

  4. 判断标志位响应
    由于 A H AH AH并不是 A L AL AL的符号扩展
    0000   0000   1 110   0001 {\color{Green} 0000\ 0000} \ {\color{Red} 1} 110\ 0001 0000 0000 1110 0001
    A H AH AH全为0,而 A L AL AL最高位(符号位)为1,因此溢出 O F = C F = 1 OF=CF=1 OF=CF=1

    有符号数乘积的高半部分只起到表示符号的作用,溢出时,其是无效的信息可不关注,因此对于8位有符号数相乘不溢出的结果范围即为 − 128 -128 128 ~ + 127 +127 +127,这里低8位最高位为1表示结果为负数,而两乘数均为负数,结果应为正数,故产生了溢出

  5. debug测试
    在这里插入图片描述

24 H × F D H 24H\times FDH 24H×FDH ( + 36 ) × ( − 3 ) = ( − 108 ) (+36)\times (-3)=(-108) (+36)×(3)=(108)

0000   0000   0010   0100 × 1111   1111   1111   1101 0000   0000   0010   0011   1111   1111   1 001   0100 \begin{array}{r} {\color{Blue} 0000\ 0000} \ 0010\ 0100\\ \times {\color{Blue} 1111\ 1111} \ 1111\ 1101\\ \hline {\color{Gray} 0000\ 0000\ 0010\ 0011} \ {\color{Green} 1111\ 1111\ 1} 001\ 0100 \end{array} 0000 0000 0010 0100×1111 1111 1111 11010000 0000 0010 0011 1111 1111 1001 0100

这里高半部分是低半部分的符号扩展,因此未溢出, O F = C F = 0 OF=CF=0 OF=CF=0,这里结果 1001   0100 1001\ 0100 1001 0100即为 − 108 -108 108的补码形式

在这里插入图片描述

MUL(unsigned multiply)无符号数乘法

格式与操作与IMUL相同,用来作无符号数乘法

标志位响应:

  • 当乘积的高半部分不为0时,表示溢出, C F = O F = 1 CF=OF=1 CF=OF=1
  • 当乘积的高半部分为0时,表示未溢出, C F = O F = 0 CF=OF=0 CF=OF=0

很简单就直接乘,乘就完事了!直接上例子(和有符号的第一个例子数据相同,看其对比)

举例:

F 1 H × F 1 H F1H\times F1H F1H×F1H 241 × 241 = 58081 241\times 241=58081 241×241=58081

1111   0001 × 1111   0001 1110   0010   1110   0001 \begin{array}{r} 1111\ 0001\\ \times 1111\ 0001\\ \hline 1110\ 0010\ 1110\ 0001 \end{array} 1111 0001×1111 00011110 0010 1110 0001

显然这里高半部分不为0,故溢出 C F = O F = 1 CF=OF=1 CF=OF=1

在这里插入图片描述

这里的溢出和有符号的溢出都是针对于低半部分范围而言的,即对于无符号数的乘积不溢出的范围则是 0 0 0 ~ 255 255 255,但是由于高半部分的数据由 A X AX AX的高半部分 A H AH AH存储,故虽说是“溢出”但是其总的结果是正确的、有效的;而对于有符号乘积,其 A H AH AH存的只是符号扩展信息,当发生溢出时,则代表该结果是错误的

另外,无符号数相乘结果总是正确的,因为最大的乘积也不会超越其乘数位数的两倍可表示的范围

1111   1111 × 1111   1111 1111   1110   0000   0001 \begin{array}{r} 1111\ 1111\\ \times 1111\ 1111\\ \hline 1111\ 1110\ 0000\ 0001 \end{array} 1111 1111×1111 11111111 1110 0000 0001

F F H × F F H = F E 01 H FFH\times FFH=FE01H FFH×FFH=FE01H

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值