Является ли test eax, eax
более эффективным, чем cmp eax, 0
? Есть ли случай, когда test eax, eax
необходим, когда cmp eax, 0
не отвечает требованиям?
В x86 какая разница между "test eax, eax" и "cmp eax, 0"
Ответ 1
Как уже сказал Zang MingJie в комментарии, test eax,eax
почти идентичен cmp eax,0
, за исключением того, что он короче cmp
, потому что с cmp
вам нужно поставить 0
в качестве аргумента. Обратите внимание, что сбережения не очень велики, потому что второй операнд получает расширенный знак, чтобы соответствовать размеру первого операнда, поэтому он не обязательно принимает целых 4 байта для представления этого нуля.
Теперь вы спрашиваете, есть ли другая разница. Это разумный вопрос, потому что cmp
является арифметической операцией (он выполняет вычитание и отбрасывает результат), тогда как test
является логической операцией (он выполняет побитовое И и отбрасывает результат), поэтому можно было бы разумно заподозрить что они могут изменять регистр Flags
разному.
Как оказалось, обе инструкции изменяют регистр Flags
почти одинаковым образом. Обе команды изменяют биты OF SF ZF AF PF и CF в регистре флагов. test
команда всегда очищает OF и CF, но также и то, что делает cmp
против нуля. Единственное другое отличие состоит в том, что команда cmp
правильно установит неясный флаг AF
, в то время как test
инструкция оставляет содержимое этого флага неопределенным. Но в случае cmp eax,0
AF всегда будет очищаться независимо от значения eax
, поэтому нет ничего, что вы можете узнать из cmp eax,0
что вы не узнаете из test eax,eax
.
Поэтому я бы пришел к выводу, что нет ситуации, когда test eax,eax
даст вам что-то, что cmp eax,0
не будет, и не наоборот. Две инструкции кажутся полностью взаимозаменяемыми для любой практической или даже не столь практичной цели, за исключением сохранения байта или двух кода команды.
Используя test eax,eax
вместо cmp eax,0
показывает, что вы знаете свою сборку. Это также показывает, что вы предпочитаете слегка загадочную и слегка улучшающую инструкцию по простой, понятной инструкции. Это та вещь, которая имеет тенденцию зарабатывать бонусные очки от других вундеркиндов, но в последние пару десятилетий она не имела практической пользы в реальном мире.
Ответ 2
Разница (Теоретическое)
Как указано выше в комментарии и принятом ответе, также, что эти инструкции почти идентичны при использовании таким образом, но тогда почему в наборе команд есть две инструкции, если они одинаковы?
Потому что они разные, если используются с разными операндами.
Тот факт, что test same,same
работает как сравнение с нулем, является лишь удобным следствием того, как 2 дополняют и FLAGS работают, что делает его полезной оптимизацией глазка.
Инструкция TEST использует логику AND для пар битов из arg0 и arg1 и может проверить, установлен конкретный бит или нет, тогда FLAGS устанавливается соответствующим образом. (С целочисленным результатом отбрасывается). Точно так же, как cmp
устанавливает флаги из вычитания, отбрасывая целочисленный результат.
Операция (ТЕСТ)
HTML, кроме из руководства Intel vol.2 PDF
TEMP ← SRC1 **AND** SRC2; SF ← MSB(TEMP); IF TEMP=0 THEN ZF ← 1; ELSE ZF ← 0; FI: PF ← BitwiseXNOR(TEMP[0:7]); CF ← 0; OF ← 0; (* AF is undefined *)
Flags Affected
Флаги OF и CF установлены в 0. Флаги SF, ZF и PF установлены в соответствии с результатом (см. раздел "Эксплуатация" выше). состояние флага AF не определено.
(Операция TEST устанавливает флаги CF и OF на ноль. SF устанавливается на старший значащий бит результата AND. Если результат равен 0, ZF устанавливается на 1, в противном случае устанавливается на 0.)
В то время как инструкция CMP использует инструкцию SUB и вычитает arg1 из arg0 и устанавливает CF (флаг переноса) и ZF (нулевой флаг) на основе заданных аргументов в инструкцию CMP,, если оба равны (arg1 == arg0), то очевидно, что результатом будет ноль, и ZF будет установлен в 1, и если arg0> arg1, тогда никакой флаг не будет установлен (остается 0 для ZF и CF), и если arg0 & lt; arg1, тогда ZF останется 0, поскольку они не равны, но CF будет установлен.
Операция (CMP)
temp ← SRC1 − SignExtend(SRC2); ModifyStatusFlags; (* Modify status flags in the same manner as the SUB instruction*)
Flags Affected
The CF, OF, SF, ZF, AF, и PF flags are set according to the result.
Ссылка от: assembly_language_for_x86_processors.pdf