Test
ist wie and
, außer dass es nur FLAGS schreibt und beide Eingänge unverändert lässt. Mit zwei verschiedenen Eingängen ist es nützlich, um zu testen, ob einige Bits alle Null sind oder ob mindestens eines gesetzt ist. (z.B. test al, 3
setzt ZF, wenn EAX ein Vielfaches von 4 ist (und somit beide seiner niedrigen 2 Bits auf Null gesetzt hat).
test eax,eax
setzt alle Flags genau so, wie es cmp eax, 0
würde:
Außer bei AF (Hilfs-Carry-Flag, verwendet von ASCII/BCD-Anweisungen). TEST lässt es undefiniert, aber CMP setzt es "entsprechend dem Ergebnis". Da Subtrahieren von Null keinen Carry vom 4. zum 5. Bit erzeugen kann, sollte CMP AF immer löschen.
TEST ist kleiner (keine Immediate) und manchmal schneller (kann auf mehr CPUs in mehr Fällen in ein Vergleichen-und-Sprung-UOP fusionieren als CMP). Dies macht test
zum bevorzugten Ausdruck für den Vergleich eines Registers mit null. Es ist eine Peephole-Optimierung für cmp reg,0
, die unabhängig von der semantischen Bedeutung verwendet werden kann.
Der einzige häufige Grund für die Verwendung von CMP mit einem Immediate-Wert von 0 ist, wenn Sie gegen eine Speicheroperanden vergleichen möchten. Zum Beispiel cmpb $0, (%esi)
um nach einem Terminierungsnullbyte am Ende eines impliziten C-Style-Strings zu suchen.
AVX512F fügt kortestw k1, k2
hinzu und AVX512DQ/BW (Skylake-X aber nicht KNL) fügen ktestb/w/d/q k1, k2
hinzu, die auf AVX512-Maskenregister (k0..k7) arbeiten, aber immer noch reguläre FLAGS wie test
setzen, genauso wie Ganzzahl-OR
oder AND
Anweisungen. (Ähnlich wie SSE4 ptest
oder SSE ucomiss
: Eingaben im SIMD-Bereich und Ergebnis in Ganzzahl-FLAGS.)
kortestw k1,k1
ist die idiomatische Möglichkeit, basierend auf einem AVX512-Vergleichsergebnis zu verzweigen / cmovcc / setcc, wodurch SSE/AVX2 (v)pmovmskb/ps/pd
+ test
oder cmp
ersetzt werden.
Die Verwendung von jz
vs. je
kann verwirrend sein.
jz
und je
sind buchstäblich dieselbe Anweisung, d.h. dieselbe Opcodes im Maschinencode. Sie tun dasselbe, haben aber unterschiedliche semantische Bedeutung für Menschen. Disassembler (und typischerweise Assemblierungscode von Compilern) werden immer nur eine verwenden, sodass die semantische Unterscheidung verloren geht.
cmp
und sub
setzen ZF, wenn ihre beiden Eingaben gleich sind (d.h. das Subtraktionsergebnis ist 0). je
(springen, wenn gleich) ist das semantisch relevante Synonym.
test %eax,%eax
/ and %eax,%eax
setzt erneut ZF, wenn das Ergebnis Null ist, aber es gibt keinen "Gleichheits"-Test. ZF nach test sagt Ihnen nicht, ob die beiden Operanden gleich waren. Also ist jz
(springen, wenn null) das semantisch relevante Synonym.