Можете ли вы представить себе какое-либо законное (умное) использование для модификации кода во время выполнения (программа, изменяющая свой собственный код во время выполнения)?
Современные операционные системы, похоже, недовольны программами, которые делают это, поскольку этот метод используется вирусами, чтобы избежать обнаружения.
Все, о чем я могу думать, - это некая оптимизация времени выполнения, которая удаляла бы или добавляла некоторый код, зная что-то во время выполнения, что не может быть известно во время компиляции.
Ответы:
Есть много подходящих случаев для модификации кода. Генерация кода во время выполнения может быть полезна для:
Иногда код переводится в код во время выполнения (это называется динамической двоичной трансляцией ):
Модификация кода может использоваться для обхода ограничений набора инструкций:
Еще случаи модификации кода:
источник
Это было сделано в компьютерной графике, особенно в программных средствах визуализации в целях оптимизации. Во время выполнения проверяется состояние многих параметров и генерируется оптимизированная версия кода растеризатора (потенциально исключающая множество условных выражений), которая позволяет визуализировать графические примитивы, например, треугольники, намного быстрее.
источник
Одна из веских причин заключается в том, что в наборе инструкций asm отсутствуют некоторые необходимые инструкции, которые вы могли бы создать самостоятельно. Пример: на x86 нет возможности создать прерывание для переменной в регистре (например, сделать прерывание с номером прерывания в ax). Разрешены только константные числа, закодированные в коде операции. С помощью самомодифицирующегося кода можно имитировать такое поведение.
источник
Некоторые компиляторы использовали его для инициализации статической переменной, избегая затрат на условное выражение для последующих обращений. Другими словами, они реализуют принцип «выполнить этот код только один раз», перезаписывая этот код без операций при первом выполнении.
источник
Случаев много:
Некоторые модели безопасности ОС означают, что самомодифицирующийся код не может работать без прав root / администратора, что делает его непрактичным для общего использования.
Из Википедии:
В таких ОС даже программам, таким как Java VM, требуются права root / admin для выполнения своего JIT-кода. (Подробнее см. Http://en.wikipedia.org/wiki/W%5EX )
источник
Синтез OS в основном частично оценил программу по вызовам API, и заменить код ОС с результатами. Основное преимущество заключается в том, что исчезло много проверок ошибок (потому что, если ваша программа не собирается просить ОС сделать что-то глупое, ей не нужно проверять).
Да, это пример оптимизации времени выполнения.
источник
Много лет назад я провел утро, пытаясь отладить некоторый самомодифицирующийся код, одна инструкция изменила целевой адрес следующей инструкции, то есть я вычислял адрес ветвления. Он был написан на ассемблере и отлично работал, когда я выполнял программу по одной инструкции за раз. Но когда я запустил программу, она не удалась. В конце концов, я понял, что машина получает 2 инструкции из памяти и (поскольку инструкции были размещены в памяти) изменяемая мной инструкция уже была получена, и, таким образом, машина выполняла неизмененную (неправильную) версию инструкции. Конечно, когда я отлаживал, он выполнял только одну инструкцию за раз.
Я хочу сказать, что самомодифицирующийся код может быть чрезвычайно неприятным для тестирования / отладки и часто имеет скрытые предположения относительно поведения машины (будь то аппаратная или виртуальная). Более того, система никогда не могла совместно использовать кодовые страницы между различными потоками / процессами, выполняемыми на (теперь) многоядерных машинах. Это сводит на нет многие преимущества виртуальной памяти и т. Д. Это также аннулирует оптимизацию ветвей, выполненную на аппаратном уровне.
(Примечание - я не включаю JIT в категорию самомодифицирующегося кода. JIT переводит из одного представления кода в альтернативное представление, это не модифицирует код)
В общем, это просто плохая идея - действительно изящная, очень непонятная, но очень плохая.
конечно - если все, что у вас есть, это 8080 и ~ 512 байт памяти, вам, возможно, придется прибегнуть к таким методам.
источник
С точки зрения ядра операционной системы каждый Just In Time Compiler и Linker Runtime выполняет самомодификацию текста программы. Ярким примером может служить интерпретатор скриптов Google V8 ECMA.
источник
Другая причина самомодифицируемого кода (на самом деле «самогенерируемого» кода) заключается в реализации механизма своевременной компиляции для повышения производительности. Например, программа, которая считывает алгебраическое выражение и вычисляет его по диапазону входных параметров, может преобразовать выражение в машинный код до того, как объявить вычисление.
источник
Вы знаете старый каштан, что нет никакой логической разницы между оборудованием и программным обеспечением ... можно также сказать, что нет никакой логической разницы между кодом и данными.
Что такое самомодифицирующийся код? Код, который помещает значения в поток выполнения, чтобы его можно было интерпретировать не как данные, а как команду. Конечно, существует теоретическая точка зрения на функциональные языки, согласно которой на самом деле нет никакой разницы. Я говорю, что на e можно сделать это простым способом в императивных языках и компиляторах / интерпретаторах без презумпции равного статуса.
В практическом смысле я говорю о том, что данные могут изменять пути выполнения программы (в некотором смысле это чрезвычайно очевидно). Я думаю о чем-то вроде компилятора-компилятора, который создает таблицу (массив данных), через которую проходит синтаксический анализ, переходя из состояния в состояние (а также изменяя другие переменные), точно так же, как программа перемещается от команды к команде , изменяя переменные в процессе.
Таким образом, даже в обычном случае, когда компилятор создает пространство кода и ссылается на полностью отдельное пространство данных (кучу), можно по-прежнему изменять данные, чтобы явно изменить путь выполнения.
источник
Я реализовал программу, используя эволюцию, чтобы создать лучший алгоритм. Он использовал самомодифицирующийся код для модификации схемы ДНК.
источник
Одним из вариантов использования является тестовый файл EICAR, который представляет собой законный исполняемый COM-файл DOS для тестирования антивирусных программ.
Он должен использовать самостоятельную модификацию кода, потому что исполняемый файл должен содержать только печатные / печатные символы ASCII в диапазоне [21h-60h, 7Bh-7Dh], что значительно ограничивает количество кодируемых инструкций.
Подробности объяснены здесь
Он также используется для диспетчеризации операций с плавающей запятой в DOS.
Некоторые компиляторы будут
CD xx
выдавать с xx в диапазоне от 0x34-0x3B вместо инструкций с плавающей запятой x87. ПосколькуCD
это код операции дляint
инструкции, он перейдет к прерыванию 34h-3Bh и эмулирует эту инструкцию в программном обеспечении, если сопроцессор x87 недоступен. В противном случае обработчик прерывания заменит эти 2 байта на,9B Dx
так что последующие исполнения будут обрабатываться напрямую x87 без эмуляции.Какой протокол эмуляции с плавающей запятой x87 в MS-DOS?
источник
Ядро Linux имеет Загружаемые модули ядра , которые делают именно это.
Emacs также имеет эту возможность, и я использую ее постоянно.
Все, что поддерживает динамическую архитектуру плагинов, существенно изменяет свой код во время выполнения.
источник
Я провожу статистический анализ по постоянно обновляемой базе данных. Моя статистическая модель пишется и переписывается каждый раз при выполнении кода для учета новых данных, которые становятся доступными.
источник
Сценарий, в котором это можно использовать, представляет собой обучающую программу. В ответ на ввод пользователя программа изучает новый алгоритм:
Возникает вопрос, как это сделать в Java: каковы возможности для самостоятельной модификации кода Java?
источник
Лучшей версией этого могут быть макросы Лиспа. В отличие от макросов C, которые представляют собой всего лишь препроцессор, Lisp позволяет вам всегда иметь доступ ко всему языку программирования. Это самая мощная функция в lisp, которой нет ни в одном другом языке.
Я ни в коем случае не эксперт, но пусть один из шепелявых говорит об этом! Есть причина, по которой они говорят, что Лисп является самым мощным языком, а умные люди - нет, что они, вероятно, правы.
источник