Вот как это работает:
Рассмотрим два байтовых значения 0x65 и 0x31. Оба они являются значениями без знака, независимо от того, смотрите ли вы на них с точки зрения знака или без знака.
Затем вы добавляете их:
0x65 + 0x31 становится 0x96, что хорошо с точки зрения без знака (сумма помещается в байт, поэтому флаг переноса не был установлен). Однако из представления со знаком добавление двух положительных чисел привело к отрицательному числу, следовательно, были установлены флаги переполнения и знака. Фактически, для всех чисел со знаком установлен флаг переполнения, если старший бит изменяется в результате операции, в противном случае он очищается.
Вы можете видеть это так, как будто процессор выполняет две операции для каждой инструкции, устанавливая соответствующие флаги как для неподписанного, так и для подписанного добавления. После этого компилятор (или программист сборки) должен решить, является ли условная ветвь без знака (используя флаги ноль и перенос) или условной веткой со знаком (используя флаги ноль, знак и переполнение).
Так какой смысл?
Дело в том, что если бы это не было сделано таким образом, процессору потребовался бы один набор инструкций для подписанных операций (которые влияют только на флаги обнуления, знака и переполнения) и другой для операций без знака (влияющих на ноль и перенос) .