BITS AND PIECES This month, I am going to start with a brief explanation of the binary numbering system. There are only 2 digits allowed in binary: 0 and 1. Four bits make a nibble which happens to equal one hexadecimal digit also. Eight bits make a byte. In an unsigned 8-bit number, all bits are added to create a total sum (0 to 255 decimal, $00 to $FF, hexadecimal). The least signigicant bit is the one at the immediate right of the number while the most significant bit is the one at the left. Bits are numbered, starting at 0, from the least significant bit to the most significant bit. To find the value of a bit in decimal, raise the number 2 to the power of the bit number. If the bit is a 1, this value is added to the total and if it is 0, the value is ignored (0 X anything = 0). Some examples of unsigned binary numbers are as follows: 01001111 = 79 decimal (2^6+2^3+2^2+2^1+2^0) 10000000 = 128 decimal (2^7) One more convention is that two bytes make up a word. This is all very straigt-forward. Now for the monkey wrench: we are going to deal with signed binary numbers. The sign bit is the leftmost bit or the most significant one. If this bit is a 1 then the number is negative and if this bit is a 0 then the number is positive. Positive numbers are calculated as above. To calculate the value of a negative number, you must first negate it--that is, change all 0s to 1s and all 1s to 0s. Then figure out the value of this number and add one to it. I am including a program to print to screen or printer a list of 8-bit binary numbers and their TWO'S COMPLEMENT or signed decimal equivalent, their hexadecimal equivalents, and their unsigned or ONE'S COMPLEMENT equivalents. Hexadecimal values are representations of their binary equivialents. They are in common use because they break easily on byte boundaries and take up 1/4 the room that a binary equivalent takes. The use of hexadecimal values can greatly facilitate the calculation of LBxx, Bxx, and PCR addresses. First, convert your binary value to hexadecimal. Then expand the value to 2 bytes by adding $FF to the beginning if it is negative or $00 to the beginning is it is positive. (we are dealing with relative locations here). Then, add this value to the address of the NEXT instruction in the program. For example: offset=$FE, next addr=$7002 add: $FFFE $7002 ------- 17000 --- ignore the 1 at the beginning-it is an overflow value which we need not concern ourselves with. You add hexadecimal the same way you add decimal numbers. The following is a table of single digit additions: + 0 1 2 3 4 5 6 7 8 9 A B C D E F 0 0 1 2 3 4 5 6 7 8 9 A B C D E F 1 1 2 3 4 5 6 7 8 9 A B C D E F 10 2 2 3 4 5 6 7 8 9 A B C D E F 10 11 3 3 4 5 6 7 8 9 A B C D E F 10 11 12 4 4 5 6 7 8 9 A B C D E F 10 11 12 13 5 5 6 7 8 9 A B C D E F 10 11 12 13 14 6 6 7 8 9 A B C D E F 10 11 12 13 14 15 7 7 8 9 A B C D E F 10 11 12 13 14 15 16 8 8 9 A B C D E F 10 11 12 13 14 15 16 17 9 9 A B C D E F 10 11 12 13 14 15 16 17 18 A A B C D E F 10 11 12 13 14 15 16 17 18 19 B B C D E F 10 11 12 13 14 15 16 17 18 19 1A C C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B D D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C E E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D F F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E This is not as childish as it looks: this table may save you much hassle if you memorize it. As with decimal, if the addition adds to two digits, carry the extra digit to the next column. It is necessary that you understand the above information for the next section of this article. SHIFTS, ROTATES, ANDS, ORS, ETC. You may have been wondering what a "logical shift left" means or what is a "rotate left". This section will attempt to explain how this works. First of all, the difference between a shift and a rotate is that a shift moves the overflow bit into the Carry flag and inserts nothing into the vacated byte. A rotate, on the other hand, shifts the Carry into the vacated byte and puts the overflow into the Carry afterward. Next, there are two types of shifts: logical and arithmetic (pronounce arith mattic). Logical shifts introduce zeros into the vacated bits. An arithmetic shift to the right assumes that the sign bit is to remain the same and also be moved to the next bit. An arithmetic shift to the left is identical to a logical shift to the left. The shift and rotate operations work only on the two accumulators (not D) and 8-bit memory locations. Logical ands, ors, and eclusive ors, are very important in programming. As with shifts and rotates, these operations require binary values to perform. In an AND, all bits involved must be 1 for the result to be 1. In an or, all bits must be 0 for the result to be 0. An exlusive or just resets bits. Some examples: 00111111 AND 11110000 = 00110000 00000100 OR 00000011 = 00000111 00011001 EOR 00011111 = 00000110 And is generally used to clear bits within a byte without changing others. Or is used to set bits and eor is used to flip bits. There are two special cases of these instructions. These act directly on the CC register. These are ANDCC and ORCC. These instructions can be used to set or clear specific flags. The flags are arranged as follows: bit# 7 6 5 4 3 2 1 0 flag E F H I N Z V C E=Entire state--used for interupts, you can ignore it. F=FIRQ disable--used for interupts, you can ignore it. H=Half Carry--carry from bit 3 of an 8-bit add I=IRQ disable--used for interupts, you can ignore it. N=Sign flag--sign of two's complement result Z=Zero flag--set if result is 0 V=Overflow flag--Overflow from bit following sign bit C=Carry--Carry from Most Significant Bit NEGates are exactly as explained above in the section on signed 8-bit numbers; they only work on 8-bit values. DECrement - used to decrease an 8-bit value by 1 INCrement - used to increase an 8-bit value by 1 CLeaR - used to clear an 8-bit value to 0 (clears carry) TeST - sets flags according to result (8-bits) CoMPare - compares values and sets flags (8 or 16 bits) Some miscleaneous instructions are: DAA - decimal adjust A. This instruction has little practical use. SEX - sign extend B into A. This instruction copies the sign bit of register B into all 8 bits of register A. This leaves a proper 16-bit representation of a signed number in B. ABX - add B to X unsigned. This instrucion adds Accumulator B to register X. It is used to point to entries in tables. CWAI - wait for interrupts -- I am not going to deal with interrupts in this series. MUL - multiplies unsigned A * B. The result is left in D. NOP - no operation - this is self explanatory. SYNC - synchronize to interrupts - usually is not used. There are, however, 4 instructions which bear elaboration: LEAX, LEAY, LEAU, and LEAS. These instructions are used to perform arithmetic operations on the index registers. They use indexed addressing and can be used to point to a location in a position independant program; LDX, etc. will only load from that address. The LEAS instruction is often used to remove data or addresses off the stack when they are no longer necessary and the programmer does not wish to modify any registers. These instructions are often used to point to data in tables. There are also several instructions which operate only with one of the accumulators and an operand: ADCA, ADCB, BITA, BITB, SBCA, and SBCB. BITA and BITB set the condition codes as if the operand were logically anded with the appropriate accumulator. ADCA and ADCB add the operand and the value of the carry to the appropriate accumulator. SBCB and SBCA set the carry if the unsigned result goes below zero (underflow); they also subtract the current value of carry and the operand from the appropriate accumulator. There are two other arithmetic operations which may be done using accumulators: ADDs and SUBtracts. ADDA, ADDB, SUBA, SUBB -- these operate on 8-bit accumulators by adding or subtracting the operand and the register and leaving the result in the register. These may also be done on accumulator D using ADDD or SUBD. This raps up my discussion of 6809 instructions. I will include a program next month which integrates some of the techniques I explained here. I will not by any means try to implement all of them; that would be too long, but if you are ever disassembling something, whether with my disassembler from Issue #22 of CFDM or some other method, the information in these articles should help you understand the program better (unless it uses interrupts, which are complicated enough as to require more skill than I have to explain completely.)