Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Средства для упрощения создания полиморфных модификаций…
Форум разработчиков электроники ELECTRONIX.ru > Cистемный уровень проектирования > Операционные системы > Программирование
Дон Амброзио
Средства для упрощения создания полиморфных модификаций фрагментов кода

Вопрос шибко заумный, но очень актуальный.

Попытаюсь объяснить, в чём суть. Надеюсь, что у меня это получится.

Объяснение построю на примере решения конкретной задачи.

Имеется 4 флага состояния некоего вычислительного процесса. Соответственно имею 16 возможных состояний вычислительного процесса. А значит 16 ветвей алгоритма. Пишу на АСМе. Но это не существенно для обсуждаемой проблемы – так как с подобными проблемами мы сталкиваемся при написании программы на любом языке: СИ, СИ++ и т.п.

Каждая ветвь представляет собой фрагмент кода, который отличается от любого другого из 16-ти в 3-4-х местах. Например, вместо команды SUBI, команда SBCI, или вместо регистра ZH в команде используется XH. Сам же размер кодовых фрагментов порядка 50-ти ASM-команд.

Так вот. Хотелось бы не переписывать каждый раз 50 команд во всех 16-ти ветвях, а просто указать директивой какой кодовый фрагмент нужно взять за базовый и в каких местах и что нужно заменить.

Макросами не получиться. Потому что изменения каждый раз в разных местах – получается более 30-ти параметров. Указывать при вызове макроса все его 30 параметров вряд ли можно назвать упрощением решения задачи.

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

Т.е. в каких-нибудь языках программирования средства, упрощающие и облегающие создание полиморфных модификации фрагментов кода? Если есть, то что это за средства.
Дон Амброзио
Мне нужна возможность объявить любой фрагмент кода прототипом (указав с помощью специальных маркеров его начало и конец и задав ему имя) для какого-либо другого фрагмента кода (причём границу чтоб можно было установить где угодно - вплоть до "разрезания" команды) и возможность задать внутри этого фрагмента-прототипа участки(опять же с помощью неких маркеров), которые будут заменены в порождаемых от него фрагментах кода. И порождение от фрагмента-прототипа нового фрагмента кода будет выглядеть как вызов обычного макроса с заданными фактическими параметрами

Пример.

mov R2 , R3
<X ldi R16 , <0 $66 0>
sub R16 , <1 R2 1> X>

Здесь скобками '<' и '>' выделяем граница фрагмента прототипа и его изменяемые части

X - название прототипа
0 - номер изменяемой части внутри прототипа


тогда вызов

X 0:$77

где 0: - номер части, которую мы хотим модифицировать ( часть 1 - не хотим - поэтому её не указываем !!!)

породит код :

ldi R16 , $77
sub R16 , R2

а вызов

X 0:$53 1:R7

породит код :

ldi R16 , $53
sub R16 , R7


На маленьких фрагментах кода выигрыш не заметен.

Но если у Вас больше десятка фрагментов кода, каждый из которых имеет размер в несколько десятков строчек и каждый из этих фрагментов может быть получен из некоего прототипа путём изменения нескольких строчек, то выигрыш от описанной мной фичи будет просто огромна
Rst7
Вменяемый макроассемблер поддерживает макроопределения с переменным количеством аргументов. Например посмотрите на асм от IAR (рыть в описании ассемблера от цитаты и далее)
Цитата
Use REPTI to assemble a block of instructions once for each string in a series of strings.
Strings containing commas should be enclosed in quotation marks.


И т.д.
Дон Амброзио
Цитата(Rst7 @ Jun 22 2008, 21:13) *
Вменяемый макроассемблер поддерживает макроопределения с переменным количеством аргументов. Например посмотрите на асм от IAR (рыть в описании ассемблера от цитаты и далее)
И т.д.

Насколько я понял вместо отсутствующих аргументов ставится "commas", то бишь запятые. А если у меня 30 параметров? а надо изменить только 16-й.. То как? Отсчитать 15 запятых, записать фактическое значение 16-го аргумента, а затем ещё 14 запятых присобачить?

ИМХО записть X 0:$53 1:R7 мне кажется более читабельной чем X ,,,,,,,,,,,,,,,,,,$53,,,,,,,,,,,R7,,,,,,
и не дай Бог ошибёсся в кол-ве запятых

А можно в в качестве фактических парамеметров передавать произвольные многострочные куски исходника?
_Pasha
Цитата(Rst7 @ Jun 22 2008, 20:13) *
Вменяемый макроассемблер поддерживает...


1. У невменяемого AVRASM можно хитро комбинировать #define .macro
2. Доктор, а как Вы относитесь к AVRA ?
Лично я когда-то попытался в нем с его фичами что-то изобразить, но непреодолимый страх, что это все взглючит, не позволил продолжить правое(левое) дело... прошло два года.
А ведь там есть перегруз макросов. И очень может быть, оно даже полезнее окажется, чем то, что Вы изначально хотели. Имхо, конечно.
Дон Амброзио
Цитата(_Pasha @ Jun 22 2008, 22:05) *
1. У невменяемого AVRASM можно хитро комбинировать #define .macro

Да фкурсе.. А также #ifdef #undef и т.п. Юзаю вовсю все мыслимые и немыслимые их комбинации.. Очень упрощают жисть.. Даже объекто-ориентированное программирование реализовал на АСМ-е .. В частности полиморфизм идентификаторов, когда один и тот же идентификатор обозначал похожие, но всё же различающиеся сущности..

Но то что я описал выше, к сожалению, sad.gif не позволяют реализовать


Цитата(_Pasha @ Jun 22 2008, 22:05) *
2. Доктор, а как Вы относитесь к AVRA ?

Первый раз о нём слышу
Дон Амброзио
Тут тоже обсуждается эта тема
733259
Насколько я понял - требуется не переписывать 16 раз, чтобы не заниматься мех. работой и не ошибиться.
В таком случае (ИМХО) всего проще сделать "болванку" - общий кусок, в нем отметить заменяемые места какой-нибудь не встречающейся в коде последовательностью, типа "<<>>", а затем получать из нее нужный исходник скриптом на perl (если не нравится - что-то другое).
Perl здесь идеален регулярными выражениями и простотой скриптописания.
Нужные правила легко вставляются в makefile, в скрипте можно сделать любые навороты.
Плюс - пользуетесь привычным инструментом, не надо переходить на что-то ради встроенных возможностей.
Я таким образом генерю таблицы, перекодирую строки в кодировку lcd и т.п.
_Pasha
Гуглим по словам метод раскрутки компилятор bootstrapping
И курим все, шо там есть.
Я тоже rtfm. Интересно. smile.gif

PS начать полезно с http://www.ict.edu.ru/ft/005128//ch3.pdf
alx2
Цитата(Дон Амброзио @ Jun 22 2008, 22:03) *
Мне нужна возможность объявить любой фрагмент кода прототипом (указав с помощью специальных маркеров его начало и конец и задав ему имя) для какого-либо другого фрагмента кода (причём границу чтоб можно было установить где угодно - вплоть до "разрезания" команды)
man sed
_Pasha
Цитата(alx2 @ Jun 23 2008, 22:12) *
man sed


Дык тогда любой редактор с текстовыми макросами smile.gif
XVR
Цитата(alx2 @ Jun 23 2008, 23:12) *
man sed
Тогда уж man m4. Sed здесь не очень подойдет - он обрабатывает исходные файлы построчно, сделать ему макрос на несколько строк очень геморойно.
alx2
Цитата(_Pasha @ Jun 24 2008, 01:53) *
Дык тогда любой редактор с текстовыми макросами smile.gif
Мне кажется, инструмент должен более-менее соответствовать масштабу задачи. Запускать perl или vim каждый раз, когда надо в каком-то файле сделать s/шило/мыло/ можно, конечно, но ИМХО очень уж избыточно. Не та весовая категория. smile.gif
Цитата(XVR @ Jun 24 2008, 13:45)
Тогда уж man m4. Sed здесь не очень подойдет - он обрабатывает исходные файлы построчно, сделать ему макрос на несколько строк очень геморойно.
Согласен, для многострочных подстановок m4 - более адекватный инструмент.
733259
Цитата(alx2 @ Jun 24 2008, 17:27) *
Мне кажется, инструмент должен более-менее соответствовать масштабу задачи. Запускать perl или vim каждый раз, когда надо в каком-то файле сделать s/шило/мыло/ можно, конечно, но ИМХО очень уж избыточно. Не та весовая категория. smile.gif
Не понятно, что считать избыточностью.
Perl запускается моментально и отрабатывает много быстрее компилера. Просто еще одно правило для make.
Цитата
Согласен, для многострочных подстановок m4 - более адекватный инструмент.
Наиболее адекватен тот инструмент, на котором скрипт быстрее пишется.
Или просто более знакомый, привычный.
Дон Амброзио
Докладываю.

Решил проблему с помощью препроцессорных директив #include и #define.

Удалось сократить размер исходника с 890 строчек до 278 строчек при упрощении его структуры и увеличении читабельности за счёт того, что явно выделены отличия порождаемых фрагментов от прототипа. Также удалось с помощью применения такого подхода наконец-то похерить все ошибки, возникавшие раньше из-за не внимательности при переписывании/копипастинге по 16 раз одних и тех же мелких кусочков кода. Также удалось увеличить лёгкость внесения изменений.

Реализовал парадигмы «объектно-ориентированного» и одновременно «порождающего» программирования. У меня в коде прототипа используются виртуальные метки, переменные, константы, …., вообще произвольные фрагменты текста исходника.

Сам прототип оформил как отдельный файл, а порождение его полиморфных модификаций реализовал так.

1.Линкуем виртуальные идентификаторы с помощью директив #define
2.#include “PrototipFile”
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.