Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Microcontroller Programming. Thi Micro Chip PIC (Julio Sanchez, 2007).pdf
Скачиваний:
475
Добавлен:
12.08.2013
Размер:
4.99 Mб
Скачать

62

Chapter 4

4.3 Bit Manipulations and Auxiliary Operations

In addition to basic logic and arithmetic, microcontrollers contain primitive operators to manipulate individual bits, to compare operands, to make decision based on the state of individual bits and flags, and to convert data to other formats. As always, presence or absence of some of these operations, as well as their degree of power and sophistication, varies with the individual microcontroller. In the following subsections we describe the most commonly available primitives.

4.3.1 Bit Shift and Rotate

The fundamental operators to shift and rotate are useful in developing BCD and binary arithmetic routines. One interesting use of bit shifting is in implementing binary multiplication and division routines.

Shift operations consist of transposing to the left or right all the bits in the operand. In microcontrollers the operand is usually a processor register. For example, after a right shift operation all the bits in the value 01110101B (75H) are moved one position to the right, resulting in the value 00111010B (3AH). Note that on a right shift the right-most bit disappears and a zero comes into the high-order bit. By the same token, in a left shift the high-order bit disappears and a zero comes into the low-order bit. Figure 4-2 shows the action of a left-shift operation.

7

6

5

4

3

2 1 0

 

 

 

 

lost

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

BEFORE SHIFT

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

bit

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

AFTER SHIFT

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

7 6 5 4

3

2

1

0

 

 

 

Figure 4-2 Left Shift Operation

The rotate operation differs from the shift in that in the rotate the low-order bit is either a copy of the high-order bit or of the carry flag. In the first case the operation is a pure rotate, in the second case the rotate is referred to as rotate-through-carry. Figure 4-3 shows the action of a left-rotate-through-carry flag.

7 6 5 4 3 2 1 0

FIRST STEP

CF 7 6 5 4 3 2 1 0

7 6 5 4 3 2 1 0

CF

 

 

 

 

 

 

 

 

 

 

SECOND STEP

 

 

 

 

 

 

 

 

 

 

Figure 4-3 Rotate-through-carry Left Operation

Digital Logic, Arithmetic, and Conversions

63

Note in Figure 4-3 that the contents of the carry flag are first copied to the low-order bit of the destination operand, then the individual bits of the source (in gray in the illustration) are shifted left and moved to the destination. Finally the high-order bit of the source is copied to the carry flag.

There are several possible variations of the rotate operation. The Intel microprocessors distinguish between arithmetic and logic rotates. In the arithmetic rotation the high-order bit is preserved in order to maintain the sign of the operand. The rotate shown in Figure 4-3 is the one most common in microcontroller hardware. Clearing the carry flag before the rotate takes place makes the operation identical to a shift.

4.3.2 Comparison Operations

An interesting property of subtraction is its use in finding the relative size of two operands. This interesting action of subtraction is based on the following logic:

1.If the result of a subtraction is zero, then both operands were of the same size.

2.If the result of a subtraction is a positive number, then the subtrahend was smaller than the minuend.

3.If the result of a subtraction is a negative number, the subtrahend was larger than the minuend.

In a binary/digital device the result of a subtraction operation can be determined by observing the flags. If the zero flag is set, then the operands were the same (case 1, above). If the carry flag is set, then the subtrahend was larger than the minuend (case 3, above). If neither the carry nor the zero flag is set, then resulting subtrahend was smaller than the minuend (case 2, above). Since all microcontrollers offer some mechanism for re-directing execution according to the state of the flags, a program can use subtraction to make these decisions.

The one objection to the use of subtraction in comparing the size of two operands is that the process will change one of them. To use subtraction in comparison operations the programmer has to find some way of preserving the minuend. Alternatively, some devices contain a comparison operator that sets the flags as if a subtraction had taken place but without changing the operands. High-end microcontrollers are equipped with dedicated comparison operators, but the middle- and low-range devices usually are not.

4.3.3 Other Support Operations

Midand high-range microcontrollers contain other auxiliary bitwise, arithmetic, and logic operators that can be useful to the programmer. These include instructions to:

1.Increment and decrement operands

2.Clear registers or storage locations

3.Swap nibbles

4.Clear and set individual bits

5.Test individual bits

64

Chapter 4

Usually instructions to increment and decrement and to test individual bits are also capable of redirecting execution according to the result. For example, a special decrement can be followed by a jump if decrementing sets the zero flag. Or a bit test instruction can include a jump that is taken if the tested bit is set or reset.

4.4 Unsigned Binary Arithmetic

Since microcontrollers are not used in data processing, microcontroller programming does not usually require the development of powerful or sophisticated numerical routines. At the same time, because microcontrollers often lack primitive support for even the most essential calculations, the programmer makes up for this deficiency. For example, mid-range PIC microcontrollers contain primitive instructions for signed and unsigned addition and subtraction of byte-size operands. Unsigned addition and subtraction operations that exceed one byte, as well as unsigned multiplication and division, must be provided in software.

In unsigned arithmetic all bits of the binary encoding are interpreted as magnitude bits and all numbers are positive. Addition of unsigned binary numbers is limited by the machine’s word size. For example, a mid-range PIC microcontroller performs unsigned addition on 8-bit operands. An overflow of the sum is reported by the carry flag set. In this case the carry flag clear indicates that the sum is within the storage capacity of the format. In unsigned arithmetic processing, routines for extending operations to multiple bytes are straightforward and relatively simple.

