Coding for Reuse Course - Module 3 Lesson 4
Decimal Adjust for Addition and Subtraction

In this lesson we will packet binary coded decimal (BCD) and how to maintain it during addition, increment, subtraction and decrement operations.

License Terms  

The source and/or object code (subsequently referred to as code) presented in this and subsequent lessons is the property of saxelec.com and owner who retains copyright protection. This code in whole or in part is licensed only for single copy per user, non-commercial use; except in the case of educational institutions, where a license of single copy per student, only as part of course curricula, is permitted.

Donald Gerard Polak (owner)

Packed BCD Format  

Our microprocessor normally works with two's complement, hexadecimal numbers. This is this most efficient notation for performing operations, as it contains both sign and magnitude of the data and fully utilizes all bit positions. However, there is another data format used for special purposes. This notation is called packed binary coded decimal, or most frequently, simply BCD.

BCD contains only magnitude information (no sign). Each byte contains two, back-to-back, four bit 'nibbles'; each representing a binary value between zero and nine. The least significant four bits are the units value, and the most significant four bits are the tens value. Together they represent values from 0 to 99 inclusive.

BCD is most frequently used to directly drive digital read out (DRO)) devices and for format conversions to American Standard Code for Information Interchange (ASCII) or UNICODE characters for display or printing; since adding 30 hex to a BCD nibble in either code set will form the character equivalent of the value.

BCD Addition  

So what happens when we add BCD numbers on a two's complement computer? Well that depends on the magnitude and carry of the result on a per nibble basis. If the magnitude of the result in a particular nibble is nine or less, and there is no carry, the result is the same for both BCD and two's complement addition; as in:

  22 
+ 17 
-----
  29 
         
  0010  0010       
+ 0001  0111       
------------------      
  0010 1001 (29)

But suppose the two's complement addition resulted in a carry from, let's say, the lowermost nibble; what happens then?

  29 
+ 17 
-----
  36 
         
  0010  1001       
+ 0001  0111       
------------------      
  0011 0000 (30)

But what if the two's complement addition results in a purely hexadecimal value, in let's suppose, the lower nibble, and no carry occurs?

  28 
+ 17 
-----
  35 
         
  0010  1000       
+ 0001  0111       
------------------      
  0010 1111 (2F)

What caused this? Well first of all you must understand that each nibble in BCD is a separate, stand-alone entity. When a carry is required, or occurs; the value carried should be ten. A carry out of a nibble on a two's complement computer is sixteen, which, in essence, you took six more than required from the nibble that initiated the carry. To put the results back into BCD, you must add that six back. In the case of a purely hexadecimal result, the cause is the same, except that there is a disconnect between when the carry should have occurred and when it actually does.

The DAA Instruction  

The 8085 microprocessor contains one additional flag, AF, which is used by the decimal adjust for addition (DAA) instruction. This flag indicates that a carry out of the lowermost nibble has occurred. The 8085 uses the AF and CF flags to determine whether or not to add six to the appropriate nibble. It also checks each nibble for a hexadecimal value in making this decision.

This method works until we get to the number 99 (BCD), then something else that must be accounted for occurs:

    99 
+    1 
---------
 (1)01 
       
       
       
       
  1001  1001       
+ 0000  0001       
------------------      
  1001 1010        
+ 0000  0110        
------------------      
  1010 0000 (A0)

In this case, the DAA instruction itself forced a carry to occur from the lowermost nibble, causing the uppermost nibble to assume a hexadecimal value during the instruction. The solution is to anticipate the effects of this carry on the uppermost nibble if that nibble is greater than eight.

Another breakdown happens between 159(BCD) and 160 (BCD) if we simply use the carry out of the DAA instruction as the new CF:

    80 
+   79 
---------
 (1)59 
       
       
       
       
  1000  0000        
+ 0111  1001        
------------------        
  1111 1001         
+ 0110  0000         
------------------        
1 0101 1001 (1)59
    80 
+   80 
---------
 (1)60 
       
       
       
       
  1000  0000        
+ 1000  0000        
------------------        
1 0000 0000         
+ 0110  0000         
------------------        
0 0110 0000 (0)60

Here, disposing of the old carry and replacing it with the carry out of the DAA instruction, effectively threw out a hundred. If you are in the practice of throwing out a hundred, I would sure like to meet you, friend. The DAA instruction actually OR's the old carry with the carry out of the adjustment to form the new CF.

