Reputation: 328
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
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