web-dev-qa-db-fra.com

Instructions de montage JNZ & CMP

Corrigez-moi si je me trompe.

Ceci est ma compréhension de JNZ et CMP.

JNZ - Le saut aura lieu si le drapeau Z n'est PAS zéro (1)

CMP - Si les deux valeurs sont égales, l'indicateur Z est défini (1) sinon, il n'est pas défini (0)

Olly DBG

Ceci est un tutoriel flash que je regarde. Il enseigne la solution à un simple CrackMe.

Comme vous pouvez le constater, l'instruction précédente a comparé AL avec 47h. Ils étaient égaux, ce qui positionne le drapeau Z. (Vous pouvez le voir dans les fenêtres des registres sur le côté droit)

L'instruction suivante est une JNZ. Je croyais comprendre que le saut aurait lieu si le drapeau Z était activé. L'indicateur Z IS est activé, mais le saut n'a pas lieu!

Pourquoi?

17
43.52.4D.

JNZ est l'abréviation de "Jump if not zero (ZF = 0)" etNOT"Jump si le ZF est défini".

Si c'est plus facile à retenir, considérez que JNZ et JNE (jump sinon égal) sont équivalents. Par conséquent, lorsque vous utilisez cmp al, 47 et que le contenu de AL est égal à 47, le facteur ZF est défini, mais le saut (si Non égal - JNE) ne doit pas être pris.

30
Michael Foukarakis

Je vais apporter une réponse un peu plus large ici. 

Il y a généralement deux types de sauts conditionnels dans x86:

  1. Sauts arithmétiques - comme JZ (saut si zéro), JC (saut si reporté), JNC (saut si non reporté), etc.

  2. Sauts de comparaison - JE (saut si égal), JB (saut si inférieur), JAE (saut si supérieur ou égal), etc.

Donc, utilisez le premier type seulement après des instructions arithmétiques ou logiques:

sub  eax, ebx
jnz  .result_is_not_zero 

and  ecx, edx
jz   .the_bit_is_not_set

Utilisez le deuxième groupe uniquement après les instructions du CPM:

cmp  eax, ebx
jne  .eax_is_not_equal_to_ebx

cmp  ecx, edx
ja   .ecx_is_above_than_edx

De cette façon, le programme devient plus lisible et vous ne serez jamais confus.

Notez que parfois ces instructions sont en fait des synonymes. JZ == JE; JC == JB; JNC == JAE et ainsi de suite. Le tableau complet suit. Comme vous pouvez le constater, il n'y a que 16 instructions de saut conditionnel, mais 30 mnémoniques - elles sont fournies pour permettre la création de code source plus lisible:

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 
17
johnfound

Au début, il semble que JNZ signifie saut si pas zéro (0), comme dans saut si le drapeau zéro est 1/défini.

Mais en réalité, cela signifie Sauter (si) pas Zéro (est défini).

Si 0 = non défini et 1 = défini, rappelez-vous simplement:
JNZ Saute si l'indicateur zéro n'est pas défini (0)

2
43.52.4D.
JNZ     Jump if Not Zero    ZF=0

En effet, c'est déroutant à droite.

Pour faciliter la compréhension, remplacez pas de zéro par non défini . (Veuillez prendre note que ceci est pour votre propre compréhension)

Par conséquent,

JNZ     Jump if Not Set     ZF=0

Non défini signifie que le drapeau Z = 0. So Jump (saut si non défini)

Set signifie flag Z = 1. Alors, ne sautez PAS

0