单片机程序状态字PSW的OV位到底是怎么判断溢出的?有CY位不就够了么
溢出,是通用的词汇。
含义,一般就是,容器太小,盛不下了。
但是,在计算机领域,却有些怪诞。
人类所用的数,有:自然数、整数。
到了搞计算机的人的嘴里,就要改称为:无符号数、带符号数。
计算机中的八位二进制机器码,所能表示的范围,如下所示:
机器码,无论代表什么数字,只要运算结果超出范围,就是【溢出】。
但是,在计算机专业人的嘴里,就不一样了。
【无符号数的溢出】,不叫溢出,要叫做【进位】。
【带符号数的溢出】,才叫做【溢出】。
搞计算机的这些人,基本概念不清,却自命不凡!
冒充脑回路清奇。。。正常人对此,就只能无语了。
----------------------
如果你让计算机计算:
1111 1110 + 1111 1101 = (1) 1111 1011
这是代表了无符号数:254 + 253 = (256) 251 = 507。
和,超出了 255,就是溢出了。 特征是【进位为 1】。
这也代表了带符号数:(-2) + (-3) = (进位舍弃) (-5)。
和,没有超出范围,没有溢出,结果正确。
----------------------
如果你让计算机计算:
0111 1110 + 0111 1101 = (0) 1111 1011
这是代表了无符号数:126 + 125 = (0) 251。
和,不超出 255,没有溢出。 特征是【进位为 0】。
这也代表了带符号数:126 + 125 = (进位舍弃) (-5)。
和,超出 +127,就溢出了,结果错误!特征是:符号不对了。
----------------------
CPU 做完运算,会给出八位结果,以及标志位。
如果你算的是无符号数,你就应该关心“进位标志 CY”。
如果你算的是带符号数,你就应该关心“溢出标志 OV”。
对于无符号数的运算,CY位就可以表示其是否溢出。但如果是有符号数,则不能按CY标志来判断了。为此,设了另一个标志OV,其含义就是“假如是有符号数运算,是否出现了溢出”。
例如对于16位运算器,65534 + 3,(即二进制的1111111111111110 + 0000000000000011),
本该得65537,(即二进制的10000000000000001),但因为寄存器只有16位,最高位的那个1丢掉了(进入了CY标志)。结果寄存器中只剩下了1,(即二进制的0000000000000001)。
此时,我们可以说,16位的无符号数加法,65534+3溢出了,溢出后的答案成了1。
但是对于有符号整数,情况就不同了。有符号整数采用补码表示法。16位有符号整数不可能表示65534,此时如果机内二进制是1111111111111110,程序中认为它是-2,故:
机内的二进制的1111111111111110 + 0000000000000011,代表的是(-2) + 3。
请注意,此时的(-2)+3和上文的无符号数65534+3,在CPU的运算器硬件上完全相同,都是得到和为1,而CY标志也为1。
但是,有符号数(-2)+3=1并无溢出。故此时的CY标志不能代表它溢出了。
另外再举一例:
无符号数32763 + 8 = 32771,没有进位,CY标志为0。此时并不溢出。
但是,如果是有符号数32763 + 8,这就是溢出了,因为32773的二进制为1000000000000011,作为有符号数会被看成负数-32765。16位有符号数不可能表示32773的。
不管是有符号数还是无符号数,CPU的二进制运算器机器加、减操作是一样的,但其“溢出”的条件不同。
现在大多数的计算机中,如果是无符号数,都可以用CY标志来判断其是否溢出;而如果是有符号数,则需要用OV标志来判断其是否溢出。
至于OV标志在逻辑上又是根据什么产生的呢?则不同的计算机上有不同的实现方法,但效果都是一样。
这里介绍一种道理比较容易懂的方法:“双符号位法”。具体是:
作加、减法前,先将两个运算数都按照有符号数的规则扩充成17位。即:符号位是0的前面添一位0,符号位是1的前面添一位1。
然后按17位的机器加、减,得出17位的结果。
如果17位结果的高两位(即双符号位)不同,就置OV标志为1,否则,OV标志为零。
然后取其低16位作为最后结果。