Регистр флагов: ноль, знак, перенос

Урок объясняет регистр флагов: маленькие биты-индикаторы, по которым процессор принимает решения.

Флаг — отдельный бит в регистре RFLAGS, который автоматически выставляется по результату операции (например, «получился ноль»).

Зачем нужны флаги

В процессоре нет команды «если». Вместо этого почти каждая арифметическая операция и сравнение оставляют после себя «следы» в RFLAGS, а условные переходы потом смотрят на эти следы. Это разделение — ключ к тому, как из плоского кода получаются ветвления.

Четыре главных флага

ФлагИмяКогда выставлен
ZFZeroрезультат равен нулю
SFSignрезультат отрицательный (старший бит = 1)
CFCarryбыл перенос за пределы разрядности (беззнаковое переполнение)
OFOverflowзнаковое переполнение

Как сравнение пользуется флагами

Команда cmp a, b вычитает b из a, но не сохраняет результат — она только выставляет флаги. Если a == b, разность равна нулю и ZF = 1. На этом построены все условия:

mov rax, 5
cmp rax, 5      ; 5 - 5 = 0  -> ZF = 1
je  equal       ; je = jump if equal, прыгает если ZF = 1

Как работает под капотом

Сэмулируем логику флагов на Python для 8-битного сложения, где перенос виден наглядно:

def add8(a, b):
    res = a + b
    cf = 1 if res > 0xFF else 0   # перенос за 8 бит
    res8 = res & 0xFF
    zf = 1 if res8 == 0 else 0
    sf = 1 if res8 & 0x80 else 0
    return res8, zf, sf, cf

res, zf, sf, cf = add8(200, 100)
print("res =", res, "ZF =", zf, "SF =", sf, "CF =", cf)

Вывод:

res = 44 ZF = 0 SF = 0 CF = 1

200 + 100 = 300, но в 8 бит влезает только 44 (300 − 256), а флаг переноса CF честно сообщает, что число «вылезло» за разрядность. Точно так же реальный процессор отмечает беззнаковое переполнение.

Частые ошибки

  • Думать, что cmp что-то сохраняет. Она только выставляет флаги; сам результат вычитания выбрасывается.
  • Путать CF и OF. CF — переполнение для беззнаковых, OF — для знаковых чисел. Разные условия используют разные флаги.
  • Вставлять команды между сравнением и переходом. Многие команды (например, mov флаги не трогает, а add трогает) могут испортить флаги до перехода.

Итог

  • Флаги в RFLAGS — биты-индикаторы результата операции.
  • Главные: ZF (ноль), SF (знак), CF (беззнаковое переполнение), OF (знаковое).
  • cmp a, b вычитает, не сохраняя результат, и только выставляет флаги.
  • Условные переходы читают флаги — так получаются ветвления.
Проверьте себя
1. Что делает команда cmp rax, rbx?
AСкладывает регистры и сохраняет в rax
BВычитает rbx из rax, не сохраняя результат, но выставляя флаги
CКопирует rbx в rax
DСравнивает и печатает результат
2. Когда выставляется флаг ZF?
AКогда результат отрицательный
BКогда был перенос
CКогда результат равен нулю
DКогда операнды равны по размеру
3. Чем CF отличается от OF?
ACF для беззнакового переполнения, OF для знакового
BCF для сложения, OF для вычитания
CОни идентичны
DCF только для регистра rax