4.4.1 Multi-byte Unsigned Addition

Many microcontrollers are one-byte machines, so operands and results for arithmetic operations must be contained within eight bits. The largest unsigned value that can be represented in a single byte is the decimal number 255. But often applications require adding operands that are larger than a single byte and storing results that exceed this limit. In these cases multi-byte routines become necessary.

The simplest case is the addition of two unsigned byte-size operands whose sum exceeds 255 decimal. This case requires storing the result in a two-byte area and detecting those cases in which there is a carry into the high-order byte. In this case the largest possible operands for byte addition are the hexadecimal numbers FF. Addition is as follows:

Binary:

1 1 1 1 1 1 1 1

+1 1 1 1 1 1 1 1

---------------

11 1 1 1 1 1 0

C <=

In this example the symbol C <= represents a carry out of the high-order bit, the case when the sum exceeds the capacity of a single byte. In hexadecimal, the sum of HFF + HFF = H1FE. You can add two byte-size operands into a two-byte storage area by using byte addition to determine the low-order byte of the result and testing for a carry out of the high-order bit. If there is a carry, then the high-order byte of the result is 1; otherwise the high-order byte is 0.

Digital Logic, Arithmetic, and Conversions

 

 

 

65

 

 

first 4-byte

second 4-byte

possible

 

 

5-byte

 

 

 

operand

 

 

operand

 

carry

 

 

 

result

 

 

 

 

 

 

 

 

 

+

 

 

 

 

 

 

 

 

 

+

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+

 

 

 

 

 

 

 

 

 

+

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0/1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+

 

 

 

 

 

 

 

 

 

+

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0/1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+

 

 

 

 

 

 

 

 

 

+

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0/1

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

+

 

 

=

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

0/1

 

 

 

 

 

 

 

 

 

Figure 4-4 Unsigned Multi-byte Addition

The same logic can be generalized to add more than two byte-size operands as long as the storage area for the result exceeds the size of the operands by one byte. For example, two word-size operands (16 bits each) can be added into a 3-byte (24-bit) storage area, or two double-word operands (32 bits) into a 5-byte storage area. The general algorithm for multi-byte addition is shown in Figure 4-4.

The case shown in Figure 4-4 consists of adding two, 4-byte operands into a 5-byte sum. The addition of the first two operands assumes that there is no carry. In the remaining stages there can be a possible carry from the previous stage if the sum of the two byte-size operands, plus the previous carry, exceed the storage capacity of eight bits. The last byte of the result is determined solely by the possible carry from the previous stage.

In Figure 4-4 we see that multi-byte addition requires the sum of three values in all stages except the first and the last one. Some high-end microcontrollers have addition operators that accept a three-byte operand. Others have special addition opcodes that automatically add-in the carry flag. The latter operators are referred to as add-with-carry. However, in most lowand mid-range devices the software must take care of incrementing the sum if there is a carry from the previous stage. The actual multi-byte addition routines are developed in the context of programming the various microcontrollers, discussed later in this book.

4.4.2 Unsigned Multiplication

The case for multiplication cannot be generalized since high-end microcontrollers usually contain one or more multiplication operators; this is not the case in lowand mid-range devices. In the first case implementation is simply by using the correspond-

66

Chapter 4

ing operator. This section explains multiplication in devices that lack a dedicated multiplication operation code.

Arithmetically, multiplication is performed by repeated addition. The multiplier represents the number of times that the multiplicand must be added to itself. Therefore, 3 times 4 is the same as 3 + 3 + 3 + 3. This fact allows implementing multiplication routines in software as long as the device contains an addition operator. The logic is based on using the multiplier as a counter. This counter is decremented each time that the multiplicand is added to itself. The routine ends when the counter is exhausted, as shown in the flowchart in Figure 4-5.

START

A = MULTIPLICAND

B = MULTIPLIER

PERFORM P = A * B

P (PRODUCT) = 0

C (COUNTER) = B

 

 

 

 

 

YES

 

COUNTER = 0

 

 

DONE

 

 

 

 

?

 

 

 

 

 

 

NO

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

P = P + A

 

 

 

 

C = C - 1

 

YES

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Figure 4-5 Unsigned Multiplication Flowchart

The beauty of the repeated addition algorithm is its simplicity and its main shortcoming is its slowness. An alternative way of performing multiplication is by shifting the bits of the operand. This method is based on the properties of a binary positional system, in which the value of each digit is a successive power of 2. Therefore, by shifting all digits to the left, the value 0001B (1 decimal) successively becomes 0010B (2 decimal), 0100B (4 decimal), 1000B (8 decimal), and so on.

Binary multiplication by means of bit shifting has the downside that the multiplier must be a power of 2. Otherwise, the software must shift by a power of 2 that is smaller than the multiplier and then add the multiplier as many times as necessary to complete the product. In this manner, to multiply by 5 we can shift left twice and add once the value of the multiplicand. To multiply by 7 we would shift left twice and then add three times the value of the multiplicand. As the multiplier gets larger and more distant from the smaller power of 2, the number of addition operations required is also larger, and the effectiveness of the algorithm diminishes.