加法运算按从右到左的顺序一位一位地求和,并将进位累加到左侧相邻的高位。而减法则是通过加法来实现的:先将减数求补,然后加上被减数。对于原码、反码机器数的加减运算过程均较为复杂,通常不采用它们进行定点数的加减运算。
目前的计算机系统普遍采用补码实现整数加减运算,在浮点数的运算中,还用移码实现阶码的加减运算。
补码的加减运算的公式是:
[X+Y]补 = [X]补 + [Y]补 (mod 2 n+1)
[X-Y]补 = [X]补 + [-Y]补 (mod 2 n+1)
下面利用补码机器数的定义证明式
[X]补 = 2n+1 + X (mod 2 n+1)
[Y]补 = 2n+1 + Y (mod 2 n+1)
[X]补 + [Y]补 =2n+1 + X +2n+1 + Y (mod 2 n+1)
= 2n+1 + (X + Y) (mod 2 n+1)
= [X+Y]补 (mod 2 n+1)
任意两数之和的补码等于该两数的补码之和。
[X-Y]补 = [X+(-Y)] 补 = [X]补 + [-Y]补 (mod 2 n+1)
任意两数之差的补码等于被减数的补码与减数相反数的补码之和。
从[Y]补 求[-Y]补 ,该过程称为求补操作。
求补操作的规则是:包括符号位在内每一位取反,末位加 1。即:
若[Y]补 = Y0,Y1…Yn ,则 [-Y]补 = Y0#,Y1#…Yn# ;
若[Y]补 = Y0.Y1…Yn ,,则 [-Y]补 = Y0#.Y1#…Yn# 。
当运算结果超出机器数的表示范围时,称为溢出。当发生溢出时,计算机必须检测出来,否则会得到错误的结果。
显然,对于加减运算,当异号的两数相加或者同号的两数相减时,不会发生溢出。仅当同号的两数相加或者异号的两数相减时,才有可能发生溢出。
单符号位判溢方法
操作数和运算结果的正负是由其补码符号位指出的,而结果的符号位是错误的,这是因为:溢出导致数值位(实际上是进位)占用了符号位,真正的符号位被当作模 2n+1 舍去了。
单符号位判溢方法就是这四种溢出情况的直接综合表达。假设:Xf 是操作数 X 的补码符号,Yf是操作数 Y 的补码符号,Sf是加减运算结果 S 的补码符号,ADD#/SUB 是控制加减运算的控制信号, ADD#/SUB=0 做加法, ADD#/SUB=1,做减法,则溢出信号 V(为 1 有效)的表达式为:
进位判溢方法
单符号位判溢方法非常容易理解,但硬件实现略显繁琐,将各种情况下的最高有效位和符号位的进位用真值表列出。
其中,C1 是最高有效位(X1±Y1)的进位,Cf是符号位的进位。根据输入 Xf 、Yf 、C1 和全加器逻辑,可以得出运算结果 Sf 、Cf的取值。注意,在减法时,因为Y 必须取反加 1,所以全加时,Yf 应当取反。
V=C1 ⊕ Cf 即当最高有效位和符号位的进位不同时,就表明加减运算发生了溢出。这个判溢方法比上面的判溢方法在逻辑实现上,要简单得多。
双符号位判溢方法
双符号位判溢方法的运算规则是操作数 X 和 Y 采用双符号位补码参加运算,正数的双符号位为 00,负数的双符号位为 11。
当运算结果的两位符号 Sf1 Sf2 不同时,发生溢出。判溢表达式为: V=Sf1 ⊕ Sf2。其中,Sf1 是运算结果的正确符号位(即使发生溢出),Sf2 在发生溢出时储存运算结果的溢出位。当 Sf1Sf2=01 时,发生了正溢出,当 Sf1 Sf2=10 时,发生了负溢出。
一般在储存时,补码只保留一位符号位,在运算时,才可能使用双符号位。另外,为节省全加器的位数,有时在运算时仍使用单符号位,结果符号位为 Sf,但使用双符号位判溢原理,因为 Sf1= Xf ⊕Yf ⊕Cf ,Sf2=Sf,所以: V=Sf1 ⊕ Sf2 = Xf⊕ Yf⊕ Cf ⊕ Sf
双符号位补码又叫模 4 补码或者变形补码,即定点小数的模是 4,而非 2;n+1 位定点整数的模是 2n+2,而非 2 n+1。
在计算机运算中,经常用到移位运算。在计算机中,由于数据以二进制表示,且小数点位置固定,因此,二进制数据只能相对于小数点进行左移或者右移。二进制数据每相对于小数点左移一位,相当于乘以 2,数据放大了 2 倍;每相对于小数点右移一位,相当于除以 2,数据缩小了 2 倍。
移位运算对于计算机具有很大的实用价值。
采用移位指令对数据进行放大或者缩小2n 倍,比采用乘除法指令进行乘以或除以 2n,在速度上要快得多。
当计算机中没有乘除运算器时,可以采用移位器和加减法器,利用乘除串行运算方法的原理,来实现乘除运算器。
即使计算机指令系统中没有乘除运算指令,我们也可以利用移位指令和加减法指令来编制一个子程序,实现乘除运算功能。
算术移位的移位对象是带符号数据,即各种编码表示的机器数。算术移位的结果,在数值的绝对值上进行放大或缩小,同时,符号位必须要保持不变。
对于原码的算术左移,符号位不变,高位移出,低位补“0”。当左移移出的数据位为“1”时,发生溢出。算术右移时,符号位不变,低位移出,高位补“0”。
对于补码的算术左移,符号位不变,高位移出,低位补“0”。当左移移出的数据位正数为“1”、负数为“0”时,发生溢出。因此,为保证补码算术左移时不发生溢出,移位的数据最高有效位必须与符号位相同。所以,在硬件实现补码的算术左移时,直接将数据最高有效位移入符号位,不会改变机器数的符号(当不发生溢出时)。算术右移时,符号位不变,低位移出,高位正数补“0”,负数补“1”,即高位补符号位。
反码的算术移位规则是:算术左移时,最高有效位移入符号位,低位正数补“0”,负数补“1”;算术右移时,符号位不变,高位补符号位,低位移出。
根据移码的定义有:
[X]移 =2n+X -2n≤X≤2n-1
[Y]移 =2n+Y -2n≤Y≤2n-1
则有:
[X]移 + [Y]移 =2n+X+2n+Y= 2n+(2n+X+Y)=2n + [ X+Y]移
同理可得:
[X]移 + [-Y]移 = 2n + [ X-Y]移
使用移码求和,只需直接将移码相加,但由于符号位多加了一个“1”,所以结果必须将符号位取反。
使用移码求差,直接将被减数移码与减数相反数的移码相加,即[X]移 + [-Y]移,结果的符号位取反。
若使用移码和补码混合计算移码之和,由补码的定义得:
[Y]补 =2n+1+Y (mod2n+1)-2n≤Y≤2n-1
[X]移 + [Y]补 =2n+X+2n+1+Y= 2n+1+(2n +X+Y)= 2n+1 + [ X+Y]移 = [ X+Y]移(mod 2n+1)
同理,对于减法可得:
[ X-Y]移 = [X]移 + [-Y]补(mod 2n+1)
求两数之和或者之差的移码,可以用加数或者减数相反数的补码参加运算,实质上就是加数或者减数相反数的移码符号位取反送入加法器。
判溢:第一操作数采用移码表示,使用双符号位,但规定其最高符号位恒为 0;第二操作数采用补码,也使用变形补码
移码运算结果溢出的判断条件是:当结果的最高符号位 Sf1=1 时溢出,Sf1=0 时结果正确。Sf1Sf2=10 时,结果正溢出;Sf1 Sf2=11 时,结果负溢出。由于移码运算用于浮点数的阶码,当运算结果正溢出时,浮点数上溢;当运算结果负溢出时,浮点数下溢,当作机器零处理。
计算机中的十进制加法器通常采用 BCD 码设计。在二进制加法器的基础上,加上适当的校正电路,可以实现 BCD 码的加法器。
对于 8421BCD 码来说,当相加的两数之和超过 9 时,就产生向高一位 BCD 码的进位。但对于四位二进制加法器来说,只有在和超过 15 时,才有进位产生。因此,对于两个 8421BCD 码 A与 B 的和 S,有: 当 S>9 时,加 6 校正;当 S≤9 时,且无进位时,结果正确,不需校正。
假设参加运算的 2 个 8421BCD 码分别为:A=A8A4A2A1,B=B8B4B2B1,它们通过二进制加法器的运算结果是 S’=S8’S4’S2’S1’,BCD 码运算的正确结果是 S=S8S4S2S1,向高位的进位为 C1。那
么对 S’必须校正的情况有S’==1010、1011、1100、1101、1110、1111;或者进位C=1(S>15) 。
通过综合化简之后,校正的条件 P 为: P= S8’S4’ + S8’S2’ + C 。P=1,加 6 校正,否则无需校正。
对于余 3 码加法器,校正条件为进位 C,C=0,减 3 校正(即加 1101 校正);C=1,加 3 校正(加 0011 校正)。
由于 BCD 码的算术运算只用在很少进行复杂运算的系统中,因此,在目前的计算机硬件中,一般不设置专用的 BCD 码运算器,通常与二进制运算共用一个运算器,然后使用指令控制修正。所以,在计算机的指令系统中,一般具有 BCD 码校正指令,用户使用二进制的加减乘除运算指令进行运算之后,再用 BCD 码校正指令对运算结果进行调整。
由于计算机的软硬件在逻辑上具有一定的等价性,因此实现乘除法运算,可以有三种方式:
用软件实现。在某些低档机器或者模型机中,指令系统中没有乘除法指令,但具有加减运算和移位运算指令。相应的,在硬件上没有乘法器和除法器,只设置有并行加法器和移位器。此时,乘除运算可以通过编制一段子程序来实现。程序中运用串行乘除运算的算法,循环使用累加、右移指令实现乘法运算,循环使用减、右移指令实现除法。这种方式运算速度较慢,但硬件设计简单。
用硬件乘法器和除法器实现。在机器的指令系统中具有乘除法指令,在硬件上,设置有并行加法器、移位器和若干循环、计数控制逻辑电路,依据串行乘除运算的算法,将它们以硬联逻辑或者微程序的方式构成乘法器和除法器。显然,这种方式相对软件实现方法,运算速度提高,但硬件设计也相对复杂。
用高速的阵列乘法器和阵列除法器来实现。在机器的指令系统中设置有乘除法指令,它们实现的硬件基础是专用的、并行运算的阵列乘法器和阵列除法器。这种方式,硬件相当复杂,但牺牲硬件代价,赢得了速度。
由于原码表示法是最接近真值的表达方式,因此使用原码实现乘法运算的方法也非常类似于真值的乘法计算方法。下面就先讨论真值的手工乘法运算。
手工乘法算法
如同十进制乘法运算一样,在对两个二进制数据进行手工笔算乘法时,首先对它们的绝对
值进行二进制乘法,得到积的绝对值,然后根据正正得正,负负得正、正负得负、负正得负的原则得出结果符号位。我们先来研究绝对值的二进制乘法运算过程。
从右至左,对应每一位乘数求得一项位积(即中间结果),并将位积逐位左移,然后将所有的位积一次相加,得到最后的乘积。
若直接将手工算法用机器硬件完成,则对于 n 位乘 n 位的乘法,必须具备一个 2n 位宽的、具有 n 个输入的并行加法器。实际上,一般的加法器只具有两个输入端,对于这一点,解决办法为:将 n 个位积的一次相加转化为 n 次的两数累加,每次累加的对象是上一次的部分积和本次的位积,初始部分积为 0。
另外,在手工算法的相加中,对于相邻的两个位积,真正对应做加法的实际只有 n 位,最低位是直接得出不需运算的。所以,在逐次累加时,n 位宽的加法器是足够用的。但是,必须把手工算法中的每次位积左移一位,变为每次累加得到的部分积右移一位再加新位积,但做加法的两数的对应关系并没有改变。
绝对值乘法的机器算法:从乘数的最低位开始,每次根据乘数位得到其位积,乘数位为 0,位积为 0,乘数位为 1,则位积为被乘数;用原部分积右移一位加上本次位积,得新部分积;初始部分积为 0;循环累加右移 n 次(乘数的位数)。
原码一位乘法
由二进制绝对值乘法的机器算法可以得到使用原码求积的算法。
假设[X]原=XS X1 X2 …„Xn ,[Y]原=YSY1 Y2 …Yn ,P=X·Y,PS是积的符号:
PS = XS ⊕YS ,|P| = |X|·|Y|,即符号位单独处理,绝对值参加乘法运算。
初始部分积为 0,Yi=1,部分积加|X|,Yi=0,部分积加 0,累加结果右移一位,得新部分积。
累加右移 n 次,即 i=n,n-1…2,1。
该算法中,由于每次根据乘数的一位来计算位积,因此,称为原码一位乘法。注意,虽然是绝对值运算,但部分积仍保留一位附加的符号位(相当于进位标志),用于暂时储存累加时可能出现的溢出位,接下来的右移将使其回到数值位上。另外,因为采用绝对值运算,所以部分积右移时,最高位总是补“0”。
原码乘法的硬件实现
使用了 3 个 n位寄存器 A、B、Q,分别用来存放部分积、被乘数 X 的绝对值|X|、乘数 Y 的绝对值|Y|(同时保存乘积的低位)。并行加法器实现累加,计数器用来对运算步骤进行计数并加以控制。
运算前寄存器 A 清零,|X|装入寄存器 B,|Y|装入寄存器 Q,计数器置入乘数的数值位数 n。
当乘法控制信号 MUL=1 时,D 触发器被置“1”,与门打开,则时钟脉冲源源不断进来,时钟脉冲上升沿一方面用来控制计数器减 1 计数,另一面用来控制并行加法器的累加结果打入寄存器 A;在时钟脉冲下降沿,又控制寄存器 A 和 Q 联合右移一位。循环往复,直到计数器计数至 0 时,“=0”信号将使 D 触发器清零,锁住时钟脉冲,寄存器 A 和 Q 的内容不会再改变,A 中为乘积高 n 位,Q 中为乘积低 n 位。
B 寄存器中的被乘数绝对值,经过控制逻辑电路生成位积,送入并行加法器,与 A 寄存器中的部分积相加,结果再通过缓冲门送入 A 寄存器保存。每累加一次,并行加法器的最高位进位置入“进位/借位”触发器 CF,然后与寄存器 A 和 Q 联合右移一位,即寄存器 A 的最低位移入Q 的最高位,CF 移入寄存器 A 的最高位,Q 的最低位舍去。 Q 寄存器的最低位 Qn 用来控制生成位积,因此图中“控制逻辑”的电路是“与”逻辑,Qn =1,B 寄存器中数据以原代码形式送入并行加法器,位积为|X|;Qn =0,B 寄存器中数据以全“0”形式送入并行加法器,位积为 0。
补码一位乘法——校正法
假设[X]补 = X0 .X1…Xn ,[Y]补 = Y0 .Y1…Yn ,则有: [X·Y]补 = [X]补·( 0.Y1…Yn)+ Y0·[-X]补 。
当使用补码做乘法时,可以将乘数 Y的补码的数值部分,象原码一样直接做乘法,最后再根据乘数 Y 的符号位对结果做修正:当符号为正(即为“0”),无需修正;当符号为负(即为“1”),减 X 修正。这种方法被称为补码乘法的校正算法。
为保存在累加时临时出现的溢出位,需要部分积采用两位符号位,另外部分积右移时,必须采用补码的移位规则。补码的乘法中,符号位不再象原码一样单独处理,而是整个补码一同参加运算。
补码一位乘法——Booth 算法
以上的推导结果意味着可以将乘数 Y 的补码在最末位添加一位附加位 Yn+1(初始为 0)后,进行重新编码,编码规则为相邻两位,两两相减,低位减去高位,得到新编码 a0 a1…an-1 an,然后再使用新编码对[X]补作乘法。
补码 Booth 算法的运算规则如下:
假设[Y]补 = Y0 .Y1…Yn :
被乘数 X 和乘数 Y 均以补码的形式参加乘法运算,运算的结果是积的补码。
部分积和被乘数 X 采用双符号位,乘数 Y 采用单符号位。
初始部分积为 0;运算前,在乘数 Y 的补码末位后添加一位附加位 Yn+1,初始为 0。
根据 YnYn+1的值,进行累加右移操作,右移时遵循补码的移位规则。
-运算前,寄存器 A 清零,寄存器 B 中装入X 的模 4 补码,寄存器 Q 的高 n+1 位装入乘数 Y 的补码,Qn+1初始为 0,计数器置初值 n+1。每次根据 Q 寄存器的最末两位 Qn Qn+1 来判断位积,位积有三种:0、[X]补、[-X]补。另外,部分积右移时,必须采用补码的算术移位规则,即 A 寄存器的符号位(最高位)不变,同时复制符号位至次高位。累加右移了 n+1 次后,因为最后一次不应该右移,所以最后乘积的补码取寄存器 A 和 Q 的中间 n+1 位(A 的最高 2 位和 Q 的最末位舍去)。
阵列乘法器的原理类似于二进制手工算法,算式中,位积的每一位 XiYj都可以用一个与门实现,而每一位的相加均可以使用一个全加器来实现。
为避免每一行的全加器从低位到高位的进位延迟,每个全加器 FA 的进位向斜线方向传递,即本行所有全加器产生的进位要传递到下一行的高位,下一次再执行加法。虚线框内是最下面的一行全加器,其进位逻辑可以采用并行进位逻辑,以加快速度。由此,可以推导出 n 位×n 位绝对值阵列乘法器共需要 n×n 个与门,n×(n-1)个全加器。
对于原码的阵列乘法器,只要在绝对值阵列乘法器的基础上,添加一个异或门,以产生积的原码的符号位。而补码的阵列乘法器,则要先通过一个补码求绝对值的逻辑电路,变为绝对值后送入绝对值阵列乘法器,运算得到积的绝对值,然后再通过一个绝对值求补码的逻辑电路,根据积的符号求出积的补码形式。
X0’ …Xn-1’ Xn’是 X 的补码形式,其中 X0’是符号位,X1…Xn-1Xn 则是求得的绝对值。
当 X0’为 0 时,表明是正数,图中的与门输出为 0,则异或门的输出为补码本身,即 Xi=Xi’。
当 X0’为 1 时,表明是负数,图中的与门输出取决于低位的补码值,若低位为 0,则本位的绝对值为补码本身,即 Xi=Xi’;若低位为 1,则本位的绝对值为补码取反。
该电路主要是针对负数的补码求真值的情况:当最低的 m 位为 0 时,则低 m 个与门的输出就为 0,真值的最低的 m+1 位就是补码本身,而其他高位对应的与门输出均为 1,所以高位全部取反。图中的或门就用来从负数补码的最低位搜索第一个“1”。
由上面的分析可以知道,补码求绝对值电路的电路同样适合于绝对值求补码,此时X1’ …Xn-1’ Xn’是绝对值,X1…Xn-1Xn 是求得的补码数值位,X0’则是真值的补码符号,由它来控制如何产生绝对值的补码,电路原理同上。
手工除法算法
两个二进制数据的除法运算,实际上是对它们的绝对值进行二进制除法,得到商的绝对值,商的符号位另外计算。
手工进行二进制除法的过程是:
首先判断被除数是否大于除数,若大于等于除数,本次商上 1,被除数减去除数得到余数,否则,本次商上 0,不做减法,把被除数当作余数;然后在余
数的后面补 0,再用余数和右移一位的除数相比,若够减,则商上 1,否则商上 0,依次重复,直至余数为 0 或者商的位数满足精度要求。通常将每次减法得到的余数称为部分余数。
对手工算法做如下改进,即可适合机器运算:
手工计算中,通过心算来判断够减或者不够减,而计算机只能通过做减法测试来实现判断:结果大于等于 0,表明够减,商 1;结果小于 0,表明不够减,商 0。
将手工算法中用部分余数减去右移一位的除数,改变为将部分余数左移一位,再直接与不右移的除数相减。
原码恢复余数算法
假设[X]原=XS .X1 X2 …Xn ,[Y]原=YS .Y1 Y2…Yn ,Q 是 X÷Y 的商,QS是商的符号,R 是 X÷Y 的余数,RS是余数的符号,则原码除法运算的规则是:
Qs=Xs⊕Ys,Rs=Xs,|Q|=(|X|-|R|)/|Y|,即符号位单独处理,绝对值参加除法运算。
余数和被除数、除数均采用双符号位,以保存部分余数左移一位的溢出位;初始余数为|X|。
每次用部分余数减去|Y|(通过加上[-|Y|]补来实现),若结果的符号位为 0,则够减,商 1,部分余数左移一位;若结果的符号位为 1,则不够减,商 0,先加|Y|恢复余数,然后将部分余数左移一位。 循环此步骤,共做 n+1 次,最后一次不左移,但若最后一次上商 0,则必须+|Y|恢复余数;若为定点小数除法,余数则为最后计算得到的余数右移 n 位的值。
该算法中,由于当不够减时,上商 0,那么就不应该减|Y|,所以必须先加|Y|恢复余数才能保证余数的正确性,所以,这种算法叫做原码的恢复余数算法。另外,部分余数左移时,采用补码移位规则,最低位补 0,最高符号位不变,最高有效位移入低符号位,可能临时发生溢出,但随后进行的减法将会使部分余数恢复正常。
原码不恢复余数算法(加减交替法)
对于 n 位的定点小数做原码恢复余数除法,商 0 时做两次加法,商 1时做一次加法,显然,其中的加法运算的次数取决于商的值,是不固定的。这种状况下要控制运算次数较为困难,因此很不利于硬件的实现。
从原码恢复余数除法的算法中可知,由本次的部分余数 Ri求下一次的部分余数 Ri+1 的方法是:
当 Ri ≥0 时,Ri左移一位,再减去除数绝对值,得新余数 Ri+1,即 Ri+1 = 2Ri -|Y|;
当 Ri<0 时,先加除数绝对值恢复余数,再左移一位,然后减去除数绝对值,得新余数 Ri+1,即 Ri+1 = 2(Ri +|Y|)-|Y|= 2Ri +|Y|。 这表明当不够减时,商 0,之后可以不恢复余数,而是直接将部分余数左移一位,下一次通过做加|Y|的方法来求新余数,以得到下一位商。
这样,就推导出原码的不恢复余数算法的规则:
Qs=Xs⊕Ys,Rs=Xs,|Q|=(|X|-|R|)/|Y|,即符号位单独处理,绝对值参加除法运算。
部分余数和被除数、除数均采用双符号位,以保存余数左移一位的溢出位;初始余数为|X|。
每次用部分余数减去|Y|(通过加上[-|Y|]补来实现),若结果的符号位为 0,则够减,上商 1,部分余数左移一位,然后通过减去|Y|的方法来求下一次的部分余数;若结果的符号位为 1,则不够减,上商 0,部分余数左移一位,然后通过加上|Y|的方法来
求下一次的部分余数。循环操作此步骤,共做 n+1 次,最后一次上商后不左移,但若最后一次上商 0,则必须+|Y|恢复余数。
寄存器 A、B 和并行加法器为 n+2 位宽度的,Q寄存器为 n+1 位宽度的。A 用来存放被除数 X 的绝值,B 用来存放除数 Y 的绝对值,Q 用来存放商的绝对值。与乘法的硬件实现类似,并行加法器实现加减,计数器用来对运算步骤进行计数并加以控制。
运算前 A 置入|X|,B 置入|Y|,寄存器 Q 清零后末
位置“1”,计数器置入商的位数 n+1。当除法控制信号 DIV=1 时,启动除法器运行。每次根据最后的上商值即 Q 的最低位 Qn 来决定本次的操作:Qn=0,加 B 寄存器的原码(即加|Y|); Qn=1,加 B 寄存器的反码,并使得 C0= Qn=1(即减|Y|)。 这一部分通过控制逻辑电路实现。
在时钟的上跳沿,加减计算结果通过缓冲器置入累加器 A;在时钟的下跳沿,A、Q 联合循环左移一位,其中把运算结果的符号位取反后送入 Q 的最低位 Qn,即根据 A 中的符号位即A0 来产生商:A0=1(负数,不够减),商 0;A0=0(正数,够减),商 1。因为初始时 Qn=1,所以第一次做减法,即|X|-|Y|。由于定点小数的除法要求|X|<|Y|,所以第一次一定不够减。随着第一个脉冲的来临,就开始了移位上商和加减运算的循环。第 n+1 个时钟的下跳沿将执行循环左移并上商最后一位,而之前置入 Qn 的那个“1”被左移至 A 的最低位,因此,运算结果:Q寄存器中为 n+1 位的商的绝对值,累加器 A 的高 n+1 位是余数的低位部分。若最后一位商为 0,则要产生正确的余数,还需要+|Y|恢复余数。
补码的除法采用不恢复余数方法(又称补码加减交替法),直接对两个数据的补码循环进行加减和左移操作,计算结果为商的补码。
商符的确定:从除法运算规则的角度来说,商的补码符号应该是被除数 X 和除数Y 的补码符号的异或结果,即同号为正,异号为负。
第一次比较操作:由于除法的本质是被除数(余数)和除数的绝对值的比较,因此,为了得到第一次的部分余数[R0]补,当[X]补与[Y]补同号时,应该做减法进行绝对值的比较;当[X]补与[Y]补异号时,则应该做加法进行绝对值的比较。
够减/不够减的判定:在原码不恢复余数除法中,通过判断部分余数 Ri的符号来判定够减/不够减。而在补码不恢复余数除法中,参加运算的是带符号的补码,所以当余数[Ri]补与被除数[X]补同号时,表明够减;异号时,表明不够减。由于被除数在做了加减操作之后,符号可能被改变了,因此,通常与除数[Y]补的符号相比较。在[X]补与[Y]补同号时,上述够减/不够减的判定规则不变,但当[X]补与[Y]补异号时,上述够减/不够减的判定规则正好相反。
上商的规则:按照除法上商规则,当够减时,商的绝对值商 1,不够减时,商的绝对值商 0。显然,在补码除法中,商是以补码形式产生的,因此,当商符为正时,够减商 1,不够减商 0;但当商符为负时,够减商 0,不够减商 1。
新余数的产生:参照原码不恢复余数除法运算,当够减时,在余数左移之后,应该继续做绝对值减法来产生下一次余数;而当不够减时,在余数左移之后,则应该继续做绝对值加法。在补码运算时,同第一次的比较操作类似,当[X]补与[Y]补同号时,绝对值的加和减操作就是补码的加和减操作,但当[X]补与[Y]补异号时,绝对值的加和减操作则是补码的减和加操作。
由表可以归纳出补码不恢复余数除法的规则。假设[X]补=XS .X1 X2 …Xn ,[Y]补=YS .Y1Y2…Yn ,Q 是 X÷Y 的商,R 是余数,商若采用最末位恒置“1”法,则补码除法运算的规则是:
X 和 Y 以补码形式参加除法运算,商也以补码的形式产生。余数和被除数、除数均采用双符号位。
当[X]补与[Y]补同号时,第一次做[X]补+[-Y]补操作,当异号时,第一次做[X]补+[Y]补操作,
得到第一次的部分余数[R0]补。
当[Ri]补与[Y]补同号时,上商 1,然后余数先左移一位,加[-Y]补得到新余数[Ri+1]补;当
[Ri]补与[Y]补异号时,上商 0,余数左移一位,加[Y]补得到新余数[Ri+1]补。循环操作该步骤,共做 n 次,得到 1 位商符和(n-1)位商的补码数值位,最末位采用恒置“1”法。
在该算法中可以发现,第一次的操作特殊处理,与后面的操作不同,但按照求商值的规则来求商符(这是在要求|X|<|Y|的前提下,即第一次操作的结果一定是不够减的,从而保证商不会发生溢出)。
第二种运算规则,将求商符与求商值的规则统一了,即将[X]补视为[R0]补,先根据[Ri]补与[Y]补同号还是异号即求商值的规则来直接上商符:同号上商 1,然后进行左移[R0]补一次和+[-Y]补操作;异号上商 0,然后进行左移[R0]补一次和+[Y]补操作。这样,商符正好相反,所以在操作完成后,必须将商符取反。这种方法的运算规则为:
X 和 Y 以补码形式参加除法运算,商也以补码的形式产生。余数和被除数、除数均采用双符号位。部分余数初始为[X]补,即[R0]补=[X]补。
当[Ri]补与[Y]补同号时,上商 1,然后余数先左移一位,加[-Y]补得到新余数[Ri+1]补;
当[Ri]补与[Y]补异号时,上商 0,余数左移一位,加[-Y]补得到新余数[Ri+1]补。 循环操作该步骤,共做 n 次,得到 1 位商符和(n-1)位商的补码数值位,最末位采用恒置“1”法。
对比补码不恢复余数除法的两种方法,显然,第二种方法更适合硬件设计。仔细分析第二种方法可以发现,它的硬件设计应该与原码的不恢复余数除法非常相似。不同的,一是寄存器初始装入的值不同:A 寄存器初始装入[X]补,B 寄存器初始装入[Y]补,计数器初值为 n;二是上商的规则不同:A 和 B 的符号相异商 0,相同商 1,硬件中把 A0 和 B0 异或的值循环左移至 Q 的最低位 Qn;三是操作 n 次后,Q 最末位置 1,最高位取反。其他电路原理同原码的不恢复余数除法。
利用大规模集成电路技术可以设计制造出阵列除法器,以期实现更快的除法运算速度。阵列除法器由若干个可控加减单元 CAS 构成,将每步的“左移—加减”操作在一拍中完成。
CAS 由一个全加器和一个异或门组成,当加减控制信号 P=0 时,除数 Y 以原变量形式输入到全加器,该 CAS 是一个加法器;当 P=1 时,除数 Y 以反变量形式输入到全加器,如果此时 P 又作为最低位的进位,则该 CAS 可以成为一个减法器。
在构成绝对值阵列除法器时,各 CAS 单元仿照手工除法算法右斜错位设计,每一行使用同一个加减控制信号 P,同时 P 送入本行最低位的进位。由于第一次作减法,因此第一行的 P 信号置为 1,将被除数的高位减去除数,得到的余数送下一行的 CAS 单元,作为被减数/被加数。本次的商由最高位(附加符号位)的 CAS 单元的进位 C 产生,若 C=1,则没有借位,表明够减,商 1;若 C=0,则有借位,表明不够减,商 0。下一行的加减控制信号 P 则由本次的商值决定,若本次商 1,下一行做减法,P=1;若本次商 0,下一行做加法,P=0。所以,本行的商值直接作为下一行的 P 信号。
运算器的基本功能是数据信息的算术逻辑运算,在控制器的控制下,运算器完成其功能。它的组成和结构取决于计算机本身的性能要求,因而差异较大。但其基本组成包括算术逻辑运算单元 ALU、暂存器、通用寄存器堆、标志寄存器、内部总线和其他可选电路,其核心部件是进行算术逻辑运算的 ALU。
暂存器用来存放参与运算的数据及运算结果,它只对硬件设计者可见,只被控制器硬件逻辑控制或微程序所访问,是程序员不可见的。
通用寄存器堆用于存放程序中用到的数据,它可以被软件设计者所访问,是程序员可见的。标志寄存器用于记录运算器上次运算结果的状态。
内部总线则是用于连接各个部件的信息通道。视运算器的功能与结构不同,可选电路包括多路选择器、移位器、三态缓冲门等辅助电路。
在进行定点运算器的设计过程中,如何确定各部件的功能和组织方式是关键,主要取决于以下几个方面:
指令系统:指令系统是计算机系统软硬件的交界面,它即是硬件设计者的直接依据,也提供了软件设计者的最基本的程序设计语言。因此,指令系统的功能设置是运算器设计必须首要考虑的因素。
机器字长:计算机的机器字长通常是指运算器一次能够并行处理的数据位数,计算机的其他部件也均按照机器字长来设计。
机器数及其运算原理:计算机采用何种机器数来表示数据,而在运算时又采用何种算法来实现,这些都直接关系到运算器的设计方法。
体系结构:根据计算机对速度、价格、性能等各方面的要求不同,计算机选择不同的体系结构。具体到 CPU内部,表现为内部总线结构:CPU(包括运算器)内部各部件
的组织,可以采用非总线结构连接,也可以采用总线结构连接,而总线结构又可以分为单总线、双总线、三总线等几种。
单总线结构
单总线结构的运算器需要两个暂存器,根据暂存器设计的位置不同而有两种形式。
IB 是内部总线,两个暂存器 LA、LB 分别位于 ALU的两个输入数据端,LA、LB 从总线上接收数据,ALU 运算功能由一组控制信号 C_OP 控制,运算的结果通过一个缓冲器送上总线。GR 是通用寄存器堆,包含若干个寄存器 Ri,它们直接挂在总线上,但是寄存器的数据输入一般由边沿信号(打入脉冲)控制,而数据输出一般由电平信号(输出使能)控制。注意,任何要把数据送上总线的总线源部件,其数据输出端必须以三态输出的形式与总线连接,并由使能信号控制;而对于某个总线系统来说,各个总线源部件的数据输出使能信号不能同时有效,即任何时刻只能允许一个部件将数据送上总线,以保证分时享用总线。
在该结构上完成(Ri)θ (Rj)→Rk的操作需要三步(三个 CPU 周期):
(Ri)→LA;通过发送信号 Ri→IB、IB→LA 来实现。
(Rj)→LB;通过发送信号 Ri→IB、IB→LB来实现。
ALU运算,结果→Rk;通过发送信号 C_OP(θ )、 ALU→IB、IB→Ri来实现。
一个暂存器 LA 位于 ALU的一个输入数据端,另一个暂存器 LC 位于ALU 的输出端与总线之间, ALU 的另一个输入端直接从总线上接收数据。在此结构上完成(Ri)θ (Rj)→Rk的操作,也需要三步:
(Ri)→LA;通过发送信号 Ri→IB、IB→LA 来实现。
(Rj)→IB,ALU运算,结果→LC;通过发送信号 Ri→IB、C_OP(θ )、 ALU→LC 来实现。
(LC)→Rk;通过发送信号 LC→IB、IB→Ri来实现。
双总线结构
双线结构的运算器只需要一个暂存器,根据暂存器设计的位置不同而有两种形式。
在(a)的运算器结构上完成(Ri)θ (Rj)→Rk 的操作,需要两步:
(Ri)→IB1, (Rj)→IB2,ALU 运算,结果→LC;通过发送信号 Ri→IB1、Rj→IB2、
C_OP(θ )、 ALU→LC 来实现。
(LC)→Rk;通过发送信号 LC→IB1、IB1→Ri来实现。
在图(b)的运算器结构上完成(Ri)θ (Rj)→Rk的操作,需要两步:
(Ri)→LA;通过发送信号 Ri→IB1、IB1→LA 来实现。
(Rj)→IB2,ALU 运算,IB1→Rk ;通过发送信号 Ri→IB2、C_OP(θ )、 IB1→Ri来实现。
显然,要在两步中完成上述运算操作,两种结构中的寄存器堆都必须是双端口的寄存器,即同时能对两个寄存器进行读写访问。
三总线结构
三总线结构的运算器不需要暂存器,ALU的两个输入端分别从两条总线 IB1、IB2 上接收数据,而运算结果直接送上第三条总线 IB3。在总线 2 和总线 3 直间设置了一个连通器,叫总线旁路器。在完成非运算操作(譬如执行 MOV 指令)时,它很方便地实现在部件之间传送数据。同理,三总线结构中的寄存器堆必须是三端口的,即同时能对三个寄存器进行读写访问。并且可将某一寄存器的内容读出送入总线 IB1 和 IB2,也可在同一时刻将数据写入该寄存器(有门延时时
间)。
完成(Ri)θ (Rj)的操作,三总线运算器需要
一步即可:(Ri)→IB1,(Rj)→IB2,ALU 运算,IB3→Rk ;需要发送信号 Ri→IB1、Rj→IB2、C_OP
(θ )、IB3→Ri。
综上所述,很明显,三种总线结构的运算器的速度在逐步提高,但是硬件复杂使得成本提高了。
三端口寄存器
支持同时对两个寄存器读,一个寄存器写的操作,分别称为A端口、B端口和写端口。
W_a1,W_a2选择写选择端口寄存器的编号,Ra_a1,Ra_a0是执行读操作的A端口编号Rb_a1,Rb_a0是执行读操作的B端口寄存器的编号。将四个寄存器的内容分别送到两个四选一的多路通道。
A端口和B端口的读操作是电平控制,只要给出寄存器地址,就能随时读出相应寄存器的内容,
写操作需要与同步时钟同步,写地址选中的寄存器才有clk,将写数据写入选中的寄存器。
标志寄存器用来保存 ALU操作结果的某些状态,这种状态可作为外界对操作结果进行分析的一个依据,也可以用于判断程序是否要转移的条件,该寄存器通常也称为状态寄存器。依据功上的差别,不同的 CPU,其标志寄存器中包含的标志也不尽相同。一般标志寄存器中包含了最基本的 5 种运算结果标志:
ZF 结果为零标志(zero flag bit):记录运算结果是否为零的状态,运算结果为 0(全零)时 ZF 置 1,否则 ZF 置 0。
CF 进位/借位标志位(carry flag bit):记录最高位产生的进位 C,加法运算时 C=1 则CF 置 1(表示有进位),否则置 0;减法运算时 C=0 则 CF 置 1(表示不够减,有借位),否则置 0。CF 标志只对无符号数运算有意义。
OF 溢出标志(overflow flag bit) :用于反映有符号数加减运算所得结果是否溢出。此时 OF 标志位为 1,否则置 0。CF 标志只对有带符号数运算有意义。
SF 符号标志(sign flag bit):记录运算结果的符号,它与运算结果的最高位相同。在现代微机中,有符号数采用补码表示法,所以,SF 也就反映运算结果的正负号。运算结果为正数时,SF 置为 0,否则其值为 1。
PF 奇偶标志(parity flag bit),用于反映运算结果中“1”的个数的奇偶性,当结果操作数中“1”的个数为偶数时置 1,否则置 0。
每条指令执行完成后,是否要修改标志寄存器各个标志的值,取决于硬件设计者对指令功能的设计与控制。在 CPU 的指令系统中,通常传送类指令不影响各标志位,即不修改标志寄存器各位的值。而运算类指令的执行一般会影响标志位,但是不同的运算指令影响的标志位会有不同。对于逻辑类指令则在执行后将清零 CF、OF 标志,修改 ZF、SF、PF 标志。
对于浮点数运算,要求参加运算的数据必须是规格化的,运算的结果也必须是规格化的。
两个浮点数,进行加减运算的手工笔算过程,按照科学记数法的一般运算原则,则必须保证它们的指数是相同的,然后对有效数位做加减运算。
数据存储和计算都要受到计算机物理部件的处理位数的限制,超出部分全部丢失。因此,计算机中对齐小数点时,要使得阶码(指数)小的那个数变得与阶码大的那个数的阶码相等;然后对尾数(有效数位)做加减运算。
假设两个浮点数 X 和 Y,它们的值为:X=Mx×2Ex,Y=MY×2Ey,则对 X 和 Y 做加减运算的和或者差 Z 为:
Z=X±Y=(Mx×2(Ex-Ey)+MY)×2Ey。
所以,浮点数的加减运算必须经过以下五个步骤。
0 操作数检查
由于浮点加减运算的过程比较复杂,因此若能判断两个操作数之中有一个为 0,则可以直接得出结果,而无需进行运算,从而节省了时间。
对阶
在计算机中,将参加浮点加减运算的两个操作数的阶码变为相等的过程,称为对阶。对阶的实质是对齐小数点的位置。首先比较两个操作数X和Y的阶码EX和EY是否相等,即求阶差Δ E=EX-EY,若 Δ E=0,则 EX=EY,无需下面的对阶操作;若Δ E≠0,则 EX≠EY,要进行对阶操作:右移小阶的操作数的尾数,并且阶码增量,直到两阶相等。若Δ E>0,则 EX>EY,MY每右移一位,EY+1,直至 EY=EX。若Δ E<0,则 EX
对阶的原则是小阶对向大阶。小阶对大阶时,右移小阶的尾数舍去的是尾数的低位,而大阶对小阶时,必须左移大阶的尾数,舍去的是尾数的高位。
尾数相加减
当操作数的阶码相同时,尾数可以直接进行加减运算。
结果规格化 方法有 3 种:截断法、0 舍 1 入法、末位恒置 1 法等。截断法实际上没有舍入,只是简单的将多余的位数全部舍去;末位恒置 1 法则不管多余位的值为多少,始终在舍入的结果的最末位置 1;它舍入的结果相比精确结果时大时小。0 舍 1 入法类似于十进制的四舍五入,当多余位的最高位为 1 时,在尾数最低位上加 1,否则,直接舍去多余位。
IEEE 754 标准规定了 4 种可选的舍入模式:
向上舍入(总是朝+∞):为正数时,只要多余位不全为 0,就向最低有效位进 1;为负数时,则采用简单的截断法。
向下舍入(总是朝-∞):为正数时,只要多余位不全为 0,就简单地截尾;为负数时,则向最低有效位进 1。
向 0 舍入:即朝数轴的原点方向舍入,就是无论正数还是负数,都采用简单的截尾,从而使得绝对值总是变小。这种方法容易累积误差。
就近舍入:即舍入到最接近的数,就是通常的“四舍五入”。当多余位的值超出它们量程(即最低有效位的权值)的一半,则向最低有效位进 1;当小于一半,则截尾(即
舍去);当等于一半(中点),则若最低有效位为 0(偶数)就截尾,若最低有效位为 1(奇数)就进 1,以使得最低有效位总是为 0。在中点的这种舍入方法很公平:一半的
时间里向上舍入,在另一半的时间里向下舍入,它也不容易累积误差,所以被广泛使用。
为实现 4 种舍入方法,IEEE 754 标准规定,所有浮点运算的中间结果右边都必须额外多保留 2 位:保护位(guard) 、舍入位(round),它们用于实现精确的四舍五入。另外,还设置 1 位粘滞位(sticky),用于记住是否有 1 被(右)移出。只要舍入位的右边有非零位,粘滞位就置为1。
假设两个浮点数 X 和 Y,它们的值为X=Mx×2Ex,Y=MY×2Ey,则浮点数除法运算法则为: Z=X÷Y=(Mx÷MY)×2(Ex-Ey)。
0 操作数检查
当除数为 0,则报告除法出错,或者结果(商)无穷大;当被除数为 0,则商为 0。
阶码相减
同乘法类似,阶码相减的结果也可能溢出,若发生正溢出,则需报告浮点数溢出,若发生负溢出,则将结果置为机器零。
尾数相除
尾数相除可以选择任何一种定点机器数(小数)的除法算法来实现。
结果规格化
当|MX|≥|MY|时,尾数相除得到的商包含整数位,即结果溢出,因此,除法结束后,必须判断商是否规格化,若是非规格化,则右规一位即可。
舍入处理
需要注意的是,尾数相除并没有像定点小数除法那样要求|MX|≤|MY|,因此,需要规格化操作。但是,有时商无法保存溢出的整数位(譬如补码除法),所以为防止商溢出,可以在尾数相除时进行尾数调整,比较|MX|与|MY|,若|MX|≥|MY|,则将|MX|右移一位,EX加 1,这样得到的商一定是规格化的,无需规格化。
由于浮点运算复杂程度远远大于定点运算,因此,计算机根据性能要求和需要来确定是否设置浮点运算器。在没有浮点运算器的机器中,基于一定的定点运算部件,可以按照上述浮点运算的算法用软件来实现,显然,这种方法速度较慢。而设置浮点运算器的机器中,它的功能和设计方法也有很大的差别。
由浮点运算算法可知,浮点运算器由两个松散连接的定点运算部件组成:阶码运算部件和尾数运算部件。阶码运算部件要求具有加减运算和+1、-1 的功能,而尾数运算部件要求具有加减乘除四则运算和移位的功能。
左边的 EU是阶码运算部件,右边的 MU 是尾数运算部件,它们分别包含三个寄存器,用以保存参加运算的两个操作数和运算结果的阶码和尾数。
在数据送入浮点运算部件前,通过 0操作数检查部件首先测试有否 0 操作数,没有时才进入浮点运算部件运算。
当进行加减运算时,两个操作数的阶码 EX、EY送入阶码运算部件中的 ALU 做减法,求出的阶差存放于 EZ,根据 EZ的符号 Ef来控制将大阶送入 EZ寄存器,此时,使用 E_ALU的“ F=A”和“F=B”功能来实现。同时,尾数也根据 EZ 的符号 Ef来决定将小阶的尾数送入 MZ 寄存器进行右移,对阶后的尾数再送回原寄存器。接着尾数部件的 ALU做加减法,结果存入 MZ寄存器,通过规格化检查部件测试是否规格化,输出 “左规”或者“右规”控制信号,用于控制 MZ 寄存器左移或者右移,控制 EZ寄存器减 1 或者加 1,直至规格化。
乘除运算相对简单,首先控制阶码部件的 ALU进行加减,结果置入 EZ寄存器。再通过尾数部件的 ALU 进行乘除运算,结果置入 MZ寄存器,然后同加减运算类似,进行规格化处理。
浮点协处理器 80387 的主要性能如下:
算术协处理器 80387 的内部结构,可分为两个主要部分:控制单元和数字执行单元。
控制单元(Control Unit,CU)将协处理器连接到微处理器系统数据总线上。微处理器和协处理器均监视指令流,如果为 ESC(协处理器)指令,则由协处理器予以执行,否则由微处理器执行。
数字执行单元(Numeric Execution unit,NEU)负责执行所有协处理器指令。NEU中有一个由 8 个 80 位寄存器构成的堆栈,用于存储算术指令的操作数和结果。指令可以通过直接指定来寻址堆栈数据寄存器以获取数据,也可以使用压入和弹出机制在栈顶存储和取回数据。NEU 中还包含状态寄存器、控制寄存器、标记寄存器和异常指针寄存器。很少有指令在协处理器和微处理器的 AX 寄存器之间传输数据,FSTSWAX 指令是协处理器允许通过 AX 寄存器和微处理器直接通信的唯一指令。注意 8087 中不包含 FSTSWAX 指令,但所有新协处理器都包含该指令。
寄存器堆栈
协处理器包含 8 个寄存器,每个为 80 位宽,它们首尾相接,组成一个“先进后出”的寄存器堆栈。这些堆栈寄存器中总是包含一个 80 位的扩展精度浮点数。数据只有驻留在内存时才可能是任何其他格式。当数据从内存中移到协处理器的寄存器堆栈中时,协处理器将这些带符号的整数、BCD 数、单精度或双精度数转换为扩展精度浮点数。8 个寄存器编号为 0-7,处于栈顶的寄存器称为栈顶寄存器,它的编号由状态寄存器的 TOP字段指出。在协处理器指令中,用 ST 表示栈顶寄存器,用 ST(i)( i=1~7)访问相对于栈顶寄存器偏移量为 i 的寄存器,即 i 是偏移量,而不是寄存器实际的编号。
状态寄存器
状态寄存器反映协处理器所有指令的运行情况。状态位 6(SF)只在 80187 以上的更高型号中使用,用来指示堆栈上溢或下溢错误。 B 忙位(busy bit)表明协处理器正忙于执行一项任务,通过检测状态寄存器或者使用 FWAIT 指令均可测试忙位。由于较新的协处理器自动与微处理器同步,所以在执行其他协处理器任务之前不必测试忙标志。
C3~C0 条件码位(condition code bit),表明了协处理器的条件。注意,这些位对于不同的指令有不同的含义。
TOP 栈顶(top-of-stack,ST)位表示当前寻址为栈顶的寄存器,通常是寄存器 ST(0) 。
ES 错误汇总(error summary)位,当任何一个非屏蔽的错误位(PE、UE、OE、ZE、DE 或 IE)被置位时,则 ES 被置位。在 8087 协处理器中该位也可引起协处理器中断。但从 80187 开始,不再有协处理器中断。
SF 堆栈标志(stack flag)位用于区分堆栈上溢和下溢的非法操作。当该位被置 1 时,再根据标志位 B9(C1)来区分上溢和下溢两种情况。
PE 精度错误(precision error)表明结果或操作数超过了设定的精度范围。
UE 下溢错误(underflow error)表明一个非 0 的结果太小,以致于不能用由控制字选择的当前精度来表示。
OE 上溢错误(overflow error)表明结果太大而不能被表示出来,如果此错误被屏蔽,则协处理器对上溢错误就会产生一个无穷大。
ZE 被零除错误(zero error)表明当被除数是非无穷大和非零时,除数是零。
DE 非规格化操作数错误(denormalized error)表明至少有一个操作数是非规格化的。
IE 非法操作错误(Invalid error)表明堆栈有上溢或下溢错误,是不确定的形式(0
÷0、+ 和-等),或者使用了 NAN 作为操作数。此标志表明诸如对负数开平方等类似
的错误。
执行 FSTSW 指令就可以访问状态寄存器,此指令将状态寄存器中的内容存入内存的一个字单元中。在 80187 或 80187 以上的协处理器中,FSTSW AX 指令可将状态寄存器中的内容直接复制到微处理器的 AX 寄存器中。一旦状态寄存器的状态被存储到内存或 AX 寄存器中,则可以使用常规软件检测状态寄存器中的各位,譬如使用以下两种方法测试状态寄存器的各位。一种方法是使用 TEST 指令来测试状态寄存器的各位,另一种方法是使用 SAHF 指令将状态寄存器中最左边的 8 位传送到微处理器的标志寄存器中。
协处理器和微处理器之间的通信在 80187和 80287中是通过 I/O端口 00FAH~00FFH实现的,而在 80387~Pentium4 中是通过 I/O 端口 800000FAH~800000FFH实现的。注意,不要使用这些 I/O 端口来连接其他 I/O 设备到微处理器。
控制寄存器
控制寄存器包括精度控制、舍入控制和无穷大控制,它也可以屏蔽或者不屏蔽与状态寄存器最右边 6 位对应的异常位。FLDCW 指令用于给控制寄存器赋值。
IC 无穷大控制(infinity control),选择是仿射无穷大还是投射无穷大。仿射允许正无穷大和负无穷大,而投射则假定无穷大为无符号的数。
Exception Masks 异常屏蔽字段,决定异常错误是否影响状态寄存器的错误位。如果其中一个异常控制位被置为逻辑 1,则相应的状态寄存器位被屏蔽(即不影响)。
标记寄存器
标记寄存器(tag register)表明协处理器堆栈中每个寄存器内容的状态特征,因此又叫特征寄存器。标记寄存器用每 2 位表示寄存器堆栈中 1 个寄存器的状态,即 TAG(i)表示堆栈寄存器 ST(i)的状态。TAG(i)特征值为 00~11 四种组合时分别表明相应的寄存器有正确数据、数据为 0、数据非法、无数据 4 种情况。
通过程序查看标记寄存器的唯一方法是使用 FSTENV、FSAVE 或 FRSTOR 指令来存储协处理器操作环境。其中每条指令均可将标记寄存器与其他协处理器数据一起存储。
为了实现流水,首先必须把输入的任务分割为一系列的子任务,使各子任务能在流水线的各个阶段并发地执行。将任务连续不断地输入流水线,从而实现了子任务的并行。因此流水处理大幅度地改善了计算机的系统性能,是在计算机上实现时间并行性的一种非常经济的方法。
由于计算机的浮点运算较为复杂,时间开销巨大,因此流水线技术在浮点运算器中也得到广泛应用。例如,将浮点数加减法运算过程划分为四个步骤,每个步骤作为一个子任务,由专用部件实现各自的任务,处理结果送入下一步骤的功能部件。这样,在同一时刻,该浮点加减运算流水线就可以同时处理 4 组浮点数加减的运算请求。
Pentium CPU内部包含了一个 8 段的流水浮点运算器,Pentium 浮点流水线由预取 PF、首次译码 D1、二次译码 D2、取操作数 EX、首次执行 X1、二次执行 X2、浮点寄存器写入 WF 和出错报告 ER共 8 个操作步骤组成。其中预取 PF 和首次译码 Dl 这两个操作步骤与整数流水线中的前两个操作步骤公用整数部件中的同一硬件资源。而浮点流水线中的第三个步骤开始激活浮点指令的执行逻辑,其实浮点流水线中的前 5 个操作步骤与整数流水线(U或 V)的 5 个步骤是同步执行的。
一般只能由 U 流水线完成一条浮点数操作指令,流水线 U 执行浮点指令时增加了执行级 X2,浮点寄存器写入级 WF 和出错级 ER这 3 级流水线,它们均由浮点部件来完成。
Pentium 微处理器的浮点流水线由浮点接口、寄存器组及控制部件 FIRC、浮点指数功能部件 FEXP、浮点乘法部件 FMUL、浮点加法部件 FADD、浮点除法部件 FDIV 以及浮点舍入处理部件 PFRND 共 7 个部件组成。
虽然 Pentium 浮点流水线设置了 8 个操作步骤,但是对于浮点的取数、加减法、乘法和比较等“基本”操作,采用了新的算法并用硬件来实现,其执行速度是 80486 的 10 倍多,允许单周期通过,即能以每个时钟执行一条浮点指令的速度来执行。 传统的 80X87 浮点部件不仅可支持 IEEE754 标准的 32 位单精度和 64 位双精度格式的浮点数,还支持 80 位的扩展精度浮点数运算。而在 Pentium 浮点部件内又配置了直接支持 3 倍精度浮点计算的部件,虽然添加了一些硬件器件,但极大地简化了微体系结构,并明显地改进了浮点部件的性能。
基于 NetBurst 微架构的 Pentium4 实现了被称作为流 SIMD 扩展 2(SSE2)的 144 条新 SIMD指令,这些新指令支持 128 位的 SIMD 整数操作和 128 位 SIMD 双精度浮点操作。而在 Core 构架微处理器中,对浮点部件进行了不小的改进:Core 构架拥有 2 个浮点执行单元同时处理向量和标量的浮点运算,其中一个浮点单元负责加减等简单的处理,而另一个浮点单元则负责乘除等运算。尽管不能说 Core 构架令浮点性能有很大幅度的提升,但是其改进效果还是显而易见的。