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 |
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 |
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.
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 |
Previous: 16-Bit Addition | Tutorial Contents | Next: 16-Bit Multiplication |