Что такое "rep; nop;" означают в сборке x86?

  • Что означает rep; nop?
  • Это то же самое, что и инструкция pause?
  • Это то же самое, что и rep nop (без точки с запятой)?
  • Какая разница с простой инструкцией nop?
  • Одинаково ли это относится к процессорам AMD и Intel?
  • (бонус) Где находится официальная документация для этих инструкций?

Мотивация по этому вопросу

После некоторого обсуждения в комментариях другого вопроса я понял, что не знаю, что означает rep; nop; в сборке x86 (или x86-64). А также я не мог найти хорошее объяснение в Интернете.

Я знаю, что rep является префиксом, который означает "повторить следующую команду cx times" (или, по крайней мере, это было в старой 16-разрядной сборке x86). Согласно этой сводной таблице в Википедии, кажется, что rep может использоваться только с movs, stos, cmps, lods, scas (но, возможно, это ограничение было удалено на более новых процессорах). Таким образом, я бы подумал, что rep nop (без полуколонии) повторит операцию nop cx раз.

Однако после дальнейшего поиска я еще больше смутился. Кажется, что rep; nop и pause сопоставляются с точно таким же кодом операции, а pause имеет немного другое поведение, чем просто nop. Некоторая старая почта с 2005 года говорила разные вещи:

  • "старайтесь не сжигать слишком много энергии"
  • "это эквивалентно" nop "только с 2-байтным кодированием."
  • "это волшебство на Intel. Его вроде" nop, но пусть другой HT-брат работает "
  • "это пауза в Intel и быстрое дополнение к Athlon"

С этими разными мнениями я не мог понять правильного значения.

Он используется в ядре Linux (на i386 и x86_64) вместе с этим комментарием: /* REP NOP (PAUSE) is a good thing to insert into busy-wait loops. */ Также используется используемое в BeRTOS, с тем же комментарий.

Ответ 1

rep; nop действительно совпадает с инструкцией pause (код операции F390). Он может использоваться для ассемблеров, которые пока не поддерживают команду pause. На предыдущих процессорах это просто ничего не делало, как и nop, но в двух байтах. На новых процессорах, поддерживающих гиперпоточность, он используется в качестве подсказки для процессора, который вы выполняете spinloop для повышения производительности. Из Справочник по инструкциям Intel:

Улучшает производительность циклов "spin-wait". При выполнении цикла "спин-жду" процессор Pentium 4 или Intel Xeon испытывает серьезное снижение производительности при выходе из цикла, поскольку он обнаруживает возможное нарушение порядка памяти. Инструкция PAUSE дает подсказку процессору, что кодовая последовательность представляет собой цикл ожидания ожидания. Процессор использует этот совет, чтобы избежать нарушения порядка памяти в большинстве ситуаций, что значительно повышает производительность процессора. По этой причине рекомендуется, чтобы инструкция PAUSE была помещена во все циклы ожидания ожидания.

Ответ 2

Префиксы, которые не применяются к команде, игнорируются. Однако будущие процессоры могут использовать эту последовательность байтов для кодирования новой команды. (да, пространство операций x86 настолько ограничено, что они делают такие сумасшедшие вещи, как и это, и да, это усложняет декодеры.)

В этом случае это означает, что вы можете использовать pause в spinloops, не нарушая совместимость. Старые процессоры, которые не знают о pause, будут декодировать его как NOP без ущерба. На новых процессорах вы получаете преимущество энергосберегающего /HT дружелюбия, а избегаете ошибочной спекуляции с памятью, когда память, в которую вы вращаетесь, меняется, и вы 'оставляют спиновый цикл.


Ссылки на руководства Intel и множество других полезных материалов на странице справки wiki x86: /tags/x86/info

Другой случай бессмысленного префикса rep, который становится новой инструкцией для новых процессоров: lzcnt - F3 0F BD /r. На процессорах, которые не поддерживают эту инструкцию (отсутствует флаг функции LZCNT в их CPUID), он декодируется как rep bsr, который работает так же, как bsr. Таким образом, на старых процессорах он производит 32 - expected_result и undefined, когда входной сигнал был равен нулю.


Один случай бессмысленного префикса rep, который, вероятно, никогда не будет декодировать по-другому: rep ret по умолчанию используется gcc при таргетинге на "общие" ЦП (т.е. не нацеливать определенный процессор с помощью -march или -mtune), и не нацеливать на AMD K8 или K10.) Пройдет несколько десятилетий, прежде чем кто-нибудь сможет сделать процессор, который декодирует rep ret как нечто, отличное от ret, потому что он присутствует в большинстве бинарных файлов в большинстве дистрибутивов Linux. См. Что означает` rep ret`?