СРАВНЕНИЕ ЭФФЕКТИВНОСТИ КОМПИЛЯТОРОВ ДЛЯ ATMEL AVR

Пользователь habrahabr.ru Дмитрий Int_13h


В статье habrahabr.ru/post/151544/ и комментариях к ней возник вопрос, почему разные компиляторы выдают код не только разного размера, но и разной эффективности. Если с первым фактором еще можно мириться, то второй может свести все ваши усилия в написании программы на нет. Это на PC еще можно добавить памяти до 32 Гб и поставить 16 ядерный процессор на 10 ГГц, чтобы косынка на NET8.0 не тормозила, а embedded система — девица более изысканная и утонченная.

Итак, сравниваем компиляторы:

1. BASCOM-AVR

2. Wiring

3. С CodeVisionAVR.


Прошивки, любезно предоставленные для исследования товарищем vvzvlad, дизассемблируем с помощью инструмента всех времен и народов IDA. Исходные коды приведены в комментарии habrahabr.ru/post/151544/#comment_5141741. В результате изучения ассемблерных «исходников» можно отметить, что BASCOM и С CVAVR делают практически одинаковый и эффективный код, ардуиновский Wiring по сравнению с ними ловит тунцов. :)

Аперитив

Коды инициализации особого интереса не представляют, но они есть. BASCOM и C используют только то, что требуется программе, Wiring имеет чуть более чем больший инициализационный код, а также обрабатывает прерывание по таймеру Timer0, хотя в программе он нам не нужен.

К примеру, инициализация по версии BASCOM:

Cи CVAVR хочет от мелкоконтроллера почти того же самого, но кода побольше:

Инициализация Wiring №7:

За строкой «007A call sub_C9» притаились вложенные функции, которые что-то зачем-то инициализируют ;) Но, собственно, какие проблемы, стартовать системе 1 мс или 10 мс или даже 100 мс? Подробные подробности следующим письмом оставим на закуску.

Основное блюдо

Что делает с полезным кодом компилятор BASCOM:

1.hex

Превращается в:

Просто, надежно, эффективно.

И программа:

2.hex

Превратилась в:

Фокус с постоянным выводом «1» в порт возможен благодаря особенностям архитектуры (чудо просто эти AVR). Чистый ассемблер и никакого мошенничества.

Cи CVAVR сделал то, что ему сказали и ни грамма байта больше:

7.hex

Ассемблерный код:

У кода Arduino найти полезный участок займет не одну минуту, я справился с этой задачей загнав прошивку в симулятор протеуса.

3.hex

Вот он, вызов функции digitalWrite:

Саму функцию можно представить в виде следующей картинки (примите извинения за радикал, уважаемые читатели):



Кода много, код ветвист и изобилует коллами и джампами, смотрите его лучше сразу в дизассемблере.

Следующий вариант удачнее:

4.hex

Что мы имеем с этого супа:

Главный цикл:

И функция вывода:

Следующий! (с) анекдот

5.hex

Напомнило первый случай BASCOM с точностью до бита:

А вызывается оно вот отсюда, из главного цикла:

Еще парочку! (с) Булгаков

Почти то же, что и в прошивке номер 5:

6.hex

И результат прогнозируем:

Второе блюдо

Почему мне не понравился Wiring? Ладно, вы уговорили меня не использовать тяжелые библиотечные функции, будем писать все на ассемблере напрямую в порты и регистры, и куда теперь идут все наработанные сообществом библиотеки? А вот эта фраза: «Управдом друг человека!» «ROM:0061; FUNCTION CHUNK AT ROM:01B3 SIZE 00000002 BYTES» А означает она, что выполняли мы код, а потом неожиданно свалили по джампу в другое место. Ради одной команды, между прочим.

Wiring тут не одинок, видел я проекты на Сях и под AVR и под PIC, где функция разбита на кучу кусочков, распиханных в разные места памяти программ и связана кучей джампов (+2 такта на выполнение) и коллов (+1 место в стеке, + 4 такта на AVR). Переходим к тому кусочку — а нам затычка в виде ret ( + 4 такта на AVR) :), ибо компилятор так посчитал нужным. А вдруг возникает желание отладить не на языке высокого уровня, а в железе, потрогать, так сказать, его за регистры. И летает программа туда-сюда, с нулевого адреса на сотый и обратно, готовый антихакинг антиреверсинг… Эффективность? 640 кБ хватит всем ;)

Обещанная закуска

А на закуску я взял протеус, 7 чипов, 7 прошивок, запустил и сравнил. Сверху вниз 1, 2, 3, 4, 5, 6 и, конечно же, 7. Время старта (инициализация переда началом выполнения полезной функиции):



А в победителях у нас оказался....Wiring! Значит функция инициализации тут не такая уж и навороченная оказалась ;) Фавориты BASCOM и CVAVR идут ноздря в ноздрю, но на почетном втором месте.

Ну и время выполнения главной задачи — пульсирующий выход.



Впереди бесспорно CVAVR, на втором месте Wiring v.6, 3 и 4 места заслуженно у BASCOMа.

Подведем итоги. Что же выбрать в качестве языка? Если вы хотите использовать железо на 101% и не тратить впустую его ресурсы — ассемблер ваше все. Если вы доверяете трату ресурсов авторам компиляторов, а писать хотите быстро и эффективно — берите С или даже BASCOM. Если хотите создать код быстро, ресурсов у вас много, а задача состоит помигать светодиодом, нет острой необходимости в пошаговой отладке кода в железе, а также очень желательно защитить код от реверсинжиниринга и не давать никому исходников — используйте Wiring, библиотечные оптимизированные функции и прочие Це два плюса.

Всем пис :)