Ассемблер
CMP asm: что делает инструкция сравнения
cmp в asm — это инструкция сравнения. Она берет два операнда, выполняет внутреннее вычитание, не сохраняет результат и обновляет флаги процессора. После нее обычно ставят условный переход: je, jne, jl, jg, jb, ja
В NASM/Intel-синтаксисе пример выглядит так:
cmp eax, 10
je equal
В AT&T-синтаксисе, который часто встречается в выводе GCC/GDB на Linux, порядок записи другой:
cmpl $10, %eax
je equal
Обе записи сравнивают значение регистра eax с числом 10, но синтаксис отличается
Синтаксис в Intel/NASM
cmp регистр, значение
cmp регистр, регистр
cmp память, регистр
cmp регистр, память
Примеры:
cmp eax, 0
cmp eax, ebx
cmp byte [flag], 1
cmp qword [rbp-8], 100
В Intel-синтаксисе первый операнд часто воспринимают как левую часть сравнения: cmp eax, ebx означает сравнить eax с ebx
Синтаксис в AT&T
AT&T-синтаксис пишет источник перед назначением и добавляет размер в имя инструкции:
cmpb $1, -1(%rbp)
cmpl $10, %eax
cmpq %rax, %rbx
Суффиксы:
b— byte, 1 байт;w— word, 2 байта;l— long, 4 байта;q— quad, 8 байт.
Запись:
cmpl $10, %eax
означает сравнить 32-битное значение eax с 10
Какие флаги меняет cmp
После cmp особенно важны:
ZF— значения равны;CF— нужен для unsigned-сравнений;SF— знак результата;OF— переполнение для signed-сравнений.
Сами регистры не меняются. Если было:
mov eax, 4
cmp eax, 9
после cmp в eax все равно 4
Как выбрать переход
Для равенства:
cmp eax, ebx
je equal
jne not_equal
Для signed-сравнения:
cmp eax, ebx
jl less
jg greater
Для unsigned-сравнения:
cmp eax, ebx
jb below
ja above
Если вы сравниваете обычные положительные счетчики массива, часто нужны unsigned-переходы. Если сравниваете числа, которые могут быть отрицательными, нужны signed-переходы
Пример: проверка диапазона
Пусть в eax лежит возраст. Нужно проверить, что он от 18 и выше:
cmp eax, 18
jl too_young
mov ebx, 1
jmp done
too_young:
mov ebx, 0
done:
Такой код использует jl, потому что возраст записан как обычное знаковое число. Если значение гарантированно неотрицательное, можно использовать и unsigned-логику, но в учебных примерах signed-переход легче объяснить
Частые ошибки в cmp asm
Считать cmp полноценным if
cmp только готовит флаги. Сам выбор делает следующая команда
Забыть, что порядок важен
cmp eax, ebx и cmp ebx, eax дают разные флаги для «меньше» и «больше»
Смешать синтаксисы
Такой код не является нормальной одной записью:
cmp %eax, 10
Либо пишите NASM/Intel, либо AT&T
Использовать переход не того типа
jl и jb не одно и то же. Первый для signed, второй для unsigned
Что почитать дальше по ассемблеру
Если нужен общий маршрут по теме, откройте рубрику ассемблеру. Для соседних задач пригодятся эти разборы:
- CPI в ассемблере: что делает инструкция
- CMP в ассемблере
- CMP в ассемблере: как работает сравнение
- CMP, JMP, JE, JNZ: условия и циклы в ассемблере