Какова цель кода операции CIL nop?

82

Я просматриваю MSIL и замечаю, что в MSIL есть много инструкций nop .

В статье MSDN говорится, что они не предпринимают никаких действий и используются для заполнения пространства, если код операции исправлен. Они гораздо чаще используются в отладочных сборках, чем в сборках выпуска.

Я знаю, что такие операторы используются в языках ассемблера для согласования последующих инструкций, но зачем нужны MSIL nops в MSIL?

(Примечание редактора: принятый ответ касается NOP машинного кода, а не MSIL / CIL NOP, о которых изначально задавался вопрос.)

Дэн Гольдштейн
источник
19
В этих ответах наблюдается массовая путаница между инструкцией MSIL nop, отправляемой компилятором языка в сборку, и инструкциями nop x86 (на этой платформе), отправляемыми компилятором JIT при запуске сборки. [На самом деле принятый ответ касается x86 nops и не имеет отношения к MSIL.] В идеале этот вопрос следует разбить на 2 разных вопроса: назначение MSIL :: nop? а назначение родной платформы nop?
Steve Steiner

Ответы:

107

NOP служат нескольким целям:

  • Они позволяют отладчику размещать точку останова в строке, даже если она объединена с другими в сгенерированном коде.
  • Это позволяет загрузчику исправлять прыжок с целевым смещением другого размера.
  • Это позволяет выровнять блок кода по определенной границе, что может быть полезно для кэширования.
  • Это позволяет выполнять инкрементную привязку для перезаписи фрагментов кода с вызовом нового раздела, не беспокоясь об изменении общего размера функции.
Энтони Уильямс
источник
Из Википедии : «NOP чаще всего используется для целей синхронизации, для принудительного выравнивания памяти, для предотвращения опасностей, для занятия слотом задержки перехода, для аннулирования существующей инструкции, такой как переход, или в качестве заполнителя для замены. активными инструкциями позже при разработке программы (или для замены удаленных инструкций, когда рефакторинг будет проблематичным или займет много времени). В некоторых случаях NOP может иметь незначительные побочные эффекты; например, на процессорах Motorola серии 68000 NOP код операции вызывает синхронизацию конвейера. "
mbomb007
11

Вот как MSIL / CIL nops ( не машинный код x86nop ) используются при отладке:

Nops используются компиляторами языков (C #, VB и т. Д.) Для определения точек неявной последовательности. Они сообщают JIT-компилятору, где гарантировать, что машинные инструкции могут быть отображены обратно в инструкции IL.

Запись в блоге Рика Байера на DebuggingModes.IgnoreSymbolStoreSequencePoints объясняет некоторые детали.

C # также размещает инструкции Nops после вызова, так что местом возврата в источнике является вызов, а не строка после вызова.

Стив Штайнер
источник
C # также размещает инструкции Nops после вызова, так что местом возврата в источнике является вызов, а не строка после вызова. Не уверен, понял ли я это. У вас есть ссылки?
user492238
8

Он предоставляет возможность для линейных маркеров (например, точек останова) в коде, где сборка выпуска не выдаст ни одного.

гарпо
источник
Должны ли точки останова быть на нет? Почему бы просто не поставить точку останова на обычном коде операции?
Дэн Голдштейн,
4
многие обычные коды операций оптимизируются в выпускных сборках. Это испортило бы ваши точки останова, если бы там не было заполнителя nop, на который точки останова все равно указывали бы
Джимми
1
В отладочных сборках они также используются для предоставления инструкции для прерывания там, где в коде нет инструкции. Например, открывающие фигурные скобки.
Грег Д.
1
Вы можете добавить ссылку на blogs.msdn.com/oldnewthing/archive/2007/08/17/4422794.aspx в качестве источника.
Грег Д.
1
Что ж, спасибо Грегу и Джимми за настоящий ответ.
harpo,
6

Это также может ускорить выполнение кода при оптимизации для конкретных процессоров или архитектур:

Процессоры долгое время используют несколько конвейеров, которые работают примерно параллельно, поэтому две независимые инструкции могут выполняться одновременно. На простом процессоре с двумя конвейерами первый может поддерживать все инструкции, тогда как второй поддерживает только подмножество. Кроме того, между конвейерами возникают некоторые задержки, когда нужно дождаться результата предыдущей инструкции, которая еще не завершена.

В этих обстоятельствах выделенный nop может принудительно передать следующую инструкцию в конкретный конвейер (первый или не первый) и улучшить объединение следующих инструкций в пары, так что стоимость nop будет более чем амортизирована.

Петерхен
источник
5

Чувак! No-op - это круто! Это инструкция, которая только отнимает время. В смутные темные века вы могли бы использовать его для микрокоррекции таймингов в критических циклах или, что более важно, в качестве наполнителя в самомодифицирующемся коде.

плинтус
источник
Я понимаю его использование, когда он запускается непосредственно на оборудовании, но MSIL используется JIT.
Дэн Голдштейн,
MSIL поддерживает JIT только в системах с JIT - MSIL не требует JIT.
плинтус
5

В одном процессоре, с которым я работал недавно (четыре года), NOP использовался, чтобы убедиться, что предыдущая операция завершилась до начала следующей операции. Например:

загрузить значение в регистр (занимает 8 циклов) nop 8 добавить 1 в регистр

Это позволило убедиться, что регистр имел правильное значение перед операцией добавления.

Другое использование заключалось в заполнении исполнительных единиц, таких как векторы прерывания, которые должны были быть определенного размера (32 байта), потому что адрес для вектора 0 был, скажем, 0, для вектора 1 0x20 и так далее, поэтому компилятор помещал туда NOP, если необходимо.

Макис
источник
4

Они могли использовать их для поддержки редактирования и продолжения во время отладки. Он предоставляет отладчику место для работы по замене старого кода новым без изменения смещений и т. Д.

Роб Уокер
источник
4
Я реализовал поддержку отладчика в VS для редактирования и продолжения (я не реализовал части CLR или компилятора). Nops - это часть истории, обеспечивающей правильное сопоставление старой и новой версии метода (особенно в случаях перехода из кода обработки исключений). Однако замена MSIL выполняется на основе всей функции. Для кода, управляемого CLR, нет необходимости «оставлять место» в msil для выполнения этой части. То, что вы здесь говорите, правильно в отношении собственного редактирования и продолжения.
Стив Штайнер,
4

Несколько неортодоксальное использование - это слайды NOP , используемые в эксплойтах переполнения буфера.

mdm
источник
искал это :)
Сурадж Джайн
Исправьте вашу ссылку, она не работает, пожалуйста, всегда проверяйте, отправили ли вы ссылку на веб-архив, потому что они не дают 404 не найдено.
Сурадж Джайн
В настоящее время работает над шеллкодом и хочет больше контекста по NOP. Пришлось вернуться немного назад, но вот архив: web.archive.org/web/20110124015428/http://www.phreedom.org:80/…
saniboy
4

