Перейти к содержанию
    

Самомодифицирующийся код в экосистеме Cortex-M.

Ну хорошо - придумайте своё название. :rolleyes: Не в терминах суть.

Динамически генерируемый код - вот так будет лучше, на мой взгляд.

Отладка такого кода будет адской.

 

Нет, я лучше возьму i.MX RT и закрою тему одним махом.

 

Кста, кто придумает для RT лучшую аппликацию получит плату с RT бесплатно.

Может там ваша динамика и прокатит. :biggrin:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Cortex, да и почти все arm чипы - используют внеочередное исполнение кода. Он может загружать адреса для двух функций одновременно. Просчитывать данные которые будут применяться где-то внутри функции до её реального вызова. Размазывать циклы на всю портянку. Обращать переменные в другое значение чем было назначено в пользовательской программе -без потери целостности алгоритма, и ещё много много чего. Это их главная фишка.

Фактически код в отладчике выполняется по строкам программы, а в реальности прыгает как бешеный сайгак.

Вообще-то тема про Cortex-M, а не старшие Cortex-A. И даже на последних это нисколько не мешает писать самомодифицирующийся код: сбросили кэш, установили барьеры - и вперед.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использовал хранимые в ОЗУ участки кода, которые загружались извне в виде обезличенных произвольных массивов данных в ходе работы системы, а в местах обращений к ним трактовались как подпрограммы с заранее известным адресом точки входа. А что ему может помешать так работать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть мысль использовать самомодифицирующийся код для оптимизации решения одной задачи.

Оптимизация по скорости? А то я хотел microPython предложить, для best-in-class супер простой самомодификации кода.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос к ТС - а каков предполагаемый размер генерируемой функции? Может имеет смысл просто в RAM зарезервировать буфер и в нем генерировать код. Если функция генератор уже создана, то можно смело пробовать...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мой опыт показывает что оптимизация по скорости самомодифицирующимся кодом неэффективна.

Потому что очевидно, что такой код будет находится в ОЗУ.

А в Cortex-M3,M4 у меня код быстрее выполнялся из flash тк у Atmel там 128 битная шина доступа на частоте более 25МГц...

Т.е. даже при наличии кеша данные или код из flash обрабатывались быстрее чем из озу.

А поскольку флеша пихают теперь в кристалы просто дикое количество - то необходимости что-то копировать в ОЗУ нет, разве что для снижения потребления.

 

Что касается ускорения - проще расписать циклы.

 

Есть ещё TDM для ускорения и на старых ARM - режим FIQ со своим набором регистров.

 

Единственный оправданный вариант применения самогенерирующегося кода - некий софтпроцессор.

Т.е. программа в МК зашита давно, но иногда удалённо в него прилетает новая функция и он её выполняет.

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

_4afc_, не стоит быть столь категоричным. Если говорить в общем, а задачу ТС поставил именно "а поговорить", то этих кортексов в природе хоть попой кушай и у всех разные скоростные характеристики блоков памяти. Рассуждать где что разместить можно только после того как будет произнесено вслух название чипа.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Использовал хранимые в ОЗУ участки кода, которые загружались извне в виде обезличенных произвольных массивов данных в ходе работы системы, а в местах обращений к ним трактовались как подпрограммы с заранее известным адресом точки входа. А что ему может помешать так работать?

Это называется "оверлеи". Пользовал такое на LPC4370, в котором нет флешь, ОЗУ не так уж много, и были оверлеи (редко выполняемые), подгружаемые из внешней SPI-флешь в один и тот же буфер в ОЗУ.

Тут несколько иная задача. AlexandrY уже придумал более точное название: "Динамически генерируемый код".

 

Оптимизация по скорости? А то я хотел microPython предложить, для best-in-class супер простой самомодификации кода.

