Another great guide: Understanding the transfer / transfer conditions in Carry vs. It has some nice step-by-step examples with 4-bit numbers that make it easy to keep everything in mind. This also explains that unsigned carry is what you check when you interpret bits as unsigned, while signed overflow is what you check when interpreting bits as signed.
Based on OP comment:
Does this mean that the zero flag is really on when the value of the 8 least significant bit is 0, and not just "when the operation calls 0"
The main thing you need to remember is that it is a fixed width integer arithmetic. In an 8-bit register, 0xFF + 1 does produce 0.
In mathematical terms, this is modular arithmetic with a module of 2 8 for an 8-bit operation.
So yes, ZF set according to dst = (dst+src) % 0x100 .
It is designed this way because usually you just want to know if the register is zero, regardless of whether you count to zero with inc in a register that starts with a negative value, or you count to zero with the register that started .
You can check CF==0 and ZF==1 to find a case where you received zero without hyphenation. If ZF was installed only when dst and CF were zero, you would often need another command to simply test the results registry.
If CF and ZF are independent, they mean that unsigned codes after a cmp or sub work as follows:
JA Jump if above (CF=0 and ZF=0). JAE Jump if above or equal (CF=0). JB Jump if below (CF=1). JBE Jump if below or equal (CF=1 or ZF=1). JC Jump if carry (CF=1). JE Jump if equal (ZF=1).
I think that if ZF could only be installed when there was no transfer, you could not distinguish between Above and Above-or-Equal . So, probably, the most specific reason for the design decision should not be made as soon as your first assumption began.
Here is one of the signed comparison conditions:
JLE Jump if less or equal (ZF=1 or SF ≠ OF).
A complete set of conditions is provided in the Intel insn reference manual (links in the x86 tag wiki), in the jcc instruction jcc (jump if condition).