assembly - Instrucciones de montaje de JNZ & CMP
x86 reverse-engineering (4)
Corrígeme si estoy equivocado.
Este es mi entendimiento de JNZ
y CMP
.
JNZ
: el salto se llevará a cabo si el indicador Z
NO es cero (1)
CMP
: si los dos valores son iguales, el indicador Z
se establece (1), de lo contrario no se establece (0)
Este es un tutorial flash que estoy viendo. Es enseñar la solución a un simple CrackMe.
Como se puede ver, la instrucción anterior comparó AL
con 47h
. Eran iguales los que ponían la bandera Z
. (Puedes verlo en la ventana de Registros en el lado derecho)
La siguiente instrucción es un JNZ
. Mi entendimiento fue que el salto se llevará a cabo si se establece la bandera Z
La bandera Z
está activada, ¡pero el salto no tiene lugar!
¿Por qué?
Al principio, parece que JNZ significa saltar si no es cero (0), como en saltar si el indicador cero es 1 / set.
Pero en realidad significa Saltar (si) no Cero (está configurado).
Si 0 = no establecido y 1 = establecido, entonces recuerde:
JNZ salta si el indicador cero no está establecido (0)
JNZ es la abreviatura de "Saltar si no es cero (ZF = 0)", y NO "Saltar si ZF está configurado".
Si es más fácil de recordar, considere que JNZ y JNE (saltar si no son iguales) son equivalentes. Por lo tanto, cuando está haciendo cmp al, 47
y el contenido de AL
es igual a 47, se establece la ZF, por lo que no se debe realizar el salto (si no es igual a JNE).
Voy a hacer una respuesta un poco más amplia aquí.
En general, hay dos tipos de saltos condicionales en x86:
Saltos aritméticos: como JZ (saltar si es cero), JC (saltar si llevar), JNC (saltar si no llevar), etc.
Saltos de comparación: JE (salto si es igual), JB (salto si está debajo), JAE (salto si está arriba o igual), etc.
Entonces, use el primer tipo solo después de instrucciones aritméticas o lógicas:
sub eax, ebx
jnz .result_is_not_zero
and ecx, edx
jz .the_bit_is_not_set
Use el segundo grupo solo después de las instrucciones de CMP:
cmp eax, ebx
jne .eax_is_not_equal_to_ebx
cmp ecx, edx
ja .ecx_is_above_than_edx
De esta manera, el programa se vuelve más legible y nunca te confundirás.
Tenga en cuenta que a veces estas instrucciones son en realidad sinónimos. JZ == JE; JC == JB; JNC == JAE y así sucesivamente. La tabla completa está siguiendo. Como puede ver, solo hay 16 instrucciones de salto condicional, pero 30 mnemónicas, que se proporcionan para permitir la creación de un código fuente más legible:
Mnemonic Condition tested Description
jo OF = 1 overflow
jno OF = 0 not overflow
jc, jb, jnae CF = 1 carry / below / not above nor equal
jnc, jae, jnb CF = 0 not carry / above or equal / not below
je, jz ZF = 1 equal / zero
jne, jnz ZF = 0 not equal / not zero
jbe, jna CF or ZF = 1 below or equal / not above
ja, jnbe CF and ZF = 0 above / not below or equal
js SF = 1 sign
jns SF = 0 not sign
jp, jpe PF = 1 parity / parity even
jnp, jpo PF = 0 not parity / parity odd
jl, jnge SF xor OF = 1 less / not greater nor equal
jge, jnl SF xor OF = 0 greater or equal / not less
jle, jng (SF xor OF) or ZF = 1 less or equal / not greater
jg, jnle (SF xor OF) or ZF = 0 greater / not less nor equal
JNZ Jump if Not Zero ZF=0
De hecho, esto es confuso a la derecha.
Para que sea más fácil de entender, reemplace No Cero por No Establecer . (Por favor, tenga en cuenta que esto es para su propia comprensión)
Por lo tanto,
JNZ Jump if Not Set ZF=0
No establecido significa que la bandera Z = 0. Entonces saltar (saltar si no está establecido)
Establecer significa bandera Z = 1. Entonces, NO saltar