2012-10-25 3 views
76

Можно создать дубликат:
x86 Assembly - ‘testl’ eax against eax?Точка теста% 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 хорошо, сам по себе, в какой ситуации мы бы не прыгали?

Я начинаю программировать в целом, поэтому я был бы очень признателен, если бы кто-нибудь мог это объяснить мне. Благодаря!

+4

Поскольку некоторые ответы кажутся немного неясными в этом вопросе, позвольте мне указать, что 'TEST' обновляет другие флаги, кроме' ZF'. См. Ссылку на набор инструкций. – Jester

+0

@Jester фиксированный (в моем ответе), извините. –

+0

Другой возможный дубликат: [Что делает инструкция 'test'?] (Http://stackoverflow.com/q/6002079) – jww

ответ

95

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 равен нулю.

+3

Где я могу найти такую ​​информацию? –

+5

а именно? Список инструкций x86 [находится в Википедии] (http://en.wikipedia.org/wiki/X86_instruction_listings), который также связывает [spec от Intel] (http://www.intel.com/content/www/ us/en/processor/architecture-software-developers-manuals.html), а также [еще одна (вполне читаемая) ссылка на машину обратного пути] (http://web.archive.org/web/20100407092131/http://home .comcast.net/~ fbui/intel.html). [Учебник] (http://en.wikibooks.org/wiki/X86_Assembly) также доступен на Wikibooks. –

+0

да, это информация, которую я искал –

9

Это проверяет, нет ли EAX. Команда test выполняет побитовые AND между аргументами, и если EAX содержит нуль, результат устанавливает ZF или ZeroFlag.

+3

Это стандартный способ сделать это. Можно также выполнить cmp% eax, 0 (немедленное) для «ясности для новичков», но это будет кодировать более длинную инструкцию (ака менее эффективную). –

2

Вы правы, что test "и" s два операнда. Но результат отбрасывается, единственное, что остается, и это важная часть, - это флаги. Они установлены, и именно поэтому используется команда test (и существует).

JE прыгает не при равном (имеет значение, когда инструкция была сравнима), что она действительно делает, она перескакивает, когда установлен флаг ZF.И поскольку это один из флагов, установленный test, эта последовательность команд (test x, x; je ...) имеет смысл, что она прыгает, когда x равно 0.

За такие вопросы (и для получения дополнительной информации) Я могу просто рекомендовать книгу о инструкции x86, например даже когда он действительно большой, документация Intel очень хорошая и точная.

3

test является неразрушающим and, он не возвращает результат операции, но устанавливает флаги соответственно. Чтобы узнать, что он действительно проверяет, вам необходимо проверить следующие инструкции. Часто используется для проверки регистра на 0, возможно, связанного с условным скачком jz.

32

Некоторые инструкции x86 предназначены для того, чтобы оставить содержимое операндов (регистров) такими, какие они есть, и просто установить/удалить определенные внутренние ЦП, такие как флаг нуля (ZF). Вы можете думать о ZF как истинный/ложный логический флаг, который находится внутри CPU.

В данном конкретном случае инструкция TEST выполняет побитовое логическое И, отбрасывает фактический результат и устанавливает/отменяет ZF в соответствии с результатом логического и: если результат равен нулю, он устанавливает ZF = 1, в противном случае устанавливает ZF = 0.

условных операторов перехода, как JE предназначены, чтобы посмотреть на ZF для прыжков/notjumping поэтому использование TEST и JE вместе эквивалентно выполнить условный переход на основе значения определенного регистра:

пример:

ТЕСТ EAX, EAX
JE some_address

процессор перейдет к "some_address", если и только если ZF = 1, другими словами, если и только если И (EAX, EAX) = 0, что в превратить это может произойти, если и только если EAX == 0

эквивалентный код С:

if(eax == 0) 
{ 
    goto some_address 
} 
Смежные вопросы