0
\$\begingroup\$

Page 88 of the ARM Cortex-M4 Generic User Guide says "The SBC instruction subtracts the value of Operand2 from the value in Rn. If the carry flag is CLEAR, the result is reduced by one." Why the result is reduced by 1 when the carry flag is CLEAR rather than SET? I think the SBC instruction subtracts the value of the carry flag from the result of subtracting operand2 from Rn, therefore the result is reduced by 1 when the carry flag is SET. Am I wrong?

\$\endgroup\$
1
  • \$\begingroup\$ the carry flag is probably cleared by a borrow in previous operation ... check other operand descriptions \$\endgroup\$
    – jsotola
    Commented Mar 22, 2021 at 4:15

1 Answer 1

2
\$\begingroup\$

Forget everything you think you know, for a moment. Let's just consider the idea of how subtraction takes place in a processor.

It's very convenient to develop a logical unit that supports ADD and then modify one of the operands in order to achieve a SUB operation. (Note: I'm not yet discussing SBC, just SUB.) The SUB operation involves a minuend and a subtrahend. To achieve the SUB operation, it's very easy to instead just invert the subtrahend and also to invert the carry-in.

Keep in mind that \$-B=\overline{B}+1\$. So if the subtrahend is inverted and if the carry-in is also inverted (assume it is 0, if there is no borrow), then the subtraction operation only has to invert the subtrahend and also the carry-in, in order to perform a SUB operation.

Let's say the ALU is just 16 bits in size, but we need to perform a 32-bit subtraction. The minuend is 0x00000000 and the subtrahend is 0x00000001. Because we are performing a subtraction, the initial carry-in starts as one (no borrow when starting out the operation.)

So we'd perform the following 16-bit ADD operation using the lower-order 16 bits:

 0x0000       (minuend, lower 16 bits)
+0xFFFE       (inverted subtrahend, lower 16 bits)
+0x0001       (carry-in, set before starting operation)
-------
 0xFFFF       (carry-out is zero)

We store this result and then proceed to the next step.

 0x0000       (minuend, upper 16 bits)
+0xFFFF       (inverted subtrahend, upper 16 bits)
+0x0000       (carry-in from prior carry-out result)
-------
 0xFFFF       (carry-out is zero)

So our final result is 0xFFFFFFFF with a carry-out of zero (implying a borrow still exists if this were to be continued for a still wider result.)

This is the correct result.

Note that SUB is handled using ADD and that the meaning of the carry bit differs. In the case of ADD, a carry-out of 1 implies that even wider results may require the continuation of that additional carry. But in the case of SUB, a carry-out of 0 implies that even wider results may require the continuation of a borrow.

The sense of the carry bit is different depending upon the operation.

Some processors handle the meaning of the carry bit differently. So you must check each processor, separately. Never assume that all of them do the same thing. But in this case, it's easy. The carry-in status is not inverted for SUB or SBC, but the subtrahend is inverted. The carry-out status is also not inverted when stored back. All they do for subtraction is to invert the subtrahend bits. That greatly simplifies the ALU logic, which is a desired result when laying out the ALU logic.

This whole process allows using a single ALU ADD operation to handle both subtraction as well as addition. That's an advantage in minimizing instantiated logic.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.