使用TEST检查AL的多个位是全部为零还是全部为1

时间:2017-11-29 15:38:35

标签: assembly x86

我想检查AL的第0,3,6,7位是否全部 1 或不是TEST指令。

我知道我可以用这段代码检查第0位:

TEST AL,1

但是如何一起检查0,3,6,7位?

1 个答案:

答案 0 :(得分:2)

你的头衔正在向身体提出相反的问题。对于单个位,它几乎相同(test al,1<<bit_position / jzjnz)。但是当你需要测试多个位时,它们确实是不同的问题。

要检查全零,它仍然很容易,因为当{AND}操作的结果为0时,test设置ZF。所以屏蔽要查看的位在,并检查ZF。请注意,您可以jzjnzsetz/nz alcmovz/nz ecx, edx

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

要检查全部,通常的习惯用语为x & mask == mask。这在asm中并不理想,特别是在立即数不变的情况下,因为andcmp需要两次常量。另一种方法是反转所有位,然后使用前一种方式检查零。 (这为寄存器其他保存代码字节而不是AL,但对于op al, imm8的大多数指令,都有特殊的2字节编码。

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

另一个优化:如果你需要测试EAX的第二个字节中的一些位,它会将代码字节保存为ah,但是this adds a cycle of latency on Haswell/Skylake
例如test eax, 3<<8test ah, 3

对于单个位,bt eax, 11测试第11位(设置/清除CF,因此如果你想取这个位并将其添加到其他地方,你可以做一些像adc edx, 0这样有趣的东西。)但{ {1}}无法与JCC进行宏观融合,因此bt效率更高。

在任何一种情况下,面具都是test eax, imm32 。给定位置中由设置位表示的数字为1<<0 | 1<<3 | 1<<6 | 1<<7,汇编程序常量以数字表示。

当然,您可以用二进制编写常量(例如,在NASM中使用1<<n后缀),这样就可以 b