Точка теста% eax% eax
Возможный дубликат:
x86 Assembly - 'testl eax против eax?
Я очень новичок в программировании на ассемблере, и сейчас я пытаюсь прочитать язык ассемблера, созданный из двоичного файла. Я столкнулся с
test %eax,%eax
или test %rdi, %rdi
и т.д. и т.д. Я очень смущен относительно того, что это делает. Разве значения в %eax, %eax
не совпадают? Что это такое? Я где-то читал, что он выполняет операцию AND
..... но поскольку они являются одним и тем же значением, не будет ли он просто возвращать %eax
?
Ниже приведен только один экземпляр, где я нашел это использование:
400e6e: 85 c0 test %eax,%eax
400e70: 74 05 je 400e77 <phase_1+0x23>
Я думал, что je
перескакивает, если два сравниваемых значения равны...... ну, потому что %eax
хорошо, сам, в какой ситуации мы бы не прыгали?
Я новичок в программировании в целом, поэтому я был бы очень признателен, если бы кто-нибудь мог мне это объяснить. Спасибо!
Ответы
Ответ 1
CMP
вычитает операнды и устанавливает флаги. А именно, он устанавливает флаг нуля, если разность равна нулю (операнды равны).
TEST
устанавливает флаг нуля, ZF
, когда результат операции И равен нулю. Если два операнда равны, их побитовое И равно нулю, когда оба равны нулю. TEST
также устанавливает флаг знака SF
, когда в результате устанавливается старший значащий бит и флаг четности PF
, когда число установленных бит равно.
JE
[Jump if Equals] проверяет флаг нуля и прыгает, если флаг установлен. JE
является псевдонимом JZ
[Jump if Zero], поэтому дизассемблер не может выбрать один на основе кода операции. JE
называется таким, потому что флаг нуля установлен, если аргументы CMP
равны.
Итак,
TEST %eax, %eax
JE 400e77 <phase_1+0x23>
перескакивает, если %eax
равно нулю.
Ответ 2
Некоторые инструкции x86 предназначены для того, чтобы оставить содержимое операндов (регистров) такими, какими они есть, и просто устанавливать/удалять определенные внутренние ЦП, такие как флаг нуля (ZF). Вы можете думать о ZF как истинный/ложный логический флаг, который находится внутри CPU.
в этом конкретном случае команда TEST выполняет побитовое логическое И, отбрасывает фактический результат и устанавливает/отменяет ZF в соответствии с результатом логического и: если результат равен нулю, он устанавливает ZF = 1, в противном случае он устанавливает ZF = 0.
Инструкции условного перехода, такие как JE, предназначены для просмотра ZF для прыжков/неписелей, поэтому использование TEST и JE вместе эквивалентно выполнению условного перехода на основе значения конкретного регистра:
пример:
TEST EAX, EAX
JE some_address
CPU перейдет к "some_address" тогда и только тогда, когда ZF = 1, другими словами, если и только если AND (EAX, EAX) = 0, что, в свою очередь, может произойти тогда и только тогда, когда EAX == 0
эквивалентный код C:
if(eax == 0)
{
goto some_address
}
Ответ 3
Это проверяет, равен ли EAX
нулю. Команда test
выполняет побитовое AND
между аргументами, а если EAX
содержит ноль, результат устанавливает ZF или ZeroFlag.
Ответ 4
test
является неразрушающим and
, он не возвращает результат операции, но устанавливает флаги соответственно. Чтобы узнать, что он действительно проверяет, вам необходимо проверить следующие инструкции. Часто используется для проверки регистра на 0, возможно, связанного с условным скачком jz
.
Ответ 5
Вы правы, что test
"и" s два операнда. Но результат отбрасывается, единственное, что остается, и это важная часть, - это флаги. Они установлены, и именно поэтому используется команда test
(и существует).
JE
перескакивает не при равном (имеет значение, когда инструкция перед сравнением), что она действительно делает, она перескакивает, когда установлен флаг ZF
. И поскольку это один из флагов, установленный test
, эта последовательность команд (test x, x; je...) имеет значение, что она перепрыгивается, когда x равно 0.
Для таких вопросов (и для более подробной информации) я могу просто рекомендовать книгу о инструкции x86, например. даже когда он действительно большой, документация Intel очень хорошая и точная.