Инструкции по сборке JNZ и CMP

Поправьте меня, если я ошибаюсь.

Это мое понимание JNZ и CMP.

JNZ - прыжок БУДЕТ иметь место, если Z Флаг НЕ равен нулю (1)

CMP - Если два значения равны, установлен флаг Z (1), в противном случае он не установлен (0)

Olly DBG

Я смотрю этот флэш-урок. Это обучение решению простого CrackMe.

Как видите, предыдущая инструкция сравнивала AL с 47h. Они были равны, что установило флаг Z. (Вы можете увидеть это в окнах регистров с правой стороны)

Следующая инструкция JNZ. Насколько я понимаю, прыжок произойдет, если установлен флаг Z. Флаг Z УСТАНОВЛЕН, но прыжок не происходит!

Почему?


person 43.52.4D.    schedule 12.02.2013    source источник
comment
@nrz Ваш комментарий не очень ясен - ожидается ли, что OP осознает ошибку, посмотрев на утверждение, действительно, очень сложно?   -  person Michael Foukarakis    schedule 13.02.2013
comment
@nrz Черт возьми, ты еще больше пытаешься меня запутать?!?! Из других ответов теперь я знаю, что с JNZ прыжок происходит только в том случае, если нулевой флаг НЕ установлен (0)   -  person 43.52.4D.    schedule 13.02.2013
comment
@ 43.52.4D. Извините, я неправильно прочитал предложение JNZ - прыжок БУДЕТ иметь место, если Z Flag НЕ равен нулю (1) в вашем вопросе, и в результате мой комментарий, возможно, сбивал с толку, поэтому я удалил его сейчас. Краткий справочник Intel x86 JUMP содержит полезную таблицу для проверки условий ветвления разные условные переходы x86.   -  person nrz    schedule 13.02.2013


Ответы (5)


JNZ - это сокращение от «Прыгать, если не ноль (ZF = 0)», и НЕ «Прыгать, если ZF установлен».

Если что-то проще запомнить, считайте, что JNZ и JNE (прыжок, если не равны) эквивалентны. Следовательно, когда вы выполняете cmp al, 47 и содержимое AL равно 47, ZF устанавливается, следовательно, переход (если Not Equal - JNE) не должен выполняться.

person Michael Foukarakis    schedule 12.02.2013

Я сделаю здесь более широкий ответ.

Вообще говоря, в x86 есть два типа условных переходов:

  1. Арифметические прыжки - например, JZ (прыжок, если ноль), JC (прыжок, если перенос), JNC (прыжок, если не перенос) и т. Д.

  2. Сравнительные прыжки - JE (прыжок, если равен), JB (прыжок, если ниже), JAE (прыжок, если выше или равный) и т. Д.

Итак, используйте первый тип только после арифметических или логических инструкций:

sub  eax, ebx
jnz  .result_is_not_zero 

and  ecx, edx
jz   .the_bit_is_not_set

Используйте вторую группу только после инструкций CMP:

cmp  eax, ebx
jne  .eax_is_not_equal_to_ebx

cmp  ecx, edx
ja   .ecx_is_above_than_edx

Таким образом, программа станет более читаемой, и вы никогда не запутаетесь.

Обратите внимание, что иногда эти инструкции на самом деле являются синонимами. JZ == JE; JC == JB; JNC == JAE и так далее. Полная таблица приведена ниже. Как видите, есть только 16 инструкций условного перехода, но 30 мнемоник - они предназначены для создания более читаемого исходного кода:

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 
person johnfound    schedule 12.02.2013
comment
Для мнемонического ja, jnbe Проверенное условие должно быть CF AND ZF = 0. - person Andrew Hardiman; 16.07.2018
comment
@ case_2501: Исправлено. Спасибо. - person johnfound; 19.07.2018

Сначала кажется, что JNZ означает прыжок, если не ноль (0), как в прыжке, если нулевой флаг равен 1 / установлен.

Но на самом деле это означает прыжок (если) не ноль (установлен).

Если 0 = не установлено, а 1 = установлено, просто помните:
JNZ Перескакивает, если нулевой флаг не установлен (0)

person 43.52.4D.    schedule 12.02.2013

JNZ     Jump if Not Zero    ZF=0

Действительно, это сбивает с толку.

Чтобы облегчить понимание, замените Not Zero на Not Set. (Обратите внимание, это для вашего собственного понимания)

Следовательно,

JNZ     Jump if Not Set     ZF=0

Not Set означает, что флаг Z = 0. Итак, Jump (Перейти, если не установлен)

Установить означает флаг Z = 1. Итак, НЕ прыгайте.

person Charlotte Russell    schedule 26.05.2017
comment
В FLAGS есть несколько битов условий, ZF - только один из них. (Другие - CF, OF, SF, PF, а также AF, но вы не можете напрямую переходить по AF). Если вы хотите быть явным, перейдите, если ZF не установлен. Или прыгнуть, если !ZF - person Peter Cordes; 18.10.2020

Вы можете читать JNE / Z как *

J ump, если статус N не установлен на флаге E qual / Z ero

Не задано - это состояние, когда флаг равенства / нуля в ЦП установлен в 0, что происходит только тогда, когда условие выполнено или равно совпадению.

person Suhailan Safei    schedule 18.10.2020
comment
cmp same, same устанавливает ZF, потому что x - x == 0. Семантическое значение jne - прыгать, если два сравниваемых элемента не равны. Последнее предложение вашего ответа звучит так, будто в нем говорится, что ZF = 0, когда вы сравниваете две равные вещи, то есть наоборот. Может быть, вы хотели сказать, что ZF будет установлен только тогда, когда сравнение будет одинаково согласовано? Но вы только что говорили о 0, а затем продолжили говорить ... что только случается, придавая этой фразе неявный субъект ZF=0. - person Peter Cordes; 18.10.2020
comment
Также обратите внимание, что большинство инструкций ALU устанавливают FLAGS, поэтому, например, inc eax очистит ZF, когда выходное значение EAX не равно нулю. IDK, если это то, что вы подразумеваете под условием, выполнено. Перед jnz обычно используется инструкция test eax,eax (или любой другой регистр); Думаю, условием можно назвать ненулевой EAX. В любом случае, я не думаю, что ваш ответ, к сожалению, очень понятен для тех, кто еще не знает, как работают ФЛАГИ. - person Peter Cordes; 18.10.2020