СРАВНЕНИЕ ЭФФЕКТИВНОСТИ КОМПИЛЯТОРОВ ДЛЯ 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, библиотечные оптимизированные функции и прочие Це два плюса.
Всем пис :)