test
è come and
, tranne che scrive solo FLAGS, lasciando entrambi i suoi input non modificati. Con due diversi ingressi, è utile per verificare se alcuni bit sono tutti nulli o se almeno uno è impostato. (es. test al, 3
imposta ZF se EAX è un multiplo di 4 (e quindi ha entrambi i suoi 2 bit bassi azzerati).
test eax,eax
imposta tutte le bandiere esattamente nello stesso modo in cui cmp eax, 0
avrebbe :
- CF e OF cancellati (AND / TEST lo fa sempre; la sottrazione di zero non produce mai un riporto)
- ZF, SF e PF in base al valore in EAX. (
a = a&a = a-0
).
(PF come al solito è impostato solo in base agli 8 bit bassi )
Fatta eccezione per l'obsoleto AF (flag di trasporto ausiliario, utilizzato dalle istruzioni ASCII / BCD). TEST lo lascia indefinito , ma CMP lo imposta "in base al risultato" . Poiché la sottrazione di zero non può produrre un riporto dal 4 ° al 5 ° bit, CMP dovrebbe sempre cancellare AF.
TEST è più piccolo (non immediato) e talvolta più veloce (può fondersi in macro in un uop di confronto e diramazione su più CPU in più casi rispetto a CMP). Questo rende test
l'idioma preferito per confrontare un registro con lo zero . È un'ottimizzazione dello spioncino cmp reg,0
che puoi utilizzare indipendentemente dal significato semantico.
L'unico motivo comune per utilizzare CMP con uno 0 immediato è quando si desidera confrontare con un operando di memoria. Ad esempio, cmpb $0, (%esi)
per verificare la presenza di uno zero byte di terminazione alla fine di una stringa in stile C di lunghezza implicita.
AVX512F aggiungekortestw k1, k2
e AVX512DQ / BW (Skylake-X ma non KNL) ktestb/w/d/q k1, k2
, che opera sui registri maschera AVX512 (k0..k7) ma imposta comunque FLAG regolari come test
fanno, allo stesso modo degli interi OR
o delle AND
istruzioni. (Un po 'come SSE4 ptest
o SSE ucomiss
: input nel dominio SIMD e risultato in FLAG interi.)
kortestw k1,k1
è il modo idiomatico di branch / cmovcc / setcc basato su un risultato di confronto AVX512, sostituendo SSE / AVX2 (v)pmovmskb/ps/pd
+ test
o cmp
.
L'uso di jz
vs. je
può creare confusione.
jz
e je
sono letteralmente la stessa istruzione , cioè lo stesso codice operativo nel codice macchina. Fanno la stessa cosa, ma hanno un significato semantico diverso per gli esseri umani . I disassemblatori (e in genere l'output asm dai compilatori) ne useranno solo uno, quindi la distinzione semantica è persa.
cmp
e sub
impostare ZF quando i loro due input sono uguali (cioè il risultato della sottrazione è 0). je
(salta se uguale) è il sinonimo semanticamente rilevante.
test %eax,%eax
/ and %eax,%eax
imposta nuovamente ZF quando il risultato è zero, ma non esiste un test di "uguaglianza". ZF dopo il test non ti dice se i due operandi erano uguali. Quindi jz
(salta se zero) è il sinonimo semanticamente rilevante.