带标志加法器结构

零标志ZF

零标志是根据每一位加法器的计算结果

F

i

F_i

Fi​相或得到的,所以只有在结果的每一位都为0的时候所有位相或才能得到0的输出,但是或门上有取反符号,所以在ZF标志的输出为1时代表结果全零,反之不全为0.

溢出标志OF

注意OF是判断带符号数是否溢出的,对于无符号数OF不能用作溢出的判断,因为如果两个高位为0的数相加,得到的结果高位为1,明显对于无符号数这种情况是可以成立的,但是对于带符号数,证明其得到的结果是负数,由两个正数做和还得到了一个负数结果明显是溢出。所以在OF为溢出的情况下,对于无符号数是不能由此就判断无符号数的结果是否溢出的。

由上面的加法器结构可以看到,判断溢出没有可以通过最高位的

C

o

u

t

(

C

n

)

C_{out}(C_n)

Cout​(Cn​)和

C

n

1

C_{n-1}

Cn−1​求异或得到。下面是所有的输入输出情况可见,最高位的

C

o

u

t

(

C

n

)

C_{out}(C_n)

Cout​(Cn​)与

C

n

1

C_{n-1}

Cn−1​与OF之间是满足异或关系的。

符号标志SF

表示带符号整数加减运算结果的符号位,因此直接取结果的最高位作为SF。

进/借位标志CF

之前说的判断带符号数的溢出标志是OF,那么现在判断无符号数的溢出标志就是CF,同样CF只能判断无符号数是否溢出(溢出为1,反之为0),而不能判断带符号数的溢出情况。

其实这四个标志里CF是最令我费解的。由结构图可知

C

F

=

C

o

u

t

(

C

n

)

C

i

n

CF=C_{out}(C_n)\ \oplus\ C_{in}

CF=Cout​(Cn​) ⊕ Cin​求得。进位是很好理解的,进位一般是对于加法而言,而

C

i

n

C_{in}

Cin​是输入加减符号的对应,所以这时候

C

i

n

=

0

C_{in} = 0

Cin​=0,那么当

C

o

u

t

(

C

n

)

=

1

C_{out}(C_n) = 1

Cout​(Cn​)=1时

C

F

=

1

CF=1

CF=1表示有溢出。因为最高位处都还要向前面进位,而得到的结果会舍去最高位前面的所有值,所以自然发生了溢出。但是对于借位,我觉得真的很难理解,借位是对于减法而言的,如果在减法里还想要结果不溢出那么最高位必须让

C

o

u

t

=

1

C_{out}=1

Cout​=1才可以。对于这一点想了很久终于明白了:

我们首先以四位的数为例子,有真值为

a

,

b

a, b

a,b的两个四位无符号数。他们的机器数,也就是补码表示为

A

,

B

A,B

A,B,对于

a

b

a-b

a−b的计算可以写成

a

b

=

a

+

[

b

]

=

A

+

[

b

]

a-b=a+[-b]_{补}=A+[-b]_{补}

a−b=a+[−b]补​=A+[−b]补​而对于这个

[

b

]

[-b]_补

[−b]补​,可以通过对

b

b

b的补码各位取反,末位加一得到这个过程写出来是这样的:

1111

B

+

1

=

10000

B

1111-B+1=10000-B

1111−B+1=10000−B 那么对于

a

b

a-b

a−b可以表示成:

A

B

+

10000

A-B+10000

A−B+10000 那么对于无符号数而言做减时得到为正数的结果自然是没有发生溢出的,但是如果得到的结果为负数,那么必然发生溢出,而上面的式子很容易看到,经过这样的求值过程如果说A-B是正数,那么必然会因为

+

10000

+10000

+10000而发生进位,如果A-B的值不够为正数,那么A必然会向

+

10000

+10000

+10000借位,那么就必然不会产生进位。

综上,

C

F

CF

CF的由来就是如此。