若[X]补 = X0 X1 X2… Xn
,按前面讲过的,则在[X/2] 补= X0 X0X1
X2… Xn 。同理,若已有 [X+Y]补 ,则[(X+Y)/2
]补也是将 [X+Y]补 的符号连同其数值位同时右移一位,并使符号位保持不变,这对 [X+Y]补
的符号为0(表示正)或为1(表示负)都是正确的。这表明,在讨论补码乘运算时,对被乘数或部分积的处理上与原码乘法有某些类似,差别仅表现在被乘数和部分积的符号位要和数值位一起参加运算。
若[Y]补 = Y0 Y1 Y2… Yn ,则当Y0为0时,[Y]补与[Y]原相同,很容易证明,直接用 [Y]补 去乘 [X]补
就能得到正确的[X*Y]补。但当Y0为1时,即Y为负值时,则有
n
Y = -1 + ∑ Yi* 2-i(通过数的补码求数的实际值,见公式2.12)
i=1
n n
故有 X * Y = X * ( -1 + ∑ Yi * 2-i) = X * ∑ Yi* 2-i- X
i=1 i=1
这表明,当Y为负值时,用补码乘计算[X*Y]补, 是用[X]补乘上[Y]补的数值位,而不理[Y]补符号位上的1,乘完之后,在所得的乘积中再减X,即加[-X]补。就是说,当Y值为负时,需对求得的积再做一次加[-X]补的校正操作,得到的才是补码形式的正确的积。这种方案需区分乘数的符号,按其正负做一步不同的操作。
实现补码乘法的另一个方案是比较法,是由BOOTH夫妇最早提出来的,故又称BOOTH法。这一方法的出发点是避免区分乘数符号的正负,而且让乘数的符号位也参加运算。可以用如下公式推导出它的实现原理:
n
X * Y = X * ( -1 + ∑ Yi* 2-i ) (逐项展开则得)
i=1
= X * [ -Y0 + Y1*2-1 + Y2*2-2 + … + Yn*2-n ]
= X * [ -Y0 +(Y1-Y1*2-1) + (Y2*2-1 - Y2*2-2 )
+ … + (Yn*2-(n-1) - Yn*2-n) ] (合并相同幂次项得)
= X * [(Y1- Y0)+(Y2- Y1)*2-1 + … +(Yn-1- Yn)*2-(n-1) +(0 -
Yn)*2-n))]
n
= X * ∑ ( Yi+1 - Yi )* 2-i (写成累加求和的形式,得到实现补码乘运算的算法)
i=0
将上述公式展开,则每一次的部分积为:
[P1]补 = [ 2-1(Yn+1 - Yn)* X ) ]补
[P2]补 = [ 2-1(P1 + (Yn - Yn-1)* X ) ]补
…
[Pi]补 = [ 2-1(Pn-i + (Yn-i +2 - Yn-i +1)* X ) ]补
…
[Pn]补 = [ 2-1(Pn-1 + (Y2 - Y1)* X ) ]补
[Pn+1]补 = [( Pn + (Y1 - Y0 )* X ) ]补
则最终补码乘积为 [X*Y]补 = [Pn +1]补
由上述公式可以看到,比较法是用乘数中每相邻的两位判断如何求得每次的相加数。每两位Yi和Yi+1的取值有00、01、10和11四种组合,则它们的差值分别为0、1、-1和0,依据上述公式可以看出,非最后一次的部分积,分别为上一次部分积的1/2(右移一位)的值Rj、Rj+[X]补、Rj-[X]补(
即Rj+[-X]补) 和Rj,但一定要注意,最后一次求出的部分积即为最终乘积,不执行右移操作。
用此法计算乘积,需在乘数寄存器的低一位之后再补充一位Yn+1,并使其初值为0,再增加对Yn和Yn+1两位进行译码的线路,以区分出Yn+1-Yn
4种不同的差值。对n位的数(不含符号位)相乘,要计算n+1次部分积,并且不对最后一次部分积执行右移操作。此时的加法器最好采用双符号位方案。
看一个采用比较法完成补码数相乘的例子。
假定 [X]补 = 001101(双符号位) , [Y] = 10110(单符号位)
则 [-X]补 = 110011
最后相乘结果 [X*Y]补 = 101111110 (单符号位)。
验算 [X]补= 001101, X= +0.1101, 即X=+13/16 ,
[Y]补= 10110, Y= -0.1010, 即Y=-10/16 ,
X * Y = 130/256 =(-0.10000010), [X*Y]补 = 101111110,符号位和数值位与上述结果是一致的。
|
|