INTEL 8008/8080/8085 subtraction

82 Views Asked by At

I cannot find any reference to such a specific situation related to the subtraction operation done by INTEL 8008, 8080 and 8085. The topic, here, is the inverted carry (i.e. a borrow), that subtraction performs at the end

Now how does the processor deal with subtracting by 0? Because the two's complement of 0 is 0, there will be no carry-out, so following the subtraction logic, the carry will be always set (i.e. meaning a borrow happened), but in this case, it is wrong.

Is the processor applying in this case the logic of the addition operation, where the carry is not inverted?

thanks a lot,

Fausto

2

There are 2 best solutions below

1
hs takeuchi On BEST ANSWER

Now how does the processor deal with subtracting by 0? Because the two's complement of 0 is 0, there will be no carry-out, so following the subtraction logic, the carry will be always set (i.e. meaning a borrow happened), but in this case, it is wrong.

No. The logic used for subtraction is to complement the second operand, then add together the first operand, the complemented second operand, and the carry input. To get the two's complement of the second operand, the carry input is always a 1 (borrow input=0). For an 8-bit zero, that gives you x - 00000000 ==> x + 11111111 + 1 ==> x + 100000000 (carry output=1, borrow output=0). No special treatment for zero.

1
Myria On

The 8080 uses the "borrow" type of carry flag with subtraction. The incoming carry flag says whether to subtract an additional 1 from the result, and the outgoing carry flag says whether the subtraction borrowed out of the high bit.

That is, for sbc a, b (Zilog syntax; I don't know 8080 syntax):

uint16_t result = (uint16_t)a - b - carry;
a = (uint8_t)result;
carry = (result >> 8) & 1;
// other flags

This type of carry subtraction is the opposite way from 6502 (and many other later CPUs like ARM). On the 6502, subtraction is implemented by NOTing the argument and doing an addition. sbc #$12 means:

uint16_t result = (uint16_t)a + (0x12 ^ 0xFF) + carry;
a = (uint8_t)result;
carry = (result >> 8) & 1;
// other flags

This turns out to be the exact opposite of how carry works for subtraction on 8080. It comes from the identity that -x == ~x + 1.