Decimal Adjust for Subtract  

So what happens when we subtract instead of add? First of all, we must be able to detect when the result is the result of a subtract. After all, if you remember binary math, a subtract is nothing more than adding a two's complement value to the primary operand. The S8085C and S8085D manage this task by adding an additional flag, the NF (negative flag), which gets set on all eight-bit subtract and decrement operations, and cleared for all other transactions. The NF helps us to determine how to adjust the result.

When you are performing two's complement subtraction by hand, if the magnitude of the subtrahend is greater than or equal to the minuend a carry occurs. If the minuend is greater, no carry occurs. The 8085 complements the carry bit automatically to set or clear the CF and AF flags, which are used to indicate borrows during subtract and decrement operations.

Similar to the carry in addition, the magnitude of a borrow is sixteen instead of ten. That means if you are performing a BCD subtraction, your result will be six greater than what you wanted. To adjust the value back to BCD, you will need to subtract six from that nibble. Observe:

    52 
-   43 
---------
 (0)09 
       
       
       
       
  0101  0010        
+ 1100  1101        
------------------        
  0001 1111         
+ 1111  1010         
------------------        
1 0000 1001 (0)09

Hundreds Complement Notation  

What happens when our subtraction yields a negative result? Let's look:

    98 
-   99 
---------
 (-)01 
       
       
       
       
  1001  1000        
+ 0110  0111        
------------------        
  1111 1111         
+ 1001  1010         
------------------        
1 1001 1001 (1)99

So what went wrong? Fact is - nothing. The result is correct. The borrow indicates another hundred hanging out there, like you subtracted 99 from 198 instead of 98. The result is in hundreds complement notation. Hundreds complement notation is simply the difference between one hundred and the absolute value of the result. This is done because BCD math is seldom performed on atomic (single) digit pairs. It must assume some more significant digits are out there. If your final result ends of negative, you can convert from hundreds complement to absolute notation by subtracting each byte of the result from zero (which represents 100 with the borrow).

1 0000  0000        
+ 0110  0111        
------------------        
1 0110 0111         
+ 1001  1010         
------------------        
0 0000 0001 (-)01

True Sign Logic  

True sign logic assumes the operand magnitudes in the preceding instruction were greater than zero. That means the sign of any DAA result after an increment or add operation should be zero (positive). The sign of the DAA instruction after a decrement or subtract operation becomes 1 (negative) only if the carry flag from the preceding operation was set. In effect, this means that the sign flag from a DAA operation is nf & cf.

IMPLEMENTATION  

To avoid additional inputs and decision making logic in the microcode state machine, the DAA instruction always adds the calculated adjustment value to the accumulator. In the 8085B version this is a straight forward exercise, with the exception of the corner cases noted above. In the S8085C and S8085D versions it is a little more complex. the decimal adjust for subtract is totally reliant on the incoming state of the auxiliary carry and the carry flags. Since DCRx instructions do not affect carry, you must do an ORAA instruction prior to the decrement to clear carry. Consequently, a DAA following a DCRA will not support negative results.

The flag logic for carry and auxiliary carry required modification to support the DAA instruction. The DAA adjustment value calculation was moved to the register file. I also, as promised, checked the uf flag and, since it works correctly as coded, decided that no modification was necessary.

With the DAA instruction added; our project has become a complete microprocessor, equivalent to the original 8085A and 8085B, and new 8085C microprocessors.

Project with enhanced DAA instruction implemented.

SIMULATION  

Of course, I don't expect you to believe a word of this without a simulation at least. Since a simple simulation requires a much longer simulation period (not to mention we really want to see the decimal adjust for subtract enhancements), we will need a new definitions file :

Definition file for new simulation

and a new test bench :

Test bench for new simulation

This time I'm not going to show you a bunch of pretty pictures. That's for you to do. Feel free to modify the test bench and try out different instruction sequences.

Exercise  
  1. What do we do with the existing carry during a decimal adjust for addition?

  2. What is hundreds complement notation and why do we use it?

  3. When do we need to adjust the value after ADD or INCREMENT operations?

  4. How do we adjust the value after ADD or INCREMENT operations; and why?

  5. When do we need to adjust the value after SUBTRACT or DECREMENT operations?

  6. How do we adjust the value after SUBTRACT or DECREMENT operations; and why?

  7. What are the flags used by the DAA instruction, and what do they mean?

  8. Simulate the added instruction and verify its operation. Make sure that you check the flags.