test
é semelhante and
, exceto que apenas grava FLAGS, deixando ambas as entradas inalteradas. Com duas entradas diferentes , é útil para testar se alguns bits são todos zero ou se pelo menos um está definido. (por exemplo:test al, 3
define ZF se EAX é um múltiplo de 4 (e, portanto, tem ambos os 2 bits inferiores zerados).
test eax,eax
define todos os sinalizadores exatamente da mesma maneira que cmp eax, 0
faria :
Exceto para o AF obsoleto (sinalizador de transporte auxiliar, usado pelas instruções ASCII / BCD). TEST deixa indefinido , mas CMP o configura "de acordo com o resultado" . Uma vez que subtrair zero não pode produzir um transporte do 4º para o 5º bit, o CMP deve sempre limpar o AF.
TEST é menor (não imediato) e às vezes mais rápido (pode fundir macro em um uop de comparação e ramificação em mais CPUs em mais casos do que CMP). Isso torna test
o idioma preferido para comparar um registro com zero . É uma otimização de olho mágico paracmp reg,0
que você pode usar independentemente do significado semântico.
O único motivo comum para usar CMP com um 0 imediato é quando você deseja comparar com um operando de memória. Por exemplo, cmpb $0, (%esi)
para verificar se há um byte zero de terminação no final de uma string estilo C de comprimento implícito.
AVX512F adicionakortestw k1, k2
e AVX512DQ / BW (Skylake-X mas não KNL) adiciona ktestb/w/d/q k1, k2
, que opera em registradores de máscara AVX512 (k0..k7), mas ainda define FLAGS regulares como test
faz, da mesma forma que inteiros OR
ou AND
instruções fazem. (Mais ptest
ou menos como SSE4 ou SSEucomiss
: entradas no domínio SIMD e resultam em FLAGS inteiros.)
kortestw k1,k1
é a maneira idiomática de ramificar / cmovcc / setcc com base em um resultado de comparação AVX512, substituindo SSE / AVX2 (v)pmovmskb/ps/pd
+ test
ou cmp
.
O uso de jz
vs. je
pode ser confuso.
jz
e je
são literalmente a mesma instrução , ou seja, o mesmo opcode no código de máquina. Eles fazem a mesma coisa, mas têm significados semânticos diferentes para humanos . Os desmontadores (e normalmente a saída do conjunto de compiladores) usarão apenas um, portanto, a distinção semântica é perdida.
cmp
e sub
defina ZF quando suas duas entradas forem iguais (ou seja, o resultado da subtração é 0). je
(pule se for igual) é o sinônimo semanticamente relevante.
test %eax,%eax
/ and %eax,%eax
novamente define ZF quando o resultado é zero, mas não há teste de "igualdade". ZF após o teste não informa se os dois operandos eram iguais. Portanto, jz
(pule se zero) é o sinônimo semanticamente relevante.