16-Bit Subtraction
| This webpage is part of
The 8051/8052 Microcontroller book which was authored by
Craig Steiner, the author of this tutorial. If you find
this tutorial useful and easy to understand, you may wish
to consider obtaining
the book
which includes many additional chapters not contained in this online tutorial.
This tutorial is copyrighted by the author--do not copy/distribute without
permission from the author. |
16-bit subtraction is the subtraction of one 16-bit value from another. A subtraction of this
nature results in another 16-bit value. Why? The number 65535 is a 16-bit value. If we
subtract 1 from it, we have 65534 which is also a 16-bit value. Thus any 16-bit subtraction
will result in another 16-bit value.
Let's consider the subtraction of the following two decimal values: 8923 - 6905.
The answer is 2018. How do we go about subtracting these values with the 8051? As is the
case with addition, the first step is to convert the expression to hexadecimal. The above
decimal subtraction is equivalent to the following hexadecimal subtraction: 22DB -
1AF9.
Again, we'll go back to the way we learned it in primary school:
| . |
256's |
1's |
| . |
22 |
DB |
| - |
1A |
F9 |
| = |
07 |
E2 |
First we subtract the second value in the 1's column (low byte): DB - F9. Since F9 is greater
than DB, we need to "borrow" from the 256's column. Thus we actually perform the subtraction
1DB - F9 = E2. The value E2 is what we leave in the 1's column.
Now we must perform the subtraction 22 - 1A. However, we must remember that we "borrowed" 1
from the 256's column, so we must subtract an additional 1. So the subtraction for the 256's
column becomes 22 - 1A - 1 = 7, which is the value we leave in the 256's column.
Thus our final answer is 07E2. If we conver this back to decimal, we get the value 2018,
which coincides with the math we originally did in decimal.
As we did with addition, we'll use a small table to help us conver the above process to 8051
assembly language:
| . |
256's |
1's |
| . |
R6 |
R7 |
| + |
R4 |
R5 |
| = |
R2 |
R3 |
Since we're subtracting 16-bit values, each value requires two 8-bit registers. Essentially,
the value to be subtracted from will be held in R6 and R7 (the high byte in R6 and the
low byte in R7) while the value to be subtracted will be held in R4 and R5 (the high byte
in R4 and the low byte in R5). We will leave our answer in R2, and R3.
Let's review the steps involved in subtracting the values above:
- Subtract the low bytes R5 from R7, leave the answer in R3.
- Subtract the high byte R4 from R6, less any borrow, and leave the answer in R2.
We'll now convert the above process to assembly language, step by step.
Step 1: Subtract the low bytes R5 from R7, leave the answer in R3.
MOV A,R7 ;Move the low-byte into the accumulator
CLR C ;Always clear carry before first subtraction
SUBB A,R5 ;Subtract the second low-byte from the accumulator
MOV R3,A ;Move the answer to the low-byte of the result
|
Step 2: Subtract the high byte R4 from R6, less any borrow, and leave the answer in R2.
MOV A,R6 ;Move the high-byte into the accumulator
SUBB A,R4 ;Subtract the second high-byte from the accumulator
MOV R2,A ;Move the answer to the low-byte of the result
|
Programming Tip: The SUBB instruction always subtracts the second value in
the instruction from the first, less any carry. While there are two versions of the
ADD instruction (ADD and ADDC), one of which ignores the carry bit, there is no such
distinction with the SUBB instruction. This means before you perform the first
subtraction, you must always be sure to clear the carry bit. Otherwise, if the carry
bit happens to be set you'll end up subtracting it from your first column value --
which would be incorrect.
Combining the code from the two steps above, we come up with the following subroutine:
SUBB16_16:
;Step 1 of the process
MOV A,R7 ;Move the low-byte into the accumulator
CLR C ;Always clear carry before first subtraction
SUBB A,R5 ;Subtract the second low-byte from 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
SUBB A,R4 ;Subtract the second high-byte from the accumulator
MOV R2,A ;Move the answer to the low-byte of the result
;Return - answer now resides in R2, and R3.
RET
|
And to call our routine to subtract the two values we used in the example above, we'd use the code:
;Load the first value into R6 and R7
MOV R6,#22h
MOV R7,#0DBh
;Load the second value into R4 and R5
MOV R4,#1Ah
MOV R5,#0F9h
;Call the 16-bit subtraction routine
LCALL SUBB16_16
|
(C) Copyright 1997 - 2008 by Vault Information Services LLC. All Rights Reserved.
Information provided "as-is" without warranty. Please see details.
Contact us for usage and copy permission.
|