assembly x86 reverse-engineering ollydbg cmp

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:

  1. Saltos aritméticos: como JZ (saltar si es cero), JC (saltar si llevar), JNC (saltar si no llevar), etc.

  2. 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