test
похож на and
, за исключением того, что он записывает только флаги, оставляя оба своих ввода неизмененными. С двумя различными входами полезно проверять, все ли биты равны нулю, или установлен хотя бы один из них. (например, test al, 3
устанавливает ZF, если EAX кратно 4 (и поэтому оба его младших 2 бита обнуляются).
test eax,eax
устанавливает все флаги точно так же, как cmp eax, 0
будет :
- CF и OF очищены (AND / TEST всегда так делает; вычитание нуля никогда не приводит к переносу)
- ZF, SF и PF в соответствии со значением в EAX. (
a = a&a = a-0
)
(За исключением устаревшего AF (флаг вспомогательного переноса, используемый командами ASCII / BCD). TEST оставляет его неопределенным , но CMP устанавливает его "в соответствии с результатом" Поскольку вычитание нуля не может привести к переносу с 4-го по 5-й бит, CMP всегда должен очищать AF).
TEST меньше (не немедленный), а иногда и быстрее (может слиться макросом в моп со сравнением и ветвлением на большем количестве процессоров в большем количестве случаев, чем CMP). Это делает test
предпочтительной идиомой для проверки регистра на ноль или нет .
Единственная распространенная причина использования CMP с немедленным 0 - это когда вы хотите сравнить с операндом памяти (например, cmpb $0, (%esi)
, чтобы проверить завершающий нулевой байт в конце строки C-стиля неявной длины ).
AVX512F добавляет kortestw k1, k2
и AVX512DQ / BW (Skylake, но не KNL) add ktestb/w/d/q k1, k2
, которые работают с регистрами маски AVX512 (k0. .k7), но все равно устанавливают обычные флаги, как test
, так же, как это делают целочисленные OR
или AND
инструкции.
kortestw k1,k1
- идиоматический способ ветвления / cmovcc / setcc на основе результата сравнения AVX512, заменяющий SSE / AVX2 (v)pmovmskb/ps/pd
+ test
или cmp
.
Использование jz
против je
может сбить с толку.
jz
и je
- это буквально одна и та же инструкция , то есть один и тот же код операции в машинном коде. Они делают одно и то же, но имеют разное семантическое значение для людей . Дизассемблеры (и, как правило, выходные данные asm из компиляторов) будут использовать только один, поэтому семантическое различие потеряно.
cmp
и sub
устанавливают ZF, когда их два входа равны (то есть результат вычитания равен 0). je
(переход, если равен) является семантически значимым синонимом.
test %eax,%eax
/ and %eax,%eax
снова устанавливает ZF, когда результат равен нулю, но нет теста на "равенство". ZF после теста не сообщает, были ли оба операнда равны. Так что jz
(переход на ноль) является семантически релевантным синонимом.