In the TC-201 we have 16 bits to represent an integer. There are 216 = 65536 possible patterns of 16 bits, so we could represent that many different integers. If we needed only non-negative integers, a natural choice would be "unsigned binary", which would just be the 16-bit binary representations of the numbers 0 through 65,535 as the patterns 0000000000000000 through 1111111111111111, respectively.
However, we'd like to represent a range of positive and negative integers, but the number of integers from -n to n is 2n+1, an odd number. As a result, the number representations we'll consider each have an "anomaly" because the number of patterns is even. The three systems we consider are: sign/magnitude, one's complement, and two's complement. For illustration, we'll consider the systems using just 4 bits (instead of 16) -- the principles apply to any number of bits, for example, the more common 32 or 64 bits of modern computers. With 4 bits we have 24 = 16 possible bit patterns. Here is what they represent, in unsigned binary and in each of the three systems we consider.
bit pattern unsigned binary sign/magnitude one's complement two's complement
----------- --------------- -------------- ---------------- ----------------
0000 0 0 0 0
0001 1 1 1 1
0010 2 2 2 2
0011 3 3 3 3
0100 4 4 4 4
0101 5 5 5 5
0110 6 6 6 6
0111 7 7 7 7
1000 8 -0* -7 -8*
1001 9 -1 -6 -7
1010 10 -2 -5 -6
1011 11 -3 -4 -5
1100 12 -4 -3 -4
1101 13 -5 -2 -3
1110 14 -6 -1 -2
1111 15 -7 -0* -1
(The asterisk (*) indicates the "anomaly" in each system we consider: a second
representation of 0 in sign/magnitude and one's complement, and
a number, -8, with no corresponding positive number in the representation,
in two's complement.)
Note that all three systems represent the numbers 0 through 7 in
the same way (except for the extra representations of 0) -- as
0 followed by the 3-bit unsigned binary representation of the
integer; this is also the unsigned binary representation of these numbers.
(In general, for b bits, the numbers 0 through 2b-1-1 are represented
as 0 followed by the (b-1)-bit unsigned binary representation of the
number.)
The three systems differ in how they represent negative numbers.
For sign/magnitude, the representation of a negative number is 1 followed by the 3-bit unsigned binary representation of the absolute value of the number. Thus, the high-order bit is a sign bit (0 for + and 1 for -), and the remaining bits give the magnitude (or absolute value) of the number. To convert a positive to a negative number, it suffices to change the high-order bit from 0 to 1, and to convert a negative to a positive number, it suffices to change the high-order bit from 1 to 0. Note that we have two representations of 0, namely 0000 and 1000, that latter being referred to as -0.
For one's complement, the negative of a number is found by complementing each bit individually (changing 0 to 1 and 1 to 0.) Thus, we represent -1 in 4-bit one's complement by complementing each bit of 0001 to get 1110. Of course, since complementation is self-inverse (the complement of the complement is the original argument), the negative of a negative number is also found by complementing each bit. In one's complement (also) the number zero has two representations: 0000 and 1111 -- the latter being referred to as -0.
The rationale for two's complement is that it implements arithmetic modulo 2b, where b is the number of bits. If we consider the integers 0 through 15 modulo 16, then we have 1+15 = 0 (modulo 16) and 5+11 = 0 (modulo 16). Thus, modulo 16, 15 "behaves like" -1, in the sense that 1 and 15 add to 0 (modulo 16), and 11 "behaves like" -5. If we consider the 4-bit unsigned representation of 15, we have 1111, which is the representation of -1 in 4-bit two's complement arithmetic, and the unsigned 4-bit representation of 11 is 1011, which is the representation of -5 in 4-bit two's complement. The number 8 is a bit anomalous modulo 16, because 8+8 = 0 (modulo 16). The representation 1000 is taken to be -8, which means that the high-order bit signifies whether the number is negative (if the bit is 1) or non-negative (if the bit is 0.) Why would two's complement be desirable? If you recall the circuit we designed to add two 4-bit numbers to get a 5-bit sum, if we just ignore the high-order bit of the result, the circuit computes the sum of its two inputs, modulo 16. Two's complement is in fact the most common choice for the representation of integers in modern computers.
The rule some have learned for negating a two's complement number is to complement each bit individually and then add 1. For example, to complement 5, we start with 0101 and complement each bit: 1010, and then add 1: 1011, which is the correct representation of -5 in two's complement. Going the other direction, from -5, we start with 1011, complement each bit: 0100, and add 1, to get 0101. Why does this work? Hint: complementing each bit is equivalent to subtracting the unsigned value of the number from 15.
In a class vote, it was decided that this term's TC-201 computer would have sign/magnitude representation of integers. We also decided that skipzero will skip on both positive zero (0000 0000 0000 0000) and "negative zero" (1000 0000 0000 000).
Next, we turn to the following task: read in a zero-terminated sequence of numbers, print them out in reverse, and then halt. A sample interaction with the user might look like the following.
input = 17
input = -13
input = 22
input = 0
output = 22
output = -13
output = 17
We start with the following idea, which is NOT a solution.
read-num: input
skipzero
jump store-num
jump produce-output
store-num: store num
jump read-num
num: data 0
The reason this doesn't work is that the first number read in
will be stored in num, and then the second number read in will
be stored in num (overwriting the first number) and then the third
number will be stored in num (overwriting the second number), and
so on.
When this jumps to the code for produce-output, only the latest
number read in will be available in num, and we won't have
the information we need to print out the reverse of the sequence
of numbers read in.
(See the next lecture for how we solve this problem.)