|
|
Регистрация Восстановить пароль |
Повторная активизация e-mail |
Регистрация | Задать вопрос |
Заплачу за решение |
Новые сообщения |
Сообщения за день |
Расширенный поиск |
Правила |
Всё прочитано |
|
|
Опции темы | Поиск в этой теме |
06.07.2016, 20:23 | #1 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
Полиморфизм и самомодификация
Заинтересовала эта тема..
Интригует то, что можно писАть мутирующий код, который при каждом запуске будет отличаться содержимым (опкодами), при той-же функциональности. Хороший фундамент для защиты приложений, но непонятен один вопрос! Что значит "команды в конвейере"? В источниках пишут, что "Если команда находится уже в конвейере, то её нельзя менять/изменить!". Почему? Что значит это определение? Например, я подготовил регистры перед вызовом прерывания. Это они что-ли "..в конвейере"? Объясните, кто в курсе.. И может у кого-нибудь есть примеры самомодифицирующихся кодов, чтоб накопить идей. Вот пара примеров, как сбить с толку начинающих крэкеров: Код:
Нашедшего выход - затаптывают первым..
|
07.07.2016, 00:35 | #2 |
Старожил
Регистрация: 13.07.2012
Сообщений: 6,331
|
Потому что процессор уже эту инструкцию прочитал. Каждая инструкция выполняется в несколько шагов и один из первых это считывание из памяти. Потом может пройти довольно много времени до того, как эта инструкция реально выполнится. В этот момент менять уже бесполезно.
|
07.07.2016, 08:56 | #3 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
waleri, а как узнать какие команды находятся в конвейере на данный момент? Есть какая-нить закономерность, или это напрямую зависит от архитектуры ЦП (скольки уровневый у него конвейер)?
Нашедшего выход - затаптывают первым..
|
07.07.2016, 09:07 | #4 |
Лис
Старожил
Регистрация: 18.09.2015
Сообщений: 2,409
|
Это в 386 - 586 где кэш был внешней микросхемой были такие проблемы. А после ЦПу научился нормально отслеживает изменение команды в кэше. Заботиться об конвейре не надо. Единственное требование это чтобы изменение команды происходило атомарно. Т.е. модифицируемая команда не должна попадать на границу кэш линии. А если попала, то использовать атомарные инструкции для модификации CMPXCHG/CMPXCHG8B/CMPXCHG16B.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал . |
07.07.2016, 11:06 | #5 |
Лис
Старожил
Регистрация: 18.09.2015
Сообщений: 2,409
|
Перечитал маны. Пишут что на новых ядрах могут не отследить в случае если изменяют по одному линейному адресу а выполняют по другому. Т.е если разные страницы ссылаются на одну физическую память и вы поменяете код в одной странице, а выполнять будете в другой. То процессор не отследит. Но честно пример надуманный. Так как в любом отладчике прежде чем вернуть управления мы выполним ret или jmp, что является десерализационной командой.
И на будущее Intel рекомендует, так как система кешей становятся более запутанной рекомендуют использовать jmp или cpuid(или любую десерализационной) для предотвращения проблем. От будущего этот совет не спасёт. Либо все также и останется медленным либо jmp и ret не будут десериализационными командами.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал . Последний раз редактировалось Pavia; 07.07.2016 в 11:10. |
07.07.2016, 11:24 | #6 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
Pavia, спасибо!
Значит если размер кэш-линии равен 16..64 байт (один параграф памяти), то я не должен менять значения регистров из участка кода, лежащего в этим диапазоне. Я правильно понял? Это в идеале, ..без применения атомарных инструкций. Если-же моя команда модификации лежит внутри одной кэш-линии от изменяемой инструкции, то я должен искусственно превратить инструкцию в атомарную, добавив префикс "LOCK" (опкод F0h), т.к. на одних стандартных/атомарных инструкциях типа CMPXCHG8B далеко не уедешь. Просто каша в голове, а хочется чтобы код был портабельным. Пусть у меня есть такой участок кода.. По-моему мнению здесь ошибки нет, хотя команды лежат внутри кэш-линии, но они не находятся в конвейере: Код:
Код:
Нашедшего выход - затаптывают первым..
|
07.07.2016, 12:36 | #7 | |||||
Лис
Старожил
Регистрация: 18.09.2015
Сообщений: 2,409
|
R71MT
Цитата:
Цитата:
Цитата:
LOCK - бесполезный прёфикс. Он работает далеко не всегда:Не применима к MOV. Поэтому все и использую xchg или CMPXCHG16B. 16 байт максимальная длина инструкции. Как решить проблему? Очевидно что выронить инструкции. В разных ассемблерах по разному. Где макрос align, там подставлялись NOP нужной длины. К примеру точно не помню, но в MASM метки автоматически выравнивались по указанному значению _TEXT segment para public 'CODE' para- парагроф 16 байт. А TASM это значение использовал только для функций. Цитата:
Просто есть рекомендации для будущих процессоров. Цитата:
Но есть инструкции которые сбрасывают конвейр. Такие как CPUID. После них процессор ждет пока все стадии конвейра снова загрузятся новыми данными. JMP опять таки. Не всякий JMP годится. Как минимум надо - JMP FAR [mem] Хотя для реального режима там были исключения.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
У дзен программиста программа делает то что он хотел, а не то что он написал . Последний раз редактировалось Pavia; 07.07.2016 в 12:39. |
|||||
07.07.2016, 15:24 | #8 |
Старожил
Регистрация: 13.07.2012
Сообщений: 6,331
|
LOCK неприменима к MOV потому что MOV инструкции это не нужно - она атомарна сама по себе. Для XCHG нужно, потому что на деле есть две операции - чтение, потом запись.
Я не уверен, что конвейр вообще следит за кешем но это легко проверить запустив самомодифицрующийся код без отладчика. |
14.07.2016, 14:29 | #9 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
Накачал себе инфы и вроде с конвейером картинка чуть прояснилась..
Чтобы вопрос не повис в воздухе, попытаюсь отпоститься по результу из того, что нашёл. Современные ЦП начиная с "Pentium Pro" вполне могут сами разобраться с содержимым конвейера. В них применяются нелинейные алгоритмы с ветвлением, в которых обработкой инструкций параллельно занимаются 6 независимых/исполнительных блоков. При надобности, один из них может перезагрузиться, не мешая работе другого. Задержки всё-же имеются, но они не столь значительны. Значит конвейер.. Процессоры 8086 до 386 не имели встроенного конвейера, и в каждый момент времени выполняли только одну инструкцию. Этот алгоритм дошёл до наших дней и имеет такой вид: загрузка(Fetch), декодирование(D1), вычисление операндов(D2), выполнение(EX) и запись результата в регистры/память, т.н. отставка(WB): Код:
Код:
Такая схема повышает производительность, но имеет и свои недостатки. Они проявляются когда, например, в конвейер попадает блок(If-Else), или-же когда одна инструкция требует результата другой. Такое явление называется ступор, или пузырь в конвейере (Pipeline Bubble). Декодер останавливается и ждёт до тех пор, пока первая инструкция не дойдёт до уровня(WB) и вернёт ему свой результат. Только после этого вторая инструкция может продолжить свой путь по конвейеру. Решить эту проблему удалось в процессорах начиная с 'Pentium Pro' и выше. Инженеры применили в них 12-уровневый конвейер. Очевидно, что с такой длинной проблема ступора стала более актуальной, если-бы не введение принципиально нового ядра с внеочерёдным (Out-of-Order, OOO) и упреждающим (Speculative) исполнением команд. Конвейер так-же подвергся переработки. Раньше он работал по линейному алгоритму, в котором все инструкции шли одна-за-другой. Теперь-же, в него ввели нелинейные пути, и проблема ступора стала не так заметна. Суть была в том, что декодер новых ЦП может предсказать появление ветвления (например вызов функции) и начать загрузку инструкций заранее. Вместо обработки лишь одной инструкции по указателю(IP), сегодняшние ЦП могут декодировать 4- и более инструкций за такт, разбивая одну инструкцию на несколько микроопераций (micro-ops). Теперь, множество операций выполнялись одновременно. Одна инструкция могла читать из регистра, пока другая в него пишет. Но запись в регистр может изменить значение, нужное другой инструкции! Чтобы избежать подобных ошибок, были введены внутренние (скрытые от программиста) регистры, которыми подменялись оригинальные РОН. Такой подход позволял выполнять сразу 7 микроопераций за такт, с помощью которых и вычислялся нелинейный путь. Если все нужные данные доступны, то они обрабатываются одновременно на 6-ти исполнительных блоках (execution unit). Если данные недоступны, выполнение откладывается до их готовности, пока выполняются другие/готовые микрооперации. Таким образом долгие операции не блокируют быстрые и последствия ступора конвейера уже не так печальны. Сегодняшнее OOO-ядро так-же содержит 6 исполнительных блоков, но они немного изменились. Теперь каждый блок специализирован для конкретных микроопераций, позволяя выполнять работу быстрее, по сравнению с блоками общего назначения. В идеальных условиях нынешнее OOO-ядро может обрабатывать 11 микроопераций за такт. *********************************** ************* Меня интересовало: не вызовет-ли подмена инструкций в конвейере, крах всей программы? Оказывается нет. Лишь-бы поинтеры не указывали после этого в космос. В наше время ЦП обладают достаточным интелектом, чтоб разобраться в таких ситуациях.
Нашедшего выход - затаптывают первым..
|
14.07.2016, 14:31 | #10 |
Участник клуба
Регистрация: 16.06.2011
Сообщений: 1,428
|
С кэшем инструкций дела (на мой взгляд) обстоят по-проще..
ЦП читает инструкции блоками, чуть дальше текущего указателя(IP) и помещает их в свой кэш. Кэши современных процессоров имеют размер 32К, куда вполне может вместиться вся DOS-программа. Эти 32 кило разбиваются на линейки по 64 байт (cache line), в каждой из которых имеется поле(tag) с адресом в ОЗУ, от куда была скопирована эта линейка. Смотрю на свойства своего ЦП: 32К/64 = 512. Именно столько кэш-линеек (и столько-же тэгов к ним) присутствует в кэше моего процессора: Код:
Подскажите, в ту-ли степь меня несёт? Буду благодарен, если укажите на ошибки, т.к. это то, как я понимаю весь/этот процесс.
Нашедшего выход - затаптывают первым..
|
|
Похожие темы | ||||
Тема | Автор | Раздел | Ответов | Последнее сообщение |
Полиморфизм | Anubys | Помощь студентам | 1 | 26.12.2011 20:42 |
Полиморфизм | Zorgan | Visual C++ | 22 | 29.08.2011 12:23 |
Полиморфизм | MasterSporta | Общие вопросы C/C++ | 3 | 10.04.2011 23:46 |
полиморфизм | slayerblya | Общие вопросы C/C++ | 1 | 27.02.2011 01:43 |
Полиморфизм | mister2010 | Общие вопросы C/C++ | 30 | 24.05.2010 01:07 |