Ассемблер
CMP в ассемблере
CMP в ассемблере используют для сравнения двух значений. Инструкция работает как проверочное вычитание: выставляет флаги процессора, но не сохраняет результат и не меняет операнды. Поэтому cmp почти всегда читают вместе со следующей командой условного перехода
Базовая запись:
cmp eax, ebx
je equal
Если eax и ebx равны, переход je equal сработает. Если не равны, выполнение пойдет дальше
Синтаксис CMP
В Intel/NASM-синтаксисе:
cmp левый_операнд, правый_операнд
Примеры:
cmp eax, 0
cmp eax, ebx
cmp byte [flag], 1
cmp dword [rbp-4], 10
Операнды должны быть совместимыми по размеру. Если сравниваете байт, указывайте байт. Если сравниваете 32-битное значение, используйте 32-битный регистр или явный размер памяти
Пример проверки равенства
mov eax, 42
cmp eax, 42
je answer
mov ebx, 0
jmp done
answer:
mov ebx, 1
done:
После cmp eax, 42 процессор выставит ZF, потому что значения равны. Переход je означает «jump if equal»
Пример проверки неравенства
cmp eax, 0
jne not_zero
Если eax не равен нулю, переход выполнится. jne и jnz часто используются как близкие варианты после cmp: не равно и не ноль
Больше и меньше
Для знаковых чисел:
cmp eax, ebx
jl less
jg greater
Для беззнаковых чисел:
cmp eax, ebx
jb below
ja above
Если вы сравниваете -1 и 1, signed и unsigned логика дадут разный смысл. В 32-битном виде -1 — это FFFFFFFFh, а как unsigned это огромное положительное число
Порядок операндов
cmp eax, ebx и cmp ebx, eax — разные проверки для «меньше» и «больше»
cmp eax, ebx
jl eax_less_than_ebx
читается как:
если eax меньше ebx
Если поменять операнды местами, условие изменится
CMP в цикле
mov ecx, 0
loop_start:
add ecx, 1
cmp ecx, 10
jl loop_start
Пока ecx < 10, цикл возвращается к loop_start. Как только ecx станет 10, переход jl больше не сработает
CMP и TEST
Для проверки нуля можно писать:
cmp eax, 0
je zero
Можно встретить и так:
test eax, eax
je zero
test часто компактнее для проверки нуля, но cmp проще для понимания, потому что явно сравнивает с конкретным значением
Частые ошибки
Думают, что CMP меняет операнд
После cmp eax, 5 значение eax остается прежним
Сравнивают память с памятью
На x86 многие формы не позволяют напрямую сравнить два адреса памяти. Обычно одно значение сначала загружают в регистр
Смешивают signed и unsigned переходы
Запомните: jl/jg для signed, jb/ja для unsigned
Меняют флаги между CMP и переходом
Ставьте переход сразу после сравнения, пока не уверены в каждой инструкции
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- CMP в ассемблере: как работает сравнение
- CMP, JMP, JE, JNZ: условия и циклы в ассемблере
- Как работает CMP в ассемблере
- Что такое CMP в ассемблере