REPRESENTATION OF NEGATIVE NUMBERS There are three methods commonly used to represent negative numbers in binary. They are: signed magnitude, one's complement, and two's complement. We have already encountered one's complement and two's complement briefly in a previous lecture (lecture 3, SUBTRACTION). Signed magnitude uses the most significant bit (leftmost) as the sign, and the remaining bits as the magnitude. SIGNED MAGNITUDE The most significant bit is usually assigned the value 0 for positive sign, and 1 for negative sign. The remaining bits represent the magnitude. Note that there are two zeros. Numbers in the range -(2 ** (n - 1)) - 1 to +(2 ** (n -1)) - 1 can be represented, where n is the number of bits used to store the number. The following table is for n = 4. Decimal Binary Decimal Binary ------- ------ ------- ------ 0 0000 -0 1000 1 0001 -1 1001 2 0010 -2 1010 3 0011 -3 1011 4 0100 -4 1100 5 0101 -5 1101 6 0110 -6 1110 7 0111 -7 1111 To get the negative of a 4 bit number X, xor it with 1000: -X = X xor -0 ONE'S COMPLEMENT The negative of a number X is obtained by inverting each bit of the number: -X = not(X) This means that negative numbers have 1 as their most significant bit, and positive numbers have 0 as their most significant bit. The range of numbers representable is the same as for signed magnitude. Decimal Binary Decimal Binary ------- ------ ------- ------ 0 0000 -0 1111 1 0001 -1 1110 2 0010 -2 1101 3 0011 -3 1100 4 0100 -4 1011 5 0101 -5 1010 6 0110 -6 1001 7 0111 -7 1000 Addition of two 1's complement numbers is independent of the signs of the two numbers. It is done by adding the binary representations and then adding 1 if there was a carry. 5 - 2 = 5 + (-2) = 0101 + 1101 ----- 10010 = 0010 + 0001 because of carry = 0011 = 3 4 - 6 = 4 + (-6) = 0100 + 1001 = ---- 1101 = -2 TWO'S COMPLEMENT The negative of a number X stored in n bits is obtained by subtracting it from 2 ** n: -X = (2 ** n) - X This is not a very useful definition, as it defines negation in terns of a more complex operation, namely subtraction. A simpler definition is the following: -X = not(X) + 1 which is easily checked using the table below. As for the two representations above, negative numbers are distinguished by having their most significant bit set to 1. This repesentation is different from the other two in that it does not have a negative zero. Numbers in the range -(2 ** (n - 1)) to +(2 ** (n - 1)) - 1 can be represented, where n is the number of bits used to store the number. Decimal Binary Decimal Binary ------- ------ ------- ------ 0 0000 1 0001 -1 1111 2 0010 -2 1110 3 0011 -3 1101 4 0100 -4 1100 5 0101 -5 1011 6 0110 -6 1010 7 0111 -7 1001 -8 1000 Addition of two 2's complement numbers is independent of the signs of the two numbers. It is done simply by adding the binary representations. Carry is ignored. 5 - 3 = 5 + (-3) = 0101 + 1101 = ----- 10010 = 0010 (ignoring carry) = 2 2 - 5 = 2 + (-5) = 0010 + 1011 = ---- 1101 = -3 If multiplication or division is to be performed on 1's complement or 2's complement negative numbers, it is necessary to take their modulus (convert them to positive numbers) before carrying out the operation. OVERFLOW DETECTION Overflow occurs when the result of an arithmetic operation cannot be held in the number of bits reserved for it. In the case of addition and subtraction, this is normally the number of bits taken up by each of the input numbers. None of the arithmetic operations in the examples above have overflow. To detect overflow in addition of 1's complement or 2's complement numbers, do the following: (1) For each number, do: if the number is positive (has a 0 as its most significant digit), then add an extra 0 on the left. If the number is negative (has a 1 as its most significant digit), then add an extra 1 on the left. (2) Perform the addition on the extended numbers. If the 1's complement convention is being used, then add 1 if there was a carry. (3) Ignore the carry bit. Now, compare the two most significant bits. If they are different, then overflow has occurred. Examples for 2's complement: 4 + 5 = 0 0100 + 0 0101 = ------ 0 1001 Overflow has occurred. 4 - 5 = 4 + (-5) = 0 0100 + 1 1011 = ------ 1 1111 = -1 - 3 - 7 = (-3) + (-7) = 1 1101 + 1 1001 = ------ 11 0110 Overflow has occurred. Note the carry bit. Example for 1's complement: 6 - 2 = 6 + (-2) = 0 0110 + 1 1101 = ------- 10 0011 = 0 0011 + 1 because of carry = 0 0100 = 4 -6 - 3 = -6 + (-3) = 1 1001 + 1 1100 = ------- 11 0101 = 1 0110 because of carry. Overflow has occurred. BINARY CODED DECIMAL Binary coded decimal, or BCD, is a 6 bit code for representing digits, uppercase letters, and some punctuation characters. It is not used very often now. However, it does have one interesting property: the BCD code of a digit is the same as its numeric value, e.g. 6 is represented by 000 110. To convert a digit from ASCII to its numeric value, it is necessary to 'and' it with 0000 1111. Decimal digits can be represented in only 4 bits, and so it is often useful to store each digit of a decimal number in a 4 bit cell. This is done in COBOL systems. The COBOL language allows the programmer to choose whether numbers are represented in 8 bits (so that they are printable), or 4 bits (so that they take up less space, and decimal arithmetic can be done more efficiently). If numbers are stored in 4 bit form, they are not printable. When signed numbers are stored in 4 bit form, the sign is immediately to the left if the most significant digit. Binary 13 (1101) is used for the minus sign, and binary 12 (1100) is used for the plus sign. SIMPLE INPUT/OUTPUT ON THE PDP-11 There are no machine language instructions specific to input or output operations on the PDP-11. However, there are system macros which perform simple I/O operations. The instructions for terminal I/O are .TTYIN and .TTYOUT. .TTYIN reads the next character typed in at the terminal and places it in the least significant byte of register R0. .TTYOUT writes to the terminal the character held in the least significant byte of register R0. To use .TTYIN and .TTYOUT, it is necessary to declare their use at the beginning of the program using .MCALL. The character set used in I/O operations on the PDP-11 is ASCII. To start a new line of output, it is necessary to output a carriage return (CR) followed by a line feed (LF). The following program reads a character from the terminal, and then writes it, followed by a carriage return and line feed. .MCALL .TTYIN,.TTYOUT ;System macros used. ;ASCII codes for: CR: .BYTE 15 ; carriage return (octal). LF: .BYTE 12 ; line feed (octal). START: .TTYIN ;Read a char into R0. .TTYOUT ;Write the char. MOVB CR,R0 ; .TTYOUT ;Output a carriage return. MOVB LF,R0 ; .TTYOUT ;Output a line feed. HALT ;Stop. .END START The following program will print the ASCII code in octal for a character read in from the terminal. There are several new instructions used. Several instructions have their mnemonic code ending in a 'B'. This indicates that these instructions only act on the bottom byte of the word. These instructions are especially useful in character manipulation. ASR means 'arithmetic shift right'. This instruction shifts its operand one bit to the right. ASL means 'arithmetic shift left', and shifts its operand one bit to the left. SWAB means 'swap bytes', and swaps the bytes of the word specified in the operand. BIC means 'bit clear', and clears the bits in the second operand which are set in the first operand. BIS means 'bit set', and sets the bits in the second operand which are set in the first operand. Thus, these two instructions are equivalent to the following boolean operations: BIS MASK,X ;X <- X or MASK BIC MASK,X ;X <- X and not(MASK) They are used in their byte form in the program. .MCALL .TTYIN,.TTYOUT CR: .BYTE 15 LF .BYTE 12 START: .TTYIN ;Read a char into R0. MOVB R0,R1 ;Copy it into R1. ASR R1 ;Shift R1 ... ASR R1 ; ASR R1 ;... 3 bits to the right. BICB #370,R1 ;Clear all but bits 0, 1 and ;2. The bottom byte of R1 ;now contains bits 3, 4 and 5 ;of the input char. BISB #60,R1 ;Convert it to ASCII. MOVB R0,R2 ;Copy the input char into R2. BICB #370,R2 ;Clear all but bits 0, 1 and ;2. The bottom byte of R2 ;now contains bits 0, 1 and 2 ;of the input char. BISB #60,R2 ;Convert it to ASCII. ASL R0 ;Shift R0 ... ASL R0 ;... 2 bits to the left. ;Bits 6 and 7 of the input ;char are now in the top byte ;of R0. SWAB R0 ;Put them in the bottom byte. BICB #374,R0 ;Clear the other bits. The ;The bottom byte of R0 now ;contains bits 6 and 7 of the ;input char. BISB #60,R0 ;Convert it to ASCII. .TTYOUT ;Write bits 6 and 7, MOVB R1,R0 ; .TTYOUT ;bits 3, 4 and 5, MOVB R2,R0 ; .TTYOUT ;and bits 0, 1 and 2 ;to the terminal. MOVB CR,R0 ; .TTYOUT ;Output a carriage return, MOVB LF,R0 ; .TTYOUT ;and then a line feed. HALT ;Stop. .END START