TEST performs the same bit-by-bit AND as the AND instruction, but throws the result away. Neither operand changes; only the flags are set from what the result would have been. It is the instruction for asking "is this bit on?" before a conditional jump.

Reading the flags

AfterMeansJump
ZF = 1none of the tested bits is setJZ / JE
ZF = 0at least one tested bit is setJNZ / JNE
SF = 1the top bit of the result is setJS
CF = OF = 0always

AF is undefined. PF reflects only the low 8 bits of the result, as with every instruction that sets it.

Idioms

TEST AL, 1 then JNZ branches when AL is odd. TEST AL, 80h (or TEST AX, 8000h) looks at the sign bit. TEST AX, AX sets ZF if AX is zero and SF if it is negative, without changing AX; it is the usual way to check a register that was just loaded with MOV, since MOV does not set flags.

Pitfall: several bits

With a mask of more than one bit, ZF=0 means "any of them", not "all of them". TEST AL, 0Ch is non-zero when bit 2 or bit 3 is set. To require both, copy the value, AND it with the mask and compare with the mask:

MOV AH, AL
AND AH, 0Ch
CMP AH, 0Ch ; ZF = 1 only if bits 2 and 3 are both set

A memory operand with an immediate needs a size: TEST BYTE PTR [BX], 1. The example below counts the 1 bits of a byte by testing each bit with a mask that moves left.

Prints 5
MOV AL, 0B5h ; 1011 0101: five 1 bits
MOV BL, 1 ; mask, bit 0 first
XOR BH, BH ; the count
MOV CX, 8
COUNT1:
TEST AL, BL ; AL itself does not change
JZ ZERO1
INC BH
ZERO1:
SHL BL, 1 ; next bit
LOOP COUNT1
MOV AL, BH
ADD AL, "0"
MOV DL, AL
MOV AH, 02h
INT 21h