16-bit addition is the addition of two 16-values. First, we must recognize that the addition of two 16-bit values will result in a value that is, at most, 17 bits long. Why is this so? The largest value that can fit in 16-bits is 256 * 256 - 1 = 65,535. If we add 65,535 + 65,535, we get the result of 131,070. This value fits in 17 bits. Thus when adding two 16-bit values, we will get a 17-bit value. Since the 8051 works with 8-bit values, we will use the following statement: "Adding two 16-bit values results in a 24-bit value". Of course, 7 of the highest 8 bits will never be used--but we will have our entire answer in 3 bytes. Also keep in mind that we will be working with unsigned integers.
Programming Tip: Another option, instead of using 3 full bytes for the answer, is to use 2 bytes (16-bits) for the answer, and the carry bit ( C ), to hold the 17th bit. This is perfectly acceptable, and probably even preferred. The more advanced programmer will understand and recognize this option, and be able to make use of it. However, since this is an introduction to 16-bit mathematics it is our goal that the answer produced by the routines be in a form that is easy for the reader to utilize, once calculated. It is our belief that this is best achieved by leaving the answer fully expressed in 3 8-bit values.Let's consider adding the following two decimal values: 6724 + 8923. The answer is, of course, 15647. How do we go about adding these values with the 8051? The first step is to always work with hexadecimal values. Simlply convert the two values you wish to add to hexadecimal. In this case, that is equivalent to the following hexadecimal addition: 1A44 + 22DB.
How do we add thes two numbers? Let's use the exact same method we used in primary school, and in the previous section:
First we add the values in the 1's column (low byte): 44 + DB = 11F. Only a 2-digit hexadecimal value can fit in a single column, so we leave the 1F in the low-byte column, and carry the 1 to the high-byte column. We now add the high bytes: 1A + 22 = 3C, plus the 1 we carried from the low-byte column. We arrive at the value 3D.
Thus, our completed answer is 3D1F. If we convert 3D1F back to decimal, we arrive at the answer 15647. This matches with the original addition we did in decimal. The process works. Thus the only challenge is to code the above process into 8051 assembly language. As it turns out, this is incredibly easy.
We'll use the following table to explain how we're going to do the addition:
Programming Tip: Remember that we mentioned above that the sum of two 16-bit values
is a 17-bit value. In this case, we'll using 24-bits (R1, R2, and R3) for our answer, even
though we'll never use more than 1 bit of R1.
- Add the low bytes R7 and R5, leave the answer in R3.
- Add the high bytes R6 and R4, adding any carry from step 1, and leave the answer in R2.
- Put any carry from step 2 in the final byte, R1.
Step 1: Add the low bytes R7 and R5, leave the answer in R3.
MOV A,R7 ;Move the low-byte into the accumulator ADD A,R5 ;Add the second low-byte to the accumulator MOV R3,A ;Move the answer to the low-byte of the result
Step 2: Add the R6 and R4, add carry, leave the answer in R2.
MOV A,R6 ;Move the high-byte into the accumulator ADDC A,R4 ;Add the second high-byte to the accumulator, plus carry. MOV R2,A ;Move the answer to the high-byte of the result
Step 3: Put any carry from step 2 in the final byte, R1.
MOV A,#00h ;By default, the highest byte will be zero. ADDC A,#00h ;Add zero, plus carry from step 2. MOV R1,A ;Move the answer to the highest byte of the result
That's it! Combining the code from the three steps, we come up with the following subroutine:
ADD16_16: ;Step 1 of the process MOV A,R7 ;Move the low-byte into the accumulator ADD A,R5 ;Add the second low-byte to the accumulator MOV R3,A ;Move the answer to the low-byte of the result ;Step 2 of the process MOV A,R6 ;Move the high-byte into the accumulator ADDC A,R4 ;Add the second high-byte to the accumulator, plus carry. MOV R2,A ;Move the answer to the high-byte of the result ;Step 3 of the process MOV A,#00h ;By default, the highest byte will be zero. ADDC A,#00h ;Add zero, plus carry from step 2. MOV MOV R1,A ;Move the answer to the highest byte of the result ;Return - answer now resides in R1, R2, and R3. RET
And to call our routine to add the two values we used in the example above, we'd use the code:
;Load the first value into R6 and R7 MOV R6,#1Ah MOV R7,#44h ;Load the second value into R4 and R5 MOV R4,#22h MOV R5,#0DBh ;Call the 16-bit addition routine LCALL ADD16_16
|Previous: 16-Bit Math Introduction||Tutorial Contents||Next: 16-Bit Subtraction|