По скорости. Ну если у меня оптимизация на таком уровне (генерация маш.кода), то это совсем другой порядок скоростей, чем смогут всякие явы и питоны :laughing:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Имхо сейчас время такое что проще взять более мощный чип. Вообще полиморфы родились как способ обдурить антивирус. Разработчики, которым нужна подобная оптимизация (без криминала) обычно делают N *.dll'ек, которые загружаются исходя и потребностей.

Так что на мой взгляд толстый проц с большим кол-вом флеша и с помощью темплейтов скомпилировать все комбинации кода.

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

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вопрос к ТС - а каков предполагаемый размер генерируемой функции? Может имеет смысл просто в RAM зарезервировать буфер и в нем генерировать код. Если функция генератор уже создана, то можно смело пробовать...

Так и есть. Размер функции переменный, в зависимости от заданных входных аргументов: от одной команды BX LR (пустой список) до примерно полусотни команд.

Генератор сейчас в процессе создания B)

 

А в Cortex-M3,M4 у меня код быстрее выполнялся из flash тк у Atmel там 128 битная шина доступа на частоте более 25МГц...

А теперь возьмите калькулятор в руки и посчитайте: 128/8*25=400МБ/сек; т.е. - если CPU работает на хотя-бы 100МГц тактовой, то 4-байтовые чтения из 0-wait-state ОЗУ уже дадут такую скорость. Так что на частотах >100МГц выполнение из ОЗУ у Вас должно быть быстрее. Конечно тут нужно ещё учесть влияние кеша FLASH и пересечение prefetch-ей с обращениям за данными по этой же шине (можно вынести такой код в отдельный регион SRAM с отдельной шиной для скорости).

 

Но у меня МК с шиной к FLASH программ == 256 бит, кешем FLASH и тактовой 144МГц. Но зато есть регион PSRAM (program SRAM) с отдельной шиной к нему от ядра. И существенной разницы в скорости выполнения между FLASH и PSRAM я не замечаю.

 

Да и дело не в этом даже: я писал выше уже, что ускорение я ожидаю не за счёт каких-то шин и прочего, а за счёт того, что динамически сгенерённый код будет в разы меньше, чем статический.

Потому что произойдёт оптимизация на уровне алгоритма. Так что влияние кешей и пр. тут ничтожно мало.

 

Т.е. даже при наличии кеша данные или код из flash обрабатывались быстрее чем из озу.

А поскольку флеша пихают теперь в кристалы просто дикое количество - то необходимости что-то копировать в ОЗУ нет, разве что для снижения потребления.

Ещё раз внимательнее перечитайте мои посты: я уже много раз написал, что говорю не о копировании заранее подготовленных кусков (оверлеев) в ОЗУ, а о динамической генерации кода.

 

Рассуждать где что разместить можно только после того как будет произнесено вслух название чипа.

XMC4700 :rolleyes:

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А теперь возьмите калькулятор в руки и посчитайте: 128/8*25=400МБ/сек; т.е. - если CPU работает на хотя-бы 100МГц тактовой, то 4-байтовые чтения из 0-wait-state ОЗУ уже дадут такую скорость. Так что на частотах >100МГц выполнение из ОЗУ у Вас должно быть быстрее. Конечно тут нужно ещё учесть влияние кеша FLASH и пересечение prefetch-ей с обращениям за данными по этой же шине (можно вынести такой код в отдельный регион SRAM с отдельной шиной для скорости).

 

Но у меня МК с шиной к FLASH программ == 256 бит, кешем FLASH и тактовой 144МГц. Но зато есть регион PSRAM (program SRAM) с отдельной шиной к нему от ядра. И существенной разницы в скорости выполнения между FLASH и PSRAM я не замечаю.

 

Да и дело не в этом даже: я писал выше уже, что ускорение я ожидаю не за счёт каких-то шин и прочего, а за счёт того, что динамически сгенерённый код будет в разы меньше, чем статический.

