Estoy tratando de entender alguna asamblea.
El montaje de la siguiente manera, me interesa la testl
línea:
000319df 8b4508 movl 0x08(%ebp), %eax
000319e2 8b4004 movl 0x04(%eax), %eax
000319e5 85c0 testl %eax, %eax
000319e7 7407 je 0x000319f0
Estoy tratando de entender ese punto testl
entre %eax
y %eax
? Creo que los detalles de lo que este código no es importante, solo estoy tratando de entender la prueba consigo misma, ¿no sería siempre cierto el valor?
assembly
x86
instructions
maxpenguin
fuente
fuente
test
ycmp
. Sí, entiendo que esa es su creencia basada en sus comentarios a Cody. Sin embargo, ponerlo en mi publicación es un asunto diferente; no es una afirmación que esté dispuesta a mantener, simplemente porque no sé si es idéntica en todos los casos.je
,jz
,cmp
, ytest
, y no JE, JZ, CMP, o TEST. Soy así de quisquilloso.test a,a
ycmp $0,a
establecer banderas de manera idéntica; gracias por señalar que se trata de una afirmación no trivial. re: TEST vstest
.: recientemente comencé a usar mayúsculas como los manuales de Intel. Pero cuando hablo de mnemónicos de AT&T frente a mnemónicos de Intel, utilizotestb
estilo para AT&T. IDK si eso ayuda a la legibilidad.El significado de
test
es hacer Y los argumentos juntos, y verificar que el resultado sea cero. Entonces, este código prueba si EAX es cero o no.je
saltará si es cero.Por cierto, esto genera una instrucción más pequeña
cmp eax, 0
que la razón por la que los compiladores generalmente lo hacen de esta manera.fuente
La instrucción de prueba realiza una operación Y lógica entre los operandos pero no escribe el resultado en un registro. Solo se actualizan las banderas.
En su ejemplo, la prueba eax, eax establecerá el indicador cero si eax es cero, el indicador de signo si se establece el bit más alto y también algunos otros indicadores.
La instrucción Jump if Equal (je) salta si se establece el indicador de cero.
Puede traducir el código a un código más legible como este:
Tiene la misma funcionalidad pero requiere algunos bytes más de espacio de código. Esa es la razón por la que el compilador emitió una prueba en lugar de una comparación.
fuente
test eax, eax
ycmp eax, 0
ambos establecen todos los indicadores y los establecen en valores idénticos. Ambas instrucciones establecen todas las banderas "según el resultado". Restar0
nunca puede producir acarreo o desbordamiento. Su argumento es correcto para cualquier inmediato distinto de 0, pero no para 0.test
es comoand
, excepto que solo escribe BANDERAS, dejando ambas entradas sin modificar. Con dos entradas diferentes , es útil para probar si algunos bits son todos cero, o si al menos uno está configurado. (por ejemplo,test al, 3
establece ZF si EAX es un múltiplo de 4 (y por lo tanto tiene ambos bits bajos de 2 en cero).test eax,eax
establece todas las banderas de la misma manera quecmp eax, 0
lo haría :a = a&a = a-0
).(PF, como de costumbre, solo se establece de acuerdo con los 8 bits bajos )
Excepto por el AF obsoleto (indicador de transporte auxiliar, utilizado por las instrucciones ASCII / BCD). TEST lo deja sin definir , pero CMP lo establece "según el resultado" . Dado que restar cero no puede producir un acarreo del cuarto al quinto bit, CMP siempre debe borrar AF.
TEST es más pequeño (no inmediato) y, a veces, más rápido (puede macro-fusionarse en un uop de comparación y ramificación en más CPU en más casos que CMP). Eso lo convierte en
test
el idioma preferido para comparar un registro con cero . Es una optimización de mirillacmp reg,0
que puede utilizar independientemente del significado semántico.La única razón común para usar CMP con un 0 inmediato es cuando desea comparar con un operando de memoria. Por ejemplo,
cmpb $0, (%esi)
para comprobar si hay un byte de terminación cero al final de una cadena de estilo C de longitud implícita.AVX512F agrega
kortestw k1, k2
y AVX512DQ / BW (Skylake-X pero no KNL) agregaktestb/w/d/q k1, k2
, que operan en registros de máscara AVX512 (k0..k7) pero aún establecen BANDERAS regulares como lotest
hacen, de la misma manera que lo hacen los números enterosOR
o lasAND
instrucciones. (Algo así como SSE4ptest
o SSEucomiss
: entradas en el dominio SIMD y dan como resultado BANDERAS enteras).kortestw k1,k1
es la forma idiomática de bifurcar / cmovcc / setcc basada en un resultado de comparación AVX512, reemplazando SSE / AVX2(v)pmovmskb/ps/pd
+test
ocmp
.El uso de
jz
vs.je
puede resultar confuso.jz
yje
son literalmente la misma instrucción , es decir, el mismo código de operación en el código de máquina. Hacen lo mismo, pero tienen un significado semántico diferente para los humanos . Los desensambladores (y generalmente la salida de asm de los compiladores) solo usarán uno, por lo que se pierde la distinción semántica.cmp
ysub
establecer ZF cuando sus dos entradas son iguales (es decir, el resultado de la resta es 0).je
(saltar si es igual) es el sinónimo semánticamente relevante.test %eax,%eax
/and %eax,%eax
nuevamente establece ZF cuando el resultado es cero, pero no hay una prueba de "igualdad". ZF después de la prueba no le dice si los dos operandos eran iguales. Entoncesjz
(saltar si cero) es el sinónimo semánticamente relevante.fuente
test
bit a bitand
, puede no ser obvio para las personas que solo están aprendiendo a ensamblar (y son perezosos / inconscientes para verificar la guía de referencia de instrucciones cada 60 segundos;) :)).kortest*
yktest*
mientras estaba en eso.Este fragmento de código es de una subrutina a la que se le dio un puntero a algo, probablemente alguna estructura u objeto. La segunda línea elimina la referencia de ese puntero, obteniendo un valor de esa cosa, posiblemente en sí mismo un puntero o tal vez solo un int, almacenado como su segundo miembro (desplazamiento +4). Las líneas 3 y 4 prueban este valor para cero (NULL si es un puntero) y omiten las siguientes operaciones (no se muestran) si es cero.
La prueba de cero a veces se codifica como una comparación con un valor cero literal inmediato, pero el compilador (¿o el humano?) Que escribió esto podría haber pensado que una operación de prueba se ejecutaría más rápido, teniendo en cuenta todas las cosas modernas de la CPU como la canalización y el registro. renombrar. Es de la misma bolsa de trucos que sostiene la idea de borrar un registro con XOR EAX, EAX (¡que vi en la matrícula de alguien en Colorado!) En lugar del obvio pero quizás más lento MOV EAX, # 0 (uso una notación anterior ).
En asm, como perl, TMTOWTDI.
fuente
Si eax es cero, realizará el salto condicional, de lo contrario continuará la ejecución en 319e9
fuente
En algunos programas, se pueden utilizar para comprobar si hay un desbordamiento del búfer. En la parte superior del espacio asignado se coloca un 0. Después de ingresar datos en la pila, busca el 0 al comienzo del espacio asignado para asegurarse de que el espacio asignado no se desborde.
Se usó en el ejercicio stack0 de exploits-ejercicios para verificar si estaba desbordado y si no lo había y había un cero allí, mostraría "Intentar de nuevo"
fuente
cmp DWORD PTR [esp+0x5c], 0
/jz 0x8048427 <main+51>
hubiera sido más eficiente que una carga MOV separada y luego TEST. Este no es un caso de uso común para verificar un cero.podríamos ver jg , jle Si
testl %edx,%edx. jle .L3
pudiéramos encontrar fácilmente jle es adecuado(SF^OF)|ZF
, si% edx es cero, ZF = 1, pero si% edx no es cero y es -1, después de la prueba, OF = 0 y SF = 1, entonces la bandera = verdadera, que implementa salto. Lo siento, mi inglés es pobrefuente