Предпосылки


Ряд статей (раз, два, три) навел на мысли о том, что Excel можно использовать как транслятор в ассемблерный код AVR.

Сопоставим Excel с основными фичами «обычного» редактора кода. Список самых популярных фич следующий:

Фича редактора кода Как реализовать в Excel Как реализовано в Atmel Studio
Подсветка синтаксиса Условное форматирование ячеек в зависимости от содержания Подсветка команд
Автодополнение Пользовательские функции VBA;
Именованные диапазоны;
Ячейка как миниконсоль с макросом на cобытие Change;
Нет
Отступы Вручную переход в соседний столбец Вручную
Проверка правильности расстановки скобок Есть встроенный контроль Только при сборке
Контекстная помощь по коду Нет Есть список имен меток
Сворачивание блока кода Функция группировки столбцов и строк Нет
Статический анализатор На ходу показывает ошибки в ссылках Нет

Выглядит приемлемо. Кое-что достается «даром», кое-что надо доработать.

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

Первоначальные соглашения


Общий подход и терминологию примем отсюда.

Весь алгоритм разделим на ветки. Ветка играет роль самостоятельного программного блока.
У каждой ветки есть имя, которое является точкой входа в нее. Оно должно быть уникальным и осмысленным. Все имена веток размещаются в верхней строке, которую так и назовем – «строка имен».

Ветка заканчивается одним или несколькими переходами к другим веткам. Переходы от одной ветки к другой размещаются в самой нижней строке. Назовем ее «строка переходов».

Также принимаем правило, что изнутри одной ветки нельзя переходить внутрь другой.

Общая схема алгоритма
image

Для ветвлений и циклов внутри ветки также применяются метки. То есть меток в программе очень много. Каждый раз придумывать новое уникальное имя – это рутина. Здесь на помощь приходит базовая функциональность Excel. Каждая ячейка уже имеет уникальное имя, состоящее из имени столбца и номера строки.

На VBA создадим функцию label с аргументом типа Range. Метка в ассемблере AVR должна иметь на конце двоеточие. Т.е. наша функция labelполучает на вход ссылку на ячейку, в которой размещается сама и вычисляет ее адрес в формате A1. Затем добавляет к ней текст «_M:». Фрагмент «_M» не случаен, мы будем использовать это дальше – в форматировании ячеек.

Визуализация переходов


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

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

Для блок-схем существуют стандарты на обозначения отдельных элементов. Например, прямоугольник – это вычисление; ромб – условие и т.д. При работе с табличным процессором нам доступны управление цветом, начертанием и границами.

В Excel есть удобная функция условного форматирования. Использовать ее можно по-разному, но мы введем всего три простых правила:

  1. Непустая ячейка в строке имен и в строке переходов красится в желтый цвет;
  2. Непустая ячейка в теле ветки красится в оранжевый;
  3. Ячейки с «локальными» метками и командами перехода красятся в синий. Это непустая ячейка, которая содержит символы «_М», о которых упоминалось выше.

На гифке ниже представлено, как работа с метками и переходами выглядит после всех настроек.

Работа с метками и командами перехода
image

Порядок формирования конечного листинга


Сборщик листинга обходит итоговую программу сверху вниз и слева направо. По одной ячейке за раз.

Как формируется конечный листинг
image

Алгоритм сборки пропускает пустые ячейки и ячейки, которые содержат символ «;», т.е. комментарии.

Отладка алгоритма и окончательная сборка проекта происходит в студии. Обратная связь кода в студии с ячейками Excel отсутствует. Поэтому для ловли ошибок в итоговый листинг напротив каждой команды указываем ссылку на ячейку. По этой ссылке мы находим проблемную команду на схеме в Excel.

Ветвление


Базовое алгоритмическое решение – это ветвление вида:

If <условие> then 
    <действие>
Else
    <действие>
End if

Для него в ассемблере AVR есть команды условного перехода (breq, brne, sbic и прочие). Эти команды указывают программе, куда перейти при выполнении условия.

Теперь представим, как должна выглядеть программа такого ветвления с учетом озвученных выше принципов:

Простое ветвление
image

У команды brne и ее аналогов есть ограничение. Дальность перехода составляет 64 слова в каждую сторону. Поэтому длинный макрос, вставленный в ответвление «Нет» может вызвать out of range.

Для обхода этого ограничения обработку «Нет» производить в отдельной ветке, которая будет правее метки перехода от brne. Либо использовать подпрограмму, в которой вызывается макрос.

Select Case


Если выбирать приходится из большого количества вариантов, в ЯВУ используется Select Case:

Select Case <переменная>
    Case <условие1>
    Case <условие2>
    Case <условие3>
    Case else
End select

На ассемблере под AVR доступны индексные переходы. Покажем вариант реализации.

Select Case
image

Здесь видно, что нарушен запрет прыжка из тела ветки к другой ветке. Это сделано преднамеренно, иначе программа займет слишком много места по горизонтали.

По этой же причине вектор прерываний следует выполнить в один столбик.

Цикл с постусловием


Цикл, когда необходимо минимум одно повторение, в нотации ЯВУ выглядит следующим образом:

Do
    <действие>
Loop while <условие>

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

Цикл с постусловием
image

Цикл с предусловием


Пример на ЯВУ:

Do while <условие>
	<Действие>
Loop

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

Цикл с предусловием
image

Цикл со вложенным циклом


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

Общий вид на ЯВУ:

Do
    Do
        <действие>
    Loop while <условие 2-го уровня>
    <действие>
Loop while <условие 1-го уровня>

Реализовать вложенный цикл можно двумя путями: либо внутри одной ветки, либо с помощью нескольких веток. Покажем оба варианта.

Вложенные циклы внутри одной ветки
image

Вложенные циклы с реализацией через ветки
image

Цикл с выходом по условию


Есть ситуации, когда из цикла необходимо выйти до его окончания. Например, логический ноль на 0-вой ножке порта D может говорить о какой-то неисправности. Программа должна покинуть основной цикл и запустить тревогу.

В ЯВУ используется команда break, а общий алгоритм имеет следующий вид:

Do 
    <действие>
    If <условие прерывания> then break
Loop while <условие>

Снова покажем, как будет выглядеть алгоритм без веток и с ветками.

Прерывание цикла внутри одной ветки
image


Прерывание цикла, реализованного через ветки
image

Вызов подпрограмм


Подпрограммы вызываются командами call, icall, rcall. Тут есть важная особенность. Подпрограмму необходимо вызывать строго из тела ветки. Если же вызов разместить в строке переходов, возврат из подпрограммы почти гарантированно произойдет в неверное место.

Обязательные требования к подпрограмме:

  • сама подпрограмма обязательно начинается с имени-метки;
  • последняя команда подпрограммы обязательно должна быть ret и размещаться в строке переходов.

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

Пример с бегущим огоньком


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

Конечный результат выглядит так:

Схема бегущего огонька
image

Листинг всей программы в Excel со скрипом уместился на один экран:

Бегущий огонек. Код в Excel
image

Бегущий огонек. Итоговый листинг
image

Итоги


Что не понравилось


  1. Изложенный метод вряд ли подойдет для работы над большим проектом с участием целой команды. Контроль версий, диффы и т.д. все равно придется решать на стороне.
  2. В режиме отладки очень неудобно без двух мониторов. Сама отладка ведется в студии, а блок-схема в Excel. Это разные окна, требуются переключения.
  3. Программа быстро пухнет в горизонтальном направлении. При этом в Excel прокрутка в сторону грубая и неудобная.
  4. Болезнь блок-схема как таковых – много пустого места. Для комфортной работы на одном экране разрешением 1280х1024 должно быть около 5 столбиков и 45 строк с информативными ячейками. Не более 20% от этого количества будет заполнено самими командами (это 45 команд). Остальное пространство – жертва визуальному представлению и комментариям. Примерно столько же команд помещается в окно студии на один экран.

Что понравилось


  1. Проектирование алгоритма «сверху вниз» складывается очень естественно. Объявляем только имена и переходы.
  2. Код в Excel можно открыть в несколько окон. В Atmel Studio доступно только разделение экрана по горизонтали.
  3. Сокращение рутинных действий при работе с именованными сущностями.
  4. Контроль меток не требует внимания. Переместили или переименовали метку – все переходы автоматически получат изменения. Удаление метки приведет к ошибке, которую легко найти визуально.
  5. Excel как транслятор очень просто расширять новыми функциями. Что-то доступно через формулы, что-то – через макросы VBA.

Точки роста


  1. Оптимизация работы с метками и переходами. Если в итоговом листинге команда «Переход на метку» расположена прямо над самой меткой, команду с переходом можно убрать. Освободим 4-5 тактов. Если конструкция вида «Переход на метку А – Метка А – Переход на метку Б – Метка Б» не содержит внутри никаких команд, то «Переход на метку Б» убираем, а «Переход на метку А» меняем на «Переход на метку Б». Также сэкономим 4-5 тактов.
  2. Дополнительные проверки на ошибки. Макросом легко организовать проверку, нет ли «висящих» блоков, которые не кончаются переходами. Также макросом можем найти и удалить неиспользованные метки, которые при отладке отвлекают внимание.
  3. Можно ввести собственные правила раскрашивания ячеек.
  4. Если бы табличный процессор был встроен в студию как редактор кода, то производить отладку сразу на такой блок-схеме было бы очень удобно.