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

            mov    ecx, 16
looptop:    .
            .
            .
            loop looptop

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

Что будет, если ecx = 0 начать с? Есть ли loop прыгать или провалиться в таком случае?

1 ответ

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(){} против do{}while() и как их выложить.


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

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

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


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


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

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

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

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

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

</rant>, Как я и сказал, loop это одна из моих любимых мозолей. Это неясная инструкция по игре в гольф, если вы не оптимизируете ее для настоящего 8086.

Другие вопросы по тегам