Потому что произойдёт оптимизация на уровне алгоритма. Так что влияние кешей и пр. тут ничтожно мало.

У меня для ускорения, часть алгоритма была заранее посчитана и использовались таблицы поиска (LUT).

Так вот, наибольшей скорости я добился при нахождении LUT во FLASH, а кода в ОЗУ в виде расписанных циклов.

 

В микроконтроллерах Атмела wait-state устанавливается на всю систему памяти и на FLASH и на ОЗУ (хотя теперь про это не пишут)

Поэтому для того чтобы выполнять программу с 0-wait-state из ОЗУ - надо сгенерить весь исполняемый код в ОЗУ и

на 100МГц во флеш даже носа не показывать, даже ради таблицы векторов.

 

При этом у Атмела невозможно налету поменять коэффициент деления тактовой, любое изменение частоты только через перезапуск PLL который ожидаеш на медленных RC генераторах. B вообще PLL настолько кривой - что его лучше не трогать. PSRAM - наверно выход, но PSRAM и MMU както бедно документированы.

 

Вероятно генерация (даже распаковка из внешней FLASH), при отключенной внутренней, в небольшое PSRAM на максимальной частоте кусков кода при 0-wait-state - это хорошая экономия ОЗУ под буфера данных...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Интересная тема для меня, тема СМК. Ни разу не применял, однако небольшие размышления в этой части заставили признать, что в практике программирование были моменты, где удобно было бы иметь самомодификацию. Приведу пример, где бы я использовал СМК (опять же, в реальной практике была уйма таких задач).

Пусть есть некий цикл, но внутри этого цикла подряд идут условно выполняемые команды:

while(условие)
{
    if(условие 1)
        инструкция 1;

    if(условие 2)
        инструкция 2;

    if(условие 3)
        инструкция 3;

    ...

    if(условие N)
        инструкция N;
}

Так вот, условие 1, условие 2, условие 3, ..., условие N являются флаговыми переменными и определяются где-то выше по коду. В итоге ассемблерный код будет содержать условные операции выполнения и переходы, если инструкции не представляются в машинных кодах до 4 реальных инструкций для Cortex-M. Это долго, на это тратятся такты процессора, сбрасывается конвейер инструкций... в общем, одни минусы. В приложениях с хитрой математикой или логикой, которую надо быстро просчитать, было бы удобно использовать СМК в следующем виде:

1. Просчитать все условные флаги.

2. На основании этих флагов сформировать СМК-последовательность инструкций без условных инструкций.

3. Отдать эту последовательность на выполнение.

 

В итоге существенно сократится объем ассемблерных инструкций, с учетом того, что некоторые условные инструкции идут по 2-3 такта, а после модификации останутся только "нужные" инструкции. Останется только условие продолжения цикла и нужные команды, без этих паршивых проверок. Я ж, надеюсь, никому святую тайну не открыл? :biggrin: Повторюсь, это лишь мои хотелки, было много ситуаций где хотелось бы сейчас это реализовать, но оно работает да и зачем туда лезть, тем более там, где во времени я сильно не ограничен...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

2. На основании этих флагов сформировать СМК-последовательность инструкций без условных инструкций.

Так тут будет тот же

if()...if()...if()...

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Есть мысль использовать самомодифицирующийся код для оптимизации решения одной задачи.

Именно самомодифицирующийся - программа строит часть самой себя по некоему алгоритму, а не просто копирует куски кода из одной области памяти в другую.

И вот я что-то не смог вспомнить чтобы здесь на форуме вообще когда-то поднималась эта тема.

Кто-то вообще использует такой код на ARM-ах в своих проектах? Просто интересно... :rolleyes:

Может Вам будет проще в контроллере python поднять ? Или любой другой интерпретатор...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Может Вам будет проще в контроллере python поднять ? Или любой другой интерпретатор...

действительно, интерпретатор намного эффективнее и проще в реализации.

 

Изменено пользователем twix

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...