50 лет слишком поздно, но эй.

Nop полезны, если вы набираете ассемблерный код вручную. Если бы вам пришлось удалить код, вы не смогли бы использовать старые коды операций.

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

Иногда приходилось использовать доступные инструменты. В некоторых случаях это был простой редактор машинного кода.

В настоящее время с компиляторами методы больше не имеют никакого смысла.

Жаба
источник
3

Одно из классических способов их использования - отладчик всегда может связать строку исходного кода с инструкцией IL.

Ларри ОБрайен
источник
Так как msil компилируется при JIT-компиляции, это отображение можно потерять (например, собственная инструкция не имеет уникальной инструкции MSIL). NOP используются в качестве механизма связи от компилятора языка к JIT-компилятору для сохранения такого сопоставления.
Стив Штайнер,
3

В сцене взлома программного обеспечения классическим методом разблокировки приложения было бы исправление с помощью NOP строки, которая проверяет ключ, регистрацию, период времени или еще что-то, чтобы она ничего не делала и просто продолжала запускать приложение, как если бы оно было зарегистрировано. .

гулять
источник
5
Я почти уверен, что неуправляемые инструкции были изобретены не для того, чтобы помогать людям использовать пиратское ПО :-)
Саймон Ховард,
3

Я также видел NOP в коде, который модифицируется, чтобы скрыть то, что он делает, в качестве заполнителя (очень старая защита от копирования).

Марко
источник
3

Как сказал ddaa, nops позволяет вам учитывать дисперсию в стеке, так что, когда вы перезаписываете адрес возврата, он перескакивает на салазки nop (много nops подряд), а затем правильно попадает в исполняемый код, а не прыгает на какой-то байт в инструкции, который не является началом.

Алекс Гартрелл
источник
1

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

По крайней мере, это одно из их традиционных применений.

MarkR
источник
1

Это не ответ на ваш конкретный вопрос, но в былые времена вы могли использовать NOP для заполнения слота задержки перехода , если вам не удавалось заполнить его другой полезной инструкцией.

Крис Конвей
источник
1

Согласовывают ли компиляторы .NET вывод MSIL? Я предполагаю, что это может быть полезно для ускорения доступа к IL ... Кроме того, я понимаю, что он разработан для переносимости, и согласованный доступ требуется на некоторых других аппаратных платформах.

Брайан Кноблаух
источник
1

Первой сборкой, которую я изучил, был SPARC, поэтому я знаком со слотом задержки перехода, если вы не можете заполнить его другой инструкцией, обычно инструкцией, которую вы собирались поместить над инструкцией перехода или увеличивать счетчик в циклах, вы используете NOP.

Я не знаком со взломом, но думаю, что обычно перезаписывают стек с помощью NOP, поэтому вам не нужно точно рассчитывать, где начинается ваша вредоносная функция.

Воскресенье
источник
1

Я использовал NOP для автоматической регулировки задержки, накопленной после входа в ISR. Очень удобно, чтобы точно определить время.


источник
-1

nopбудет полезен в полезной нагрузке эксплойта повреждения памяти. Конечно nopпохоже наxchg eax, eax

Не звезда
источник
В другом ответе уже упоминались слайды NOP для эксплойтов с внедрением кода. И еще один ответ на тот же вопрос. В этом ответе не упоминается, насколько они полезны, и это не очевидно, если вы еще не знаете.
Питер Кордес