test
подобен and
, за исключением того, что он записывает только FLAGS, оставляя оба входа неизмененными. С двумя разными входами это полезно для проверки, все ли некоторые биты равны нулю или установлен хотя бы один. (например, test al, 3
устанавливает ZF, если EAX кратно 4 (и, таким образом, оба младших бита обнулены).
test eax,eax
устанавливает все флаги точно так же, как если cmp eax, 0
бы :
За исключением устаревшего AF (флаг вспомогательного переноса, используемый инструкциями ASCII / BCD). TEST оставляет его неопределенным , но CMP устанавливает его «в соответствии с результатом» . Поскольку вычитание нуля не может привести к переносу с 4-го на 5-й бит, CMP всегда должен очищать AF.
ТЕСТ меньше (не сразу), а иногда и быстрее (может макрослиться в муп сравнения и ветвления на большем количестве процессоров в большем количестве случаев, чем CMP). Это делает test
предпочтительную идиому для сравнения регистра с нулем . Это оптимизация на глазок cmp reg,0
, которую можно использовать независимо от семантического значения.
Единственная распространенная причина использования CMP с немедленным 0 - это когда вы хотите сравнить с операндом памяти. Например, cmpb $0, (%esi)
чтобы проверить завершающий нулевой байт в конце строки C-стиля неявной длины.
AVX512F добавляетkortestw k1, k2
и добавляет AVX512DQ / BW (Skylake-X, но не KNL) ktestb/w/d/q k1, k2
, которые работают с регистрами маски AVX512 (k0..k7), но по-прежнему устанавливают обычные ФЛАГИ, как это test
делается, точно так же, как это делают целые числа OR
или AND
инструкции. (Что-то вроде SSE4 ptest
или SSE ucomiss
: входы в домен SIMD и результат целочисленные флаги.)
kortestw k1,k1
- это идиоматический способ ветвления / cmovcc / setcc на основе результата сравнения AVX512, заменяющий SSE / AVX2 (v)pmovmskb/ps/pd
+ test
или cmp
.
Использование jz
vs. je
может сбивать с толку.
jz
и je
представляют собой буквально одну и ту же инструкцию , то есть один и тот же код операции в машинном коде. Они делают то же самое, но имеют разное смысловое значение для людей . Дизассемблеры (и обычно вывод asm из компиляторов) будут всегда использовать только один, поэтому семантическое различие теряется.
cmp
и sub
установите ZF, когда их два входа равны (т.е. результат вычитания равен 0). je
(переход, если равно) - семантически значимый синоним.
test %eax,%eax
/ and %eax,%eax
снова устанавливает ZF, когда результат равен нулю, но нет проверки на «равенство». ZF после теста не сообщает вам, равны ли два операнда. Итак jz
(переход, если ноль) - это семантически значимый синоним.