test
est comme and
, sauf qu'il n'écrit que des FLAGS, laissant ses deux entrées inchangées. Avec deux entrées différentes , il est utile pour tester si certains bits sont tous à zéro ou si au moins un est défini. (par exemple, test al, 3
définit ZF si EAX est un multiple de 4 (et a donc tous les deux ses deux bits inférieurs à zéro).
test eax,eax
définit tous les drapeaux de la même manière que le cmp eax, 0
ferait :
- CF et OF effacés (AND / TEST fait toujours cela; soustraire zéro ne produit jamais de report)
- ZF, SF et PF selon la valeur en EAX. (
a = a&a = a-0
).
(PF comme d'habitude n'est défini qu'en fonction des 8 bits bas )
Sauf pour l'AF obsolète (indicateur de report auxiliaire, utilisé par les instructions ASCII / BCD). TEST le laisse indéfini , mais CMP le définit "en fonction du résultat" . Étant donné que la soustraction de zéro ne peut pas produire de report du 4ème au 5ème bit, CMP doit toujours effacer AF.
TEST est plus petit (pas immédiat) et parfois plus rapide (peut macro-fusionner en un uop de comparaison et de branchement sur plus de processeurs dans plus de cas que CMP). Cela fait de test
l'idiome préféré pour comparer un registre à zéro . C'est une optimisation de judas cmp reg,0
que vous pouvez utiliser quelle que soit la signification sémantique.
La seule raison courante d'utiliser CMP avec un 0 immédiat est lorsque vous souhaitez effectuer une comparaison avec un opérande mémoire. Par exemple, cmpb $0, (%esi)
pour rechercher un octet de fin de zéro à la fin d'une chaîne de style C de longueur implicite.
AVX512F ajoutekortestw k1, k2
et AVX512DQ / BW (Skylake-X mais pas KNL) ajoute ktestb/w/d/q k1, k2
, qui fonctionnent sur les registres de masque AVX512 (k0..k7) mais définissent toujours des FLAGs réguliers comme le test
font, de la même manière que les entiers OR
ou les AND
instructions. (Un peu comme SSE4 ptest
ou SSE ucomiss
: les entrées dans le domaine SIMD et aboutissent à des FLAGS entiers.)
kortestw k1,k1
est la manière idiomatique de créer un branchement / cmovcc / setcc basé sur un résultat de comparaison AVX512, en remplaçant SSE / AVX2 (v)pmovmskb/ps/pd
+ test
ou cmp
.
L'utilisation de jz
vs. je
peut être déroutante.
jz
et je
sont littéralement la même instruction , c'est-à-dire le même opcode dans le code machine. Ils font la même chose, mais ont une signification sémantique différente pour les humains . Les désassembleurs (et généralement la sortie asm des compilateurs) n'en utiliseront qu'un seul, donc la distinction sémantique est perdue.
cmp
et sub
définissez ZF lorsque leurs deux entrées sont égales (c'est-à-dire que le résultat de la soustraction est 0). je
(jump if equal) est le synonyme sémantiquement pertinent.
test %eax,%eax
/ and %eax,%eax
définit à nouveau ZF lorsque le résultat est nul, mais il n'y a pas de test "d'égalité". ZF après le test ne vous dit pas si les deux opérandes étaient égaux. Donc jz
(sauter si zéro) est le synonyme sémantiquement pertinent.