ARM: GNU AS: Проект: Среда для программирования на ассемблере (Самодел на Delphi)

Начиная программировать на языке ассемблера для микроконтроллеров ARMпервое, с чем вы столкнетесь — это отсутствие какой либо среды для программирования (c первым проектом, программами для компиляции и сборки я уже разбирался). Причем бытует мнение, что для ассемблера ничего кроме блокнота и не нужно (максимум, «для гурманов» сообщество предложит использовать редактор с подсветкой кода). И этот подход в принципе имеет место быть — ровно на столько, на сколько удобно писать программы на С++ в блокноте — то есть до того момента, как вы перейдете от программ «Hello, Word» к чему то более сложному.

Некоторое время назад я высказал предложение о необходимости написания среды разработки (или хотя бы редактора) для программ на ассемблере, но в ответ не услышал ничего. Значит, нужно написать среду самому. Понятно, что это не будет уровень современных сред программирования, над которыми трудятся целые коллективы разработчиков (да и опыта у них намного больше чем у меня), но я и не ставлю цель конкурировать с ними по «навороченности» — мне всего лишь нужна среда для комфортного программирования на ассемблере.

Если вам нужно тоже самое и нужно именно «ехать, а не шашечки» — тогда добро пожаловать под кат.
Я никогда не писал сред разработки (да и на дельфях у меня опыт программирования мал) — поэтому решил создавать среду последовательным написанием редактора кода с последующим его усложнением по требованию/желанию и превращением в полноценную (в моем понимании) среду разработки на языке ассемблера.

Для начала отвечу на вопрос «почему все таки я пришел к написанию новой программы, а не использую готовые редакторы с подсветкой кода?»
Ответ прост: дело в том, что для программирования на языке ассемблера собственно подсветка кода — это функциональность скорее желательная, чем нужная — просто потому, что в каждой строке кода может быть только одна инструкция ассемблера, следовательно подсветка инструкций практически ничем не облегчает труд программиста на ассемблере.

Я же хочу получить редактор с функциональностью которая действительно бы помогала писать программы.
Поскольку я уже писал программы на ассемблере (в том числе начал это делать и для ARM) то из своих «хочу» выделил следующую функциональность которая по моему мнению будет востребована:

  1. Подсветка кода ассемблера с проверкой правильности синтаксиса команд (то есть не просто подсветили инструкцию ассемблера с суффиксами LDR или LDRD, а еще и проверили правильность введенных аргументов команды)
  2. Авто дополнение вводимого кода (PUSHPOP, IT — IT Block, и т. д.)
  3. Контроль глобальных и локальных меток
  4. Подсказка по инструкциям ассемблера
  5. Контроль параметров подпрограмм
  6. Поддержка программ как модулей с возможностью их добавления и удаления
  7. Контроль в редакторе опций условного исполнения
  8. Перенаправление сообщений консоли на среду, компиляция и компоновка при помощи GNU AS
  9. Файл- менеджер проекта с крупными значками
  10. Закладки в файл менеджере (переход в нужную папку одним кликом)
  11. Переход на метку программы в редакторе
  12. Автоматическое формирование списка констант модуля и дописывание в начало
  13. Система помощи по регистрам настройки микроконтроллера
  14. Мастеркода (автосоставитель кода) — например для настройки GPIO, SPI, DCMI и т.д.
  15. Эмуляция исполнения кода
  16. Настраиваемые окна среды (все!, а не только окно редактора)
  17. Отладка (пока не понимаю как, но как задача висит)
  18. контроль за правильностью кода: (выдавать предупреждение при попытке использовать BL в подпрограмме без предварительного сохранения регистра LR, выдавать предупреждение при PUSH / POP командах в случае если список регистров не совпадает)


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

Первое за что я взялся — это интерфейс — в самом начале проекта я не стал «мудрить» и просто решил использовать MDI для построения среды: у меня есть главное окно, и каждый новый редактор открывается как дочернее. Такое решение мне нравиться больше чем SDI когда используются вкладки в редакторе кода — очень часто бывают ситуации когда редактируя один файл нужно подсмотреть что написано в другом — и приходиться подглядывать во второй файл либо переключаясь между вкладками (что очень быстро утомляет), либо открывая этот второй файл в другом редакторе (какой нить Notepad или Far) и смотреть там…
Мне же больше по душе возможность сделать так:
680f7d17b64046e48e12d0f8f5d1bef4.png
По большому счету — уменьшив шрифт можно разместить так и три окна — думаю в определенных случаях это будет удобно и востребовано. Поэтому такой интерфейс был взят за основу. Если кто то знает более удобный (или есть еще какие то соображения) — готов выслушивать.

Дальше начал писать редактор программы на языке ассемблера.
Первая задача которую я реализовал — это контроль за метками в программе.
Это очень удобно, поскольку во-первых позволяет сформировать список меток, во-вторых, сразу оповещать, что набранная метка уже объявлена:
fa12e780cd4a4812bc7c5273eaed51bc.png
Дополнительно появилась возможность по двойному клику на имени метки в списке сразу перейти на нее.
Так же планируется сделать добавление метки в программу выбором из списка
674def925bbb42bebc1f1f403de9b71a.png

Следующая задача определение объявления константы и обработка математических выражений в значениях.
В настоящий момент программа распознает арифметические действия, причем в качестве операндов могут быть использованы как числовые значения (десятичное, шестнадцатеричное, двоичное число), так и имена меток и других констант
d1e2f924e2094635ab28e2bb477417a2.png
Известная бага — помоему не правильно определяется операция инверсии (!) — поправлю позже

