Яка мета операційного коду CIL nop?


82

Я йду через MSIL і , помітивши , що є багато NOP інструкцій в MSIL.

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

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

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


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

Відповіді:


107

НОП слугує для кількох цілей:

  • Вони дозволяють налагоджувачу розміщувати точку зупинки на рядку, навіть якщо він поєднується з іншими у створеному коді.
  • Це дозволяє навантажувачу зафіксувати стрибок з різним розміром зміщення цілі.
  • Це дозволяє вирівняти блок коду за певною межею, що може бути добре для кешування.
  • Це дозволяє здійснювати поступове зв'язування, щоб замінити фрагменти коду викликом нового розділу, не турбуючись про загальну зміну розміру функції.

З Вікіпедії : "NOP найчастіше використовується для хронометражу, для примусового вирівнювання пам'яті, запобігання небезпекам, зайняття слота затримки гілки, анулювання існуючої інструкції, наприклад, стрибка, або як замінник місця, який замінюється активними вказівками пізніше при розробці програми (або заміною видалених інструкцій, коли рефакторинг буде проблематичним або трудомістким). У деяких випадках NOP може мати незначні побічні ефекти; наприклад, на процесорах Motorola 68000, NOP opcode викликає синхронізацію конвеєра. "
mbomb007

10

Ось як nops MSIL / CIL ( не машинний код x86nop ) використовується для налагодження:

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

Запис у блозі Ріка Байєра на DebuggingModes.IgnoreSymbolStoreSequencePoints , пояснює деякі подробиці.

C # також розміщує Nops після вказівок виклику, так що місце повернення сайту у джерелі є викликом, а не лінією після дзвінка.


C # також розміщує Nops після вказівок виклику, так що місце повернення сайту у джерелі є викликом, а не лінією після дзвінка. Не впевнений, чи отримую я це. Чи є у вас якесь посилання?
user492238

8

Він надає можливість для маркерів на основі рядків (наприклад, точок зупинку) у коді, де збірка випуску не видає жодного.


Точки зупинку повинні бути на nop? Чому б просто не поставити точку зупинки на звичайний код роботи?
Ден Голдштейн,

4
Багато звичайних кодів операційних кодів оптимізуються в збірках релізів. Це зіпсує ваші точки зупинку, якщо тільки там не буде заповнювача, пункти зупинку все одно вказуватимуть
Джиммі,

1
У збірках для налагодження вони також використовуються для надання інструкцій про розрив, коли код не має інструкцій. Наприклад, розкриваючі брекети.
Грег Д

1
Можливо, ви захочете додати посилання на blogs.msdn.com/oldnewthing/archive/2007/08/17/4422794.aspx як джерело.
Грег Д

1
Ну, дякую Грегу та Джиммі за те, що вони перетворили це на реальну відповідь.
harpo

6

Це також може пришвидшити роботу коду при оптимізації для конкретних процесорів або архітектур:

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

За цих обставин спеціальний nop може примусити наступну інструкцію потрапити до певного конвеєру (перший або не перший) та покращити поєднання наступних інструкцій, щоб вартість nop була більш ніж амортизованою.


5

Чувак! Ні-оп - це чудово! Це інструкція, яка займається нічим іншим, як лише витрачати час. У похмурий темний вік ви могли б використовувати його для мікрорегулювання часу у критичних циклах або, що ще важливіше, як наповнювач у самозмінній коді.


Я розумію його використання, коли його запускають безпосередньо на апаратному забезпеченні, але MSIL має JITed.
Ден Голдштейн,

MSIL є JITed лише в системах, які мають JIT - MSIL не вимагає JIT.
плінтус

5

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

значення навантаження для реєстрації (займає 8 циклів) nop 8 додати 1 для реєстрації

Це переконалося, що регістр мав правильне значення перед операцією додавання.

Іншим використанням було заповнення одиниць виконання, таких як вектори переривань, які мали бути певного розміру (32 байта), оскільки адреса для vector0 була, скажімо 0, для вектора 1 0x20 тощо, тому компілятор поміщав туди NOP, якщо потрібні.


4

Вони можуть використовувати їх для підтримки редагування та продовження під час налагодження. Він надає налагоджувачеві приміщення для роботи, щоб замінити старий код новим без зміни зсувів тощо.


