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.
Использование jzvs. jeможет сбивать с толку.
jzи jeпредставляют собой буквально одну и ту же инструкцию , то есть один и тот же код операции в машинном коде. Они делают то же самое, но имеют разное смысловое значение для людей . Дизассемблеры (и обычно вывод asm из компиляторов) будут всегда использовать только один, поэтому семантическое различие теряется.
cmpи subустановите ZF, когда их два входа равны (т.е. результат вычитания равен 0). je(переход, если равно) - семантически значимый синоним.
test %eax,%eax/ and %eax,%eaxснова устанавливает ZF, когда результат равен нулю, но нет проверки на «равенство». ZF после теста не сообщает вам, равны ли два операнда. Итак jz(переход, если ноль) - это семантически значимый синоним.