Далее, если заглянув в Programming manual ARM процессоров — можно узнать, что у ARM разнообразие команд перемешено с разнообразием синтаксиса этих команд… и простые команды пересылки из регистра в регистр MOV R0, R1 могут запросто превратиться в пересылку со сдвигом: MOV R0, R1, LSR 19. Разбор синтаксиса команд для ARM процессора оказался интересной задачей! Поиск по русскоязычному интернету каких то примеров и подходов к такой задаче не дал — пришлось изобретать самому:

Каждую команду ARM процессора кодирую в виде строки с использованием определенных правил:

  • \ — указывает на символ который должен быть обязательно встречен, символ указывается после \
  • _ — обязательный символ пробел (0×20) или таб (0×09)
  • [] — указывает на обязательно встречающееся одно из сочетаний
  • {} — указывает на необязательно встречающееся сочетание
  • () — указывает на сочетание которое может повторяться
  • | — указывает что далее идет один из вариантов сочетаний (используется для [],{},())
  • * — пропуск пробелов и табов
  • # — вариант окраски для символов которые считаются верными
  • s — строка заключенная в кавычки
  • v — объявление константы
  • e — расширенное значение: число, константа, метка
  • $ — указывает имя правила описанное в этом же файле


Номера цветов распределил следующим образом:

  • 0: ошибка в тексте
  • 1: примечание
  • 2: метка
  • 3: директива
  • 4: команда
  • 5: число
  • 6: константа
  • 7: математическое действие и знаки
  • 8: скобки группировки
  • 9: строка

После этого можно написать правило для проверки правильности условия исполнения команд:
$cond: #4 [ |\e\q |\n\e |\c\s |\h\s |\c\c |\l\o |\m\i |\p\l |\v\s |\v\c |\h\i |\l\s |\g\e |\l\t |\g\t |\l\e ]

А вот так описан регистр:
$reg: #4 * [ |\r [ |\1\0 |\1\1 |\1\2 |\1\3 |\1\4 |\1\5 |\0 |\1 |\2 |\3 |\4 |\5 |\6 |\7 |\8 |\9 ] |\s\p |\l\r |\p\c ]*

Сами же инструкции процессора описываются следующим образом:
Загрузка адреса в регистр
adr:{$cond}_$reg\,*e

бывают и более сложные случаи
$ldrstr_rec: $reg \, * \[ $reg { |\, * e * } \] * |\, * e * \] \! | \] * \, * e * | \, $reg { \, * \l \s \l _ * e } ]
ldr: [ |{$type} {$cond} _ $ldrstr_rec | _ $reg \, * \= e |{$type} \t {$cond} _ $reg \, * \[ $reg { \, * e } \] |{$type} {$cond} _ $reg \, e ]

Поскольку система команд процессоров может отличаться у различных семейств планирую что будет несколько файлов в каждом из которых будут описаны все команды одного процессора, сейчас предполагаю, что это могут быть файлы следующих семейств: cortex-m4, cortex-m3, cortex-m1, cortex-m0.
Определение типа процессора (и загружаемого файла определений синтаксиса команд) планирую делать по открываемому файлу — по директиве компилятора .mcu и если ее не обнаружу — то запрашивать пользователя

Версию программы готовую в настоящий момент можно скачать по этой ссылке. Примеры небольших исходников на ассемблере лежат в папке samplecode — выбирайте любой…

Сразу скажу о известных багах (описанный глюк является багом :-):
— уже упомянутый выше — не правильно обрабатываемый '!'
— возможно мерцание горизонтального скрола текста при длинных строках (не умещающихся на экране) — знаю как буду править, сейчас не обращать внимание
— при смене шрифта в редакторе с не сохраненным текстом — текст теряется — пока сохранение текста не делал потому что там будут еще дополнения в функционал редактора, сейчас не обращать внимание (шрифт менять до начала работы с текстом)
— цветовая окраска для категорий не выбирается — сделаю как будет время
— окна настроек директив и инструкций будут переделаны полностью, сейчас сделаны чтобы было удобно изменять правила разбора текста
— разбор текста в строке происходит при движении по ней курсора — поэтому если изменили правило — то двиньтесь по строке — правило будет применено.
— правила автоматически не сохраняются — пользуйтесь кнопкой сохранить — это все будет переделано при изменении окон настроек

В настоящий момент работа над редактором и средой продолжается.

Цель этой статьи — найти единомышленников…

Текущие задачи:
— развернуть сайт проекта (на хостингере есть аккаунт, есть личный домен, но нет времени разбираться) — если кто может настроить нечто вроде блога + форум — то знайте — я нуждаюсь в этой помощи (подробнее о задаче в переписке)
— написать и протестировать файлы правил для разных семейств микроконтроллеров — если вы уже смотрели демку — то видели наверное что еще не все директивы и инструкции описаны. Более того — возможно, что не всё получиться описать имеющимся набором правил -это будет ясно только после того как будут описаны все команды и директивы. Поэтому, если кто готов сделать доброе дело — то от вашей помощи не откажусь, помощь по написанию правил конечно готов оказать.
— если вы имеете какие то наработки в Delphi в части написания интерфейсов, или функциональности (которая может быть применена) — то готов слушать советы и предложения — сам в Delphi писал мало и давно… Сейчас фактически изучаю среду и язык заново
мой адрес электронной почты прежний: gorbukov @ тот_кто_знает_все

© Habrahabr.ru