test就像and,除了它只写 FLAGS ,而它的两个输入都保持不变。对于两个不同的输入,它对于测试某些位是否全为零或是否至少设置了一个很有用。(例如test al, 3,如果 EAX 是 4 的倍数,则设置 ZF(因此它的低 2 位都归零)。
test eax,eax以完全相同的方式设置所有cmp eax, 0标志:
- CF 和 OF 清零(AND/TEST 总是这样做;减去零永远不会产生进位)
- ZF、SF 和 PF 根据 EAX 中的值。(
a = a&a = a-0)。
(PF照常只根据低8位设置)
除了过时的 AF(辅助进位标志,由 ASCII/BCD 指令使用)。 TEST 将其保留为 undefined,但CMP 将其设置为“根据结果”。由于减零不能产生从第 4 位到第 5 位的进位,CMP 应始终清除 AF。
TEST 更小(不立即),有时更快(可以在比 CMP 更多的情况下在更多 CPU 上宏融合到比较和分支微指令中)。 这使得test将寄存器与零进行比较的首选习语。这是一个窥视孔优化,cmp reg,0无论语义如何,您都可以使用它。
使用立即数为 0 的 CMP 的唯一常见原因是当您想与内存操作数进行比较时。例如,cmpb $0, (%esi)检查隐式长度 C 样式字符串末尾的终止零字节。
AVX512F addkortestw k1, k2和 AVX512DQ/BW (Skylake-X 但不是 KNL) add ktestb/w/d/q k1, k2,它们在 AVX512 掩码寄存器 (k0..k7) 上运行,但仍然像test整数OR或AND指令一样设置常规 FLAGS。(有点像 SSE4ptest或 SSE ucomiss:在 SIMD 域中输入并产生整数 FLAGS。)
kortestw k1,k1是基于 AVX512 比较结果分支 / cmovcc / setcc 的惯用方式,替换 SSE/AVX2 (v)pmovmskb/ps/pd+test或cmp.
jzvs.的使用je可能会令人困惑。
jz并且je实际上是相同的指令,即机器代码中的相同操作码。 它们做同样的事情,但对人类有不同的语义。反汇编程序(通常是编译器的 asm 输出)只会使用一个,因此语义区别会丢失。
cmp并sub在它们的两个输入相等(即减法结果为0)时设置ZF。 je(jump if equal) 是语义相关的同义词。
test %eax,%eax/and %eax,%eax当结果为零时再次设置 ZF,但没有“相等”测试。测试后的 ZF 不会告诉您两个操作数是否相等。所以jz(jump if zero) 是语义相关的同义词。