В C++ условие выглядит привычно:.
Ниже — разделы про cMP: сравнить, jE: перейти, если равно и jMP: безусловный переход, чтобы быстро понять устройство материала, практические ограничения и типовые точки отказа.
В C++ условие выглядит привычно:
if (value == 10) {
result = 1;
} else {
result = 0;
}
В ассемблере нет такого красивого if. Есть сравнение, флаги и переходы. Именно здесь появляются CMP, JMP, JE, JNZ
- CMP: сравнить
- JE: перейти, если равно
- JMP: безусловный переход
- if/else на ассемблере
- JNZ: перейти, если не ноль
- Цикл через JNZ
- Почему порядок команд важен
- CMP против TEST
- Частые ошибки
- Метка написана с опечаткой
- Забыли jmp после else-блока
- Думают, что cmp меняет значение
- Вставили флаг-меняющую команду перед переходом
- Мини-задания
- Ответы на эти вопросы могут быть для вас полезными
- Что делает CMP?
- Чем JMP отличается от JE?
- Что значит JNZ?
- Как сделать цикл в ассемблере?
- Почему код после CMP ведет себя странно?
- Что почитать дальше по ассемблеру
CMP: сравнить
cmp ax, 10
cmp сравнивает ax с 10 и выставляет флаги. Сам ax не меняется
Если ax равен 10, будет выставлен флаг нуля, и переход je сможет сработать
JE: перейти, если равно
mov ax, 10
cmp ax, 10
je equal_label
Если значения равны, выполнение перейдет на метку equal_label
Метка:
equal_label:
Метка — это имя места в коде
JMP: безусловный переход
jmp end
jmp переходит всегда. Он не проверяет флаги
В условной конструкции он нужен, чтобы перепрыгнуть блок else
if/else на ассемблере
mov ax, 10
cmp ax, 10
je equal_label
mov bx, 0
jmp end
equal_label:
mov bx, 1
end:
Логика:
- если
ax == 10, перейти кequal_label; - иначе положить 0 в
bx; - после
equal_labelположить 1 вbx.
Это похоже на:
if (ax == 10) {
bx = 1;
} else {
bx = 0;
}
JNZ: перейти, если не ноль
jnz означает jump if not zero
После cmp его часто используют как "перейти, если не равно":
cmp ax, 10
jnz not_equal
Если результат сравнения не ноль, значения разные
jne и jnz во многих x86-контекстах являются близкими по смыслу для такой проверки
Цикл через JNZ
Сделаем счетчик от 3 до 1:
mov cx, 3
loop_start:
sub cx, 1
cmp cx, 0
jnz loop_start
Что происходит:
- В
cxкладем 3. - Вычитаем 1.
- Сравниваем с 0.
- Если не ноль, возвращаемся к началу.
Проходы:
cx = 3 -> sub -> 2 -> не ноль
cx = 2 -> sub -> 1 -> не ноль
cx = 1 -> sub -> 0 -> выход
Почему порядок команд важен
Так правильно:
cmp cx, 0
jnz loop_start
Если между cmp и jnz вставить команду, которая меняет флаги, переход будет смотреть уже не на то сравнение
Например:
cmp cx, 0
add ax, 1
jnz loop_start
add может изменить флаги. Это уже опасная логика
CMP против TEST
test часто используют для проверки нуля:
test ax, ax
jnz not_zero
Но для первого урока достаточно cmp:
cmp ax, 0
jnz not_zero
test можно добавить позже
Частые ошибки
Метка написана с опечаткой
je equl_label
А ниже:
equal_label:
Assembler не найдет метку
Забыли jmp после else-блока
Если не перепрыгнуть equal_label, может выполниться оба блока
Думают, что cmp меняет значение
Не меняет. Он меняет флаги
Вставили флаг-меняющую команду перед переходом
Переход смотрит на последние актуальные флаги
Мини-задания
- Проверь, равно ли
axчислу 5. - Если равно, положи в
bx100. - Если не равно, положи в
bx0. - Сделай цикл, который уменьшает
cxот 5 до 0. - Попробуй заменить
jnzнаjeи объяснить, что изменилось.
Ответы на эти вопросы могут быть для вас полезными
Что делает CMP?
Сравнивает значения и выставляет флаги, но не сохраняет результат вычитания
Чем JMP отличается от JE?
JMP переходит всегда. JE переходит только если предыдущее сравнение показало равенство
Что значит JNZ?
Jump if not zero — перейти, если результат не ноль
Как сделать цикл в ассемблере?
Через метку, изменение счетчика, сравнение и условный переход назад
Почему код после CMP ведет себя странно?
Возможно, между cmp и переходом есть команда, которая изменила флаги
Что почитать дальше по ассемблеру
Если вы собираете тему по шагам, рядом лучше открыть:
- Регистры и флаги процессора простыми словами — понять, какие флаги читает условный переход.
- Ассемблер для чайников: первый код без страха — повторить mov, add, sub и cmp перед ветвлениями.
- Hello World на ассемблере: зачем он сложнее, чем в C++ — добавить условия к более настоящей программе.
- i8080, AVR и STM32 на ассемблере: когда идти в нишевые ветки — увидеть, почему переходы отличаются на других архитектурах.



