Я просматриваю MSIL и замечаю, что в MSIL есть много инструкций nop .
В статье MSDN говорится, что они не предпринимают никаких действий и используются для заполнения пространства, если код операции исправлен. Они гораздо чаще используются в отладочных сборках, чем в сборках выпуска.
Я знаю, что такие операторы используются в языках ассемблера для согласования последующих инструкций, но зачем нужны MSIL nops в MSIL?
(Примечание редактора: принятый ответ касается NOP машинного кода, а не MSIL / CIL NOP, о которых изначально задавался вопрос.)
Ответы:
NOP служат нескольким целям:
источник
Вот как MSIL / CIL nops ( не машинный код x86
nop
) используются при отладке:Nops используются компиляторами языков (C #, VB и т. Д.) Для определения точек неявной последовательности. Они сообщают JIT-компилятору, где гарантировать, что машинные инструкции могут быть отображены обратно в инструкции IL.
Запись в блоге Рика Байера на DebuggingModes.IgnoreSymbolStoreSequencePoints объясняет некоторые детали.
C # также размещает инструкции Nops после вызова, так что местом возврата в источнике является вызов, а не строка после вызова.
источник
Он предоставляет возможность для линейных маркеров (например, точек останова) в коде, где сборка выпуска не выдаст ни одного.
источник
Это также может ускорить выполнение кода при оптимизации для конкретных процессоров или архитектур:
Процессоры долгое время используют несколько конвейеров, которые работают примерно параллельно, поэтому две независимые инструкции могут выполняться одновременно. На простом процессоре с двумя конвейерами первый может поддерживать все инструкции, тогда как второй поддерживает только подмножество. Кроме того, между конвейерами возникают некоторые задержки, когда нужно дождаться результата предыдущей инструкции, которая еще не завершена.
В этих обстоятельствах выделенный nop может принудительно передать следующую инструкцию в конкретный конвейер (первый или не первый) и улучшить объединение следующих инструкций в пары, так что стоимость nop будет более чем амортизирована.
источник
Чувак! No-op - это круто! Это инструкция, которая только отнимает время. В смутные темные века вы могли бы использовать его для микрокоррекции таймингов в критических циклах или, что более важно, в качестве наполнителя в самомодифицирующемся коде.
источник
В одном процессоре, с которым я работал недавно (четыре года), NOP использовался, чтобы убедиться, что предыдущая операция завершилась до начала следующей операции. Например:
загрузить значение в регистр (занимает 8 циклов) nop 8 добавить 1 в регистр
Это позволило убедиться, что регистр имел правильное значение перед операцией добавления.
Другое использование заключалось в заполнении исполнительных единиц, таких как векторы прерывания, которые должны были быть определенного размера (32 байта), потому что адрес для вектора 0 был, скажем, 0, для вектора 1 0x20 и так далее, поэтому компилятор помещал туда NOP, если необходимо.
источник
Они могли использовать их для поддержки редактирования и продолжения во время отладки. Он предоставляет отладчику место для работы по замене старого кода новым без изменения смещений и т. Д.
источник
Несколько неортодоксальное использование - это слайды NOP , используемые в эксплойтах переполнения буфера.
источник
50 лет слишком поздно, но эй.
Nop полезны, если вы набираете ассемблерный код вручную. Если бы вам пришлось удалить код, вы не смогли бы использовать старые коды операций.
аналогично, вы можете вставить новый код, перезаписав какой-то код операции, и перейти в другое место. Там вы помещаете перезаписанные коды операций и вставляете новый код. Когда будете готовы, отпрыгните назад.
Иногда приходилось использовать доступные инструменты. В некоторых случаях это был простой редактор машинного кода.
В настоящее время с компиляторами методы больше не имеют никакого смысла.
источник
Одно из классических способов их использования - отладчик всегда может связать строку исходного кода с инструкцией IL.
источник
В сцене взлома программного обеспечения классическим методом разблокировки приложения было бы исправление с помощью NOP строки, которая проверяет ключ, регистрацию, период времени или еще что-то, чтобы она ничего не делала и просто продолжала запускать приложение, как если бы оно было зарегистрировано. .
источник
Я также видел NOP в коде, который модифицируется, чтобы скрыть то, что он делает, в качестве заполнителя (очень старая защита от копирования).
источник
Как сказал ddaa, nops позволяет вам учитывать дисперсию в стеке, так что, когда вы перезаписываете адрес возврата, он перескакивает на салазки nop (много nops подряд), а затем правильно попадает в исполняемый код, а не прыгает на какой-то байт в инструкции, который не является началом.
источник
Они позволяют компоновщику заменять более длинную инструкцию (обычно длинный прыжок) на более короткую (короткий прыжок). NOP занимает лишнее место - код нельзя было переместить, так как это остановило бы работу других переходов. Это происходит во время компоновки, поэтому компилятор не может знать, подходит ли длинный или короткий переход.
По крайней мере, это одно из их традиционных применений.
источник
Это не ответ на ваш конкретный вопрос, но в былые времена вы могли использовать NOP для заполнения слота задержки перехода , если вам не удавалось заполнить его другой полезной инструкцией.
источник
Согласовывают ли компиляторы .NET вывод MSIL? Я предполагаю, что это может быть полезно для ускорения доступа к IL ... Кроме того, я понимаю, что он разработан для переносимости, и согласованный доступ требуется на некоторых других аппаратных платформах.
источник
Первой сборкой, которую я изучил, был SPARC, поэтому я знаком со слотом задержки перехода, если вы не можете заполнить его другой инструкцией, обычно инструкцией, которую вы собирались поместить над инструкцией перехода или увеличивать счетчик в циклах, вы используете NOP.
Я не знаком со взломом, но думаю, что обычно перезаписывают стек с помощью NOP, поэтому вам не нужно точно рассчитывать, где начинается ваша вредоносная функция.
источник
Я использовал NOP для автоматической регулировки задержки, накопленной после входа в ISR. Очень удобно, чтобы точно определить время.
источник
nop
будет полезен в полезной нагрузке эксплойта повреждения памяти. Конечноnop
похоже наxchg eax, eax
источник