Module 0260: Signed integer representation

Tak Auyeung, Ph.D.

January 30, 2017

1 About this module

2 Signed integers

Signed integers represent values that are non-negative (including zero) and those that are negative, such as 1. In our normal notation, the unary minus operator () is used to denote negative. In a system where everything is 0 or 1, however, there is no sign to indicate whether a numbe is negative or not.

There are alternatives to use 0 and 1 to represent the sign of a value. For example, we can allocate a single bit so that if this bit is 1, the number is negative, if this bit is 0, the number is non-negative. However, such a method renders the adder and subtractor logic useless.

In order to be able to better utilize transistors in a processor, we need a representation of negative integer values so that the logic gate implementation of the adder and subtractor can be used regardless of whether a value of a representation is signed or not.

3 Back to subtractors

Let us consider combinations of four bits. There are only 24 = 16 of them. If we only need to represent non-negative values, we can use all 16 combinations, from 00002 to 11112 to represent the integers from 0 to 15.

If we need to represent integer values that are both negative and non-negative, however, we will need to assign negative values to some of the these bit patterns. The only question is how to do this assignment. The objective to reuse the adder and subtractor logic helps us choose the assignment.

What we need to do is to consider the bit pattern of 00002 00012. Because 00002 represents zero (this one is obvious!), and 00012 represents 1, it makes sense that we can choose the result of 00002 00012 = 11112 to represent the value of 1. The same applies to 00002 00102 = 11102 to represent 2 and so on.

In fact, it makes sense to use 00002 wxyz2 to represent the arithmetic negation of the value represented by wxyz2 (where each letter represents a bit). For notation purposes, we use v to denote the value represented by the bit pattern wxyz2.

4 Twos’ complement

How do we perform 00002 wxyz2? Well, the same way as do we any binary subtraction! Due to the first number being zero (00002), however, we have some quick tricks to get this done.

Because we are only interested in the least significant four bits of the subtraction, 00002 wxyz2 and 100002 wxyz2 would yield exactly the same result as far as the least significant four bits are concerned. The only difference is whether there is a leftover borrow from bit 4.

100002 is 11112 + 00012. So now we have the following:

0 v = 00002 wxyz2 (in binary) = 100002 wxyz2 (becausewe only need four bits) = (11112 + 00012) wxyz2 (expand) = 11112 wxyz2 + 00012 (associative law applied) = (11112 wxyz2) + 00012

As it turns out, 11112 wxyz2 is a special subtraction, as well. Because we are always subtracting a zero or a one (represented by w to z) from a constant of 1, this is the same as boolean negation. In short, 1 w = w¯, 1 x = x¯ and so on. The boolean negation is applied to each bit of wxyz2. In C/C++, this is represented by the bit-wise not operator (~).

Now we can finish our equation:

0 v = (11112 wxyz2) + 00012 (from the previous derivation) = v + 00012 (bitwise not in place of binary subtraction) = v + 1 (one is the same regardless of base)

Of course, this rather weird way of looking at arithmetic negation is only applicable when we limit our view to a fixed number of bits. In our examples, the width of operations is 4-bit. The principle, on the other hand, applies to integers represented by any number of bits.

C2(w) = w + 1 is called two’s complement because bitwise negation is called one’s complement.

5 Range of signed values

Two’s complement does not automatically suggest the range of signed values to be represented by n bits. All it says is the bitwise operation C2 is equivalent to arithmatic negation.

However, C2 can be used to help us here. Unless x = 0, xx. Because C2 is equivalent to arithmatic negation, we can also say that unless x = 0, C2(x)x.

We can plug in individual 4-bit numbers to test this requirement. C2(00002) = 00002, but that’s okay because it is zero. C2(00012) = 1111200012, the requirement is met. This works all way until we get C2(10002) = 10002! This means we have hit a limit due to the limited number of bits (4 in this case).

Then the question is what should the bit pattern 10002 represent? We have to choices, it can be 8 or 8. The correct choice is 10002 = 8 as a signed number.

The superficial reason is that we already have 0 as a non-negative number, so the range of non-negative values only go from 0 to 7 for 8 of them. As a result, the negative values go from -1 to -8 also to have 8 of them.

The more rigorous reason is that we treat the most significant bit as the “sign” bit. All the negative values are represented by bit patterns with the most significant bit being a one. Given numbers are represented in n-bit patterns, bit n 1 is the sign bit.

In general, given n bits, the range of integer values is from 2n1 to 2n1 1.

6 Comparing unsigned values

A comparison is, essentially, a subtraction where the difference is not important. Assuming bit patterns represent unsigned values, the borrow flag can be used to indicate ordering of values.

Assume that a binary subtractor performs the n-bit subtration x y. The borrow of bit n is 1 iff x < y. This makes sense because a borrow of one is triggered only if a subtraction tries to subtract more than there is available.

Can we actually prove that “a subtraction borrows from bit n only if the bit 0 to bit n 1 of the minuend is less than bit 0 to bit n 1 of the subtrahend?”

As a matter of fact, we can! Again, the proof itself is CISP440 material, but included here for the curious and those desire rigorous mathematical proofs!

This is done by proof-by-induction. Let us use x to denote the minuend, y to denote the subtrahend. xi is bit i of x, and yi is bit i of y. We also we the notation x[i : 0] to specify the bit pattern from bit 0 to bit i of x.

The base case is when we subtract a 1-bit number from a 1-bit number. According to the B(x,y) function, we only borrow from bit 1 iff we have 0 1 for bit 0, and 0 < 1.

For the induction step, we assume the theorem is true up to an n-bit subtraction. In other words, we assume that we borrow one from bit n only if x[n 1 : 0] < y[n 1 : 0]. Furthermore, let b be the borrow bits where bi is the borrow from bit i.

Now we are ready to perform the last step. From the structure of a subtraction, the borrow from bit n + 1 is as follows:

bn+1 = B(xn,yn) + B(R(xn,yn),bn) (by structure of subtractor) = (xn¯yn) + B((xn¯yn) + (xnyn¯),bn) = (xn¯yn) + ((xn¯yn) + (xnyn¯))¯bn = (xn¯yn) + ((xn¯yn)¯ (xnyn¯)¯)bn = (xn¯yn) + ((xn + yn¯) (xn¯ + yn))bn = (xn¯yn) + ((xnxn¯ + xnyn + yn¯xn¯ + yn¯yn))bn = (xn¯yn) + ((xnyn + xn¯yn¯))bn = (xn¯yn) + ((xnyn + xn¯yn¯))bn = xn¯yn + (xn¯ + yn)bn

We have seen this derivation from a previous module, but the significance is different here.

In order for bn+1 to be a one, xn¯yn can be true. But this means xn = 0 yn = 1, which also means x[n : 0] < y[n : 0].

If xn¯yn is not true, then (xn¯ + yn)bn has to be true if bn+1 is true. Let’s see what this means.

(xn¯ + yn) is true iff xn = yn because we already know at this point xn¯yn is false. A true table can be used to illustrate this. We will also need bn to be true. Our induction assumption says that bn = 1 iff x[n 1 : 0] < y[n 1 : 0].

Because we also know that xn = yn, we can now conclude that x[n : 0] < y[n : 0]. This concludes the proof by induction.

The bottom line is that bi = 1 iff x[i 1 : 0] < y[i 1 : 0].

7 Comparing signed values

It is a little more difficult to figure out the ordering of signed values represented in binary. Intuitively, if x < y, then x y < 0, and so the sign bit of the result (difference) should be set.

This is true in some cases. For example, 1 < 1. In four-bit signed representations, 11112 = 1 and 00012 = 1. The subtraction yields, 11112 00012 = 11102, and the sign bit is set.

However, in some other cases, the sign flag is not set when “it is supposed to.” Let us take a look at this comparison: 4 < 5. In four-bit signed representations, 11002 = 4, 01012 = 5. 11002 01012 = 01112, the sign bit of the result is not a one!

This can be explained by 4 5 = 9, and that is less than the most negative value that can be represented in four bits. In other words, we have an “overflow” situation. Because 9 cannot be represented by four bits, it “wraps” around to the representation of 7.

Let us use the notation that x is the minuend, y is the subtrahend, d is the difference, and subscripts indicate bit position. Assume all values are in n bit representation. Then the overflow flag (it is a one iff a the result of a subtraction exceeds the limits of representations of signed integers) is defined as O = xn1yn1¯dn1¯ + xn1¯yn1dn1.

This means we have an overflow condition whenever the sign of subtrahend and difference are the same, and it is opposite to the sign of the minuend. This makes sense because it means (ve) (+ve) = (+ve) or (+ve) (ve) = (ve)

Although the sign flag of the difference S = dn1 alone is not sufficient to indicate ordering of signed values represented in binary, together the flags S O can. We can define a new flag L = S¯O + SO¯ to indicate the minuend is less than the subtrahend.

One way to interpret the definition of L is that when O = 1, it means “the proper S flag should be the opposite”. After a subtraction of signed values represented in binary, we want either “the S flag is set and it is proper” or “the S flag is cleared, but should have been the opposite!”