hanie
hanie

Reputation: 328

Use TEST to check if multiple bits of AL are all zero or all one

I want to check that bits 0, 3, 6, 7 of AL are all 1 or not with TEST instruction.

I know I can check bit 0 with this code:

TEST AL,1

But how can I check bits 0, 3, 6, 7 together?

Upvotes: 3

Views: 2557

Answers (1)

Peter Cordes
Peter Cordes

Reputation: 365832

Your title is asking the opposite question from the body. For a single bit, it's nearly identical (test al,1<<bit_position / jz or jnz). But they're really different problems when you need to test multiple bits.

To check for all zero, it's still easy, because test sets ZF when the result of the AND operation is 0. So mask the bits you want to look at, and check ZF. Remember that you can jz or jnz, or setz/nz al, or cmovz/nz ecx, edx.

test  al, mask
jz   all_bits_selected_by_mask_were_zero
;; fall through path: at least one non-zero bit

To check for all one, the usual idiom is x & mask == mask. This isn't ideal in asm, especially with an immediate constant, because you need the constant twice for and and cmp. The other way is to invert all the bits and then check for zero using the previous way. (This saves code bytes for registers other than AL, but there are special 2-byte encodings for most instructions with op al, imm8)

not   al
test  al, mask
jz   all_bits_selected_by_mask_were_one
;; fall through path: at least one unset bit


;;; or if mask has only a single bit set:
test  al, single_bit_mask
jnz  the_bit_was_set

Another optimization: if you need to test some bits that are all in the 2nd byte of EAX, it saves code bytes to read ah, but this adds a cycle of latency on Haswell/Skylake.
e.g. test eax, 3<<8 vs. test ah, 3.

For a single bit, bt eax, 11 tests bit 11 (setting/clearing CF, so you can do fun stuff like adc edx, 0 if you want to take that bit and add it somewhere else.) But bt can't macro-fuse with JCC, so test eax, imm32 is more efficient.


In either case, the mask is 1<<0 | 1<<3 | 1<<6 | 1<<7 for your case. The number represented by a set bit in given position is 1<<n, and assembler constants are specified in terms of numbers.

Of course, you can write constants in binary (using a b suffix in NASM for example), so you can do test al, 11001001b.

Upvotes: 2

Related Questions