Ассемблер
CPI в ассемблере: что делает инструкция
CPI в ассемблере обычно означает Compare Immediate — сравнить аккумулятор с непосредственным значением. Такая инструкция встречается в i8080/Z80-подобном контексте. Она не записывает результат вычитания обратно в аккумулятор, а только выставляет флаги, по которым затем выполняют условный переход
Простая идея
Если очень коротко:
CPI 10h
означает: сравнить значение в аккумуляторе A с числом 10h. Процессор внутренне делает что-то похожее на:
A - 10h
Но A остается прежним. Меняются флаги
Какие флаги важны
После CPI обычно смотрят:
Z— zero flag, равны ли значения;C— carry flag, был ли заем при сравнении;S— sign flag, знак результата;P/Vили parity/overflow в зависимости от процессора;- вспомогательный перенос, если он есть в данной архитектуре.
Для новичка самые важные флаги — Z и C
Если A == число, флаг Z будет установлен. Если A < число в беззнаковом смысле, обычно появляется заем, и это отражается через carry
Пример с переходом
Допустим, в аккумуляторе лежит код клавиши или число:
CPI 05h
JZ equal
JC less
Что здесь происходит:
CPI 05hсравниваетAс05h;JZ equalперейдет наequal, еслиAравно05h;JC lessперейдет наless, если при сравнении был заем, то естьAменьше05hдля беззнакового сравнения.
Сам аккумулятор после CPI не меняется. Это главное отличие от реального вычитания, где результат записывается в регистр
Чем CPI отличается от CMP
В похожих архитектурах CMP часто сравнивает аккумулятор с регистром или памятью, а CPI — с числом, которое прямо записано в инструкции
Условно:
CMP B
CPI 20h
Первое сравнивает A с регистром B, второе — A с числом 20h
Как читать CPI в чужом коде
Когда видите CPI, сразу смотрите следующую инструкцию. Почти всегда после сравнения идет переход:
CPI 00h
JZ done
Это читается так: если аккумулятор равен нулю, перейти на done
Если после CPI идет несколько условных переходов, код проверяет разные варианты результата сравнения: равно, меньше, больше или не равно
Частые ошибки
Думают, что CPI меняет аккумулятор
Нет. CPI сравнивает и меняет флаги, но значение A остается
Игнорируют архитектуру
В x86 нет такой же инструкции CPI в обычном учебном смысле. Там чаще используют cmp
Не смотрят на следующий переход
CPI сам по себе только готовит флаги. Решение принимает следующая условная инструкция
Путают знаковое и беззнаковое сравнение
Для простых байтовых значений обычно думают в беззнаковом смысле, но в конкретном процессоре нужно смотреть описание флагов
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- CMP asm: что делает инструкция сравнения
- Инструкция на ассемблере: как понять -12(%rbp)
- CMP в ассемблере
- CMP в ассемблере: как работает сравнение
Как проверить результат на практике
Для ассемблера важно сначала понять, под какую среду написан пример: DOSBox/TASM, Linux x64/NASM, Visual Studio/MASM или микроконтроллер. Один и тот же смысл может записываться разным синтаксисом, поэтому не переносите команды между средами вслепую. Создайте отдельную папку для примера, сохраните файл с расширением .asm, выполните сборку именно тем инструментом, который указан в уроке, и сравните вывод или состояние регистров с ожидаемым результатом
Если пример не собирается, читайте первую ошибку ассемблера: обычно она указывает на строку, неизвестную инструкцию, неверную метку, неправильную секцию или конфликт синтаксиса. Исправляйте одну ошибку за раз. В ассемблере это особенно важно, потому что маленькая опечатка в метке, регистре или размере операнда может полностью изменить поведение программы