哈哈,你提到溢出,让我想到CF、OF标志位,进一步发现自己一个错误:
求反码和补码,都不会影响符号位(反码计算,不会取反符号位,补码计算,会丢弃次高位的进位),所以帖子中对0和-128反码和补码的描述,是错误的!8位二进制,能表示的原码和反码范围,都为-127~127,表示不了-128!0的反码和补码,也不是帖子中那样算的!
那么,-128没有8位二进制的原码和反码,为什么却有补码(10000000)呢?而且,按照"取反+1"的计算过程,10000000也应该是-0的补码才对啊(10000000->11111111->10000000) ?
答:对于人类的大脑来说,-0、+0都为0,所以没必要占用2个补码,统一用+0的补码00000000即可(00000000->01111111->00000000),同时,想象一个128刻度的圆盘,由于向反方向转一圈(-128),和留在原地不动(-0),效果是一样的,所以就将10000000作为-128的补码。
但是,CPU怎么会想这么多呢,它只会麻木无情进行0和1相加操作,所以怎么让它区分补码10000000,代表-0,还是-128呢?这很重要的,10-0等于10,10-128可就是-118了啊。
答:以0刻度为基准,10(补码:00001010)和-118(补码:10001010),对应相同的刻度,但是,00001010+00000000得到的就是00001010,而00001010+10000000得到的就是10001010,相应也就很容易理解,单纯从位置上考虑,补码10000000对应0和-128,甚至还有+128、-256等等,但由于符号位和数值位共同的约束,决定了它只能是-128。
不过以上分析也更加说明,通过刚正面的方式去想补码的由来,很容易犯糊涂,而顺着补码设计的目的去想,就会很容易:对于M和它的反码N,由于它们每一位都相反,所以M+N的每一位就都为1,再加1,就会溢出得到0,从而将(反码+1)作为补码,就这么简单。更准确的说,补码是为了让+M与-M的数值位相加等于0,这也是计算补码,不影响符号位的原因。
理解了补码,CF、OF也会相应好理解一些了,无符号数相加是否溢出,通过CF判断,有符号数相加是否溢出,通过OF判断,以及CF、OF为什么要这样算:
CF = 最高位是否进位(进位1,否则0)
OF = 次高位是否进位(进位1,否则0) ^ CF标志位
现在大家都在呐喊学以致用,我觉得学以致用也分长线和短线吧,有些东西虽然不是直接拿来用的,但它可以保证使用相关东西的时候,不犯糊涂,熬过一个阶段后,应该会比只停留在表面,轻松一些吧
。