4
Я реалізував підтримку відладчика у VS для редагування та продовжував (я не реалізовував CLR або частини компілятора). Nops є частиною історії, щоб забезпечити правильне відображення від старої до нової версії методу (зокрема у випадках виходу з коду обробки exeception). Однак заміна MSIL виконується на основі цілої функції. Для керованого коду CLR не потрібно "залишати місце" в msil, щоб виконати цю частину. Те, що ви тут говорите, є правильним щодо рідної редагування та продовження.
Steve Steiner

4

Дещо неортодоксальним використанням є NOP-слайди , що використовуються в експлойтах переповнення буфера.


шукав це :)
Сурадж Джейн

Виправте своє посилання, воно не працює, будь ласка, завжди переконайтеся, що ви надіслали посилання на веб-архів, оскільки вони не дадуть 404 не знайдено.
Сурадж Джайн

Зараз я працюю над кодом оболонки і хотів отримати більше контексту щодо NOP. Довелося трохи повернутися назад, але ось архів: web.archive.org/web/20110124015428/http://www.phreedom.org:80/…
saniboy

4

На 50 років запізно, але ей.

Нопи корисні, якщо ви вводите код збірки вручну. Якби вам довелося видалити код, ви не могли б замінити старі коди операцій.

Подібно, ви можете вставити новий код, переписавши деякий код операції та перейти кудись ще. Там ви вставляєте перезаписані коди операцій та вставляєте новий код. Коли будете готові, ви стрибаєте назад.

Іноді доводилося користуватися доступними інструментами. У деяких випадках це був просто найпростіший редактор машинних кодів.

У наш час із компіляторами методи вже не мають сенсу.


3

Класичне їх використання полягає в тому, що ваш налагоджувач завжди може пов’язати рядок вихідного коду з інструкцією IL.


Оскільки msil є компільованим JIT під час запуску, його можна втратити (наприклад, рідна інструкція не має унікальної інструкції MSIL). NOP використовуються як механізм зв'язку від компілятора мови до компілятора JIT для збереження такого відображення.
Steve Steiner

3

На сцені злому програмного забезпечення класичним методом розблокування програми буде виправлення за допомогою NOP рядка, який перевіряє ключ, реєстрацію, період часу чи щось інше, щоб він нічого не зробив і просто продовжив запуск програми, ніби вона зареєстрована .


5
Я майже впевнений, що інструкції щодо відмови не були винайдені, щоб допомогти людям піратським програмним забезпеченням :-)
Саймон Говард,

3

Я також бачив NOP у коді, який модифікує себе, щоб затушувати те, що він робить як заповнювач (захист від старої копії Veeery).


3

Як сказав ddaa, nops дозволяє вам враховувати відхилення в стеку, так що коли ви перезаписуєте адресу повернення, вона перескакує на nop sled (багато nops поспіль), а потім вдаряє виконуваний код правильно, а не переходить до деякого байт в інструкції, яка не є початком.


1

Вони дозволяють лінкеру замінити довшу інструкцію (як правило, стрибок у довжину) на коротшу (короткий стрибок). NOP займає зайвий простір - код не можна переміщати, оскільки це зупинить роботу інших стрибків. Це відбувається під час посилання, тому компілятор не може знати, чи буде підходящим стрибок у довжину чи короткий шлях.

Принаймні, це одне з їх традиційних застосувань.



1

Чи вирівнюють компілятори .NET вихід MSIL? Я гадаю, це може бути корисним для прискорення доступу до ІЛ ... Крім того, я розумію, що він розроблений для перенесення, а на деяких інших апаратних платформах потрібні вирівняні звернення.


1

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

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


1

Я використовував NOP для автоматичного регулювання затримки, накопиченої після введення ISR. Дуже зручно забивати хронометраж.


-1

nopбуде корисним в пам'яті з пошкодженням корисного навантаження. Звичайно nop, подібне зxchg eax, eax


Інша відповідь на вже згадані слайди NOP для експлойтів з введенням коду. Так само зробив ще одну відповідь на це саме питання. Ця відповідь не згадує, наскільки вони корисні, і це не очевидно, якщо ви ще не знаєте.
Пітер Кордес,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.