Как точно работает инструкция x86 LOOP?

mov ecx, 16 looptop: . . . loop looptop 

Сколько раз будет выполняться этот цикл?

Что произойдет, если ecx = 0 для начала? В этом случае происходит прыжок или провал loop ?

loop точно так же, как dec ecx / jnz , за исключением того, что он не устанавливает флаги .

Это похоже на нижнюю часть do{} while(--ecx != 0); в C. Если выполнение входит в цикл с ecx = 0 , обертка означает, что цикл будет выполняться 2 ^ 32 раза. (Или 2 ^ 64 раза в 64-битном режиме, потому что он использует RCX).

В отличие от rep movsb/stosb/etc. , он не проверяет ECX = 0 до декремента, только после.

Размер адреса определяет, использует ли он CX, ECX или RCX. Таким образом, в 64-битном коде addr32 loop похож на dec ecx / jnz , тогда как регулярный loop похож на dec rcx / jnz . Или в 16-битном коде он обычно использует CX, но префикс размера адреса ( 0x67 ) заставит его использовать ecx . Как сказано в руководстве Intel, он игнорирует REX.W, потому что он устанавливает размер операнда, а не размер адреса.

Связано: Почему циклы всегда скомпилированы так? для получения дополнительной информации о структуре цикла в asm, while(){} vs. do{}while() и как их выложить.


Дополнительные советы по отладке

Если вы когда-нибудь захотите узнать подробности инструкции, ознакомьтесь с руководством: либо официальным справочником по учебнику для учебных пособий Intel, либо справочником html с каждой записью на другой странице ( http://felixcloutier.com/x86/ ). Но учтите, что HTML не содержит интро и приложения, в которых есть подробности о том, как интерпретировать вещи, например, когда говорится, что «флаги установлены в соответствии с результатом» для инструкций, например add .

И вы можете (и должны) также просто попробовать вещи в отладчике: меняются одношаговые и наблюдательные регистры. Используйте меньшее начальное значение для ecx чтобы быстрее добраться до интересной ecx=1 . См. Также вики-файлы x86 для ссылок на руководства, руководства и советы по отладке asm внизу.


И BTW, если инструкции, которые не показаны, изменяют ecx , он может зацикливаться сколько угодно раз. Чтобы вопрос имел простой и уникальный ответ, вам нужна гарантия того, что инструкции между меткой и инструкцией loop не изменяют ecx . (Они могли бы сохранить / восстановить его, но если вы собираетесь это делать, обычно лучше просто использовать другой регистр в качестве счетчика циклов. push / pop внутри цикла делает ваш код трудным для чтения.)


Предъявляйте чрезмерное использование LOOP даже когда вам уже нужно увеличивать что-то еще в цикле. LOOP – это не единственный способ петли, и обычно это самое худшее.

Обычно вы никогда не должны использовать инструкцию цикла, если не оптимизировать размер кода за счет скорости, потому что она медленная . Компиляторы не используют его. (Так что производители процессоров не утруждают себя быстрым, поймать 22.) Используйте dec / jnz или совсем другое условие цикла. (См. Также http://agner.org/optimize/, чтобы узнать больше о том, что эффективно.)

Циклы даже не должны использовать счетчик; часто бывает так же хорошо, если не лучше сравнивать указатель с конечным адресом или проверять какое-то другое условие. (Бесцельное использование loop – одно из моих любимых мотивов, особенно когда у вас уже есть что-то в другом регистре, который работал бы как счетчик циклов.) Использование cx в качестве счетчика циклов часто просто связывает один из ваших драгоценных немногих регистров, когда вы могли бы использовал cmp / jcc в другом регистре, который вы все равно увеличивали.

IMO, loop следует рассматривать как одну из тех неясных инструкций x86, с которыми новички не должны отвлекаться. Как stosd (без префикса rep ), aam или xlatb . Тем не менее, он действительно использует их при оптимизации размера кода. (Это иногда полезно в реальной жизни для машинного кода (например, для загрузочных секторов), а не только для таких вещей, как кодовый гольф .)

ИМО, просто учите / учите, как работают условные ветви, и как создавать петли из них. Тогда вы не застрянете в мысли, что есть что-то особенное в цикле, который использует loop . Я видел SO-вопрос или комментарий, который сказал что-то вроде «Я думал, что вам нужно объявлять циклы», и не понимал, что loop – это всего лишь инструкция.

. Как я уже сказал, loop – одно из моих любимых раздражителей. Это ненавязчивая инструкция для игры в гольф, если вы не оптимизируете фактический 8086.

  • mscorlib.dll & System.dll
  • Очень быстро memcpy для обработки изображений?
  • использование ILMerge с библиотеками .NET 4
  • Что регистрирует сохранение в соглашении вызова ARM C?
  • В чем разница между MOV и LEA?
  • Загрузка нескольких версий одной и той же сборки
  • Как вы прокручиваете загруженные в настоящее время сборки?
  • Visual Studio 2010 не создает перед запуском при изменении кода
  • Самый быстрый способ вычисления 128-битного целого по модулю 64-разрядного целого числа
  • Visual Studio 2010: ссылочные сборки Ориентация на версию с более высокой версией
  • Как получить вывод ассемблера из источника C / C ++ в gcc?
  • Давайте будем гением компьютера.