Почему важно изучать язык программирования Assembler.

В данном уроке мы с Вами рассмотрим несколько примеров работы одного и того же кода но на разных языках программирования, а так же плюсы и минусы каждого подхода.
И так, в начале мы рассмотрим программирование на С++ в системе Arduino Ide. Программный код будет очень простой, — мы будем по очереди включать и выключать один из выходов микроконтроллера. Результат выходного сигнала будем смотреть на осциллографе.
Программный код на С++ для микроконтроллера Atmega328P (плата Arduino Nano):

void setup() {
   pinMode(5, OUTPUT);
}

 

void loop() {
   digitalWrite(5, 0);
   digitalWrite(5, 1);
}

Запустив данный код мы видим на осциллограмме частоту 117кГц:

Но если у нас частота микроконтроллера 16МГц, с учетом работы микроконтроллера, у нас на выходе должно было быть 4МГц. Как мы видим данный код работает немного медленно. При этом код занимает 734байта.
Теперь давай напишем тот же программный код, но на языке программирования С:

void setup(){
  DDRD = 0x20;
while(1){
  PORTD = 0x20;
  PORTD = 0;
 }
}

void loop() {;}

Как мы видим на осциллограмме, частота на выходе равна 4МГц, что равно уже расчетной, но как мы видим у нас нет меандра, то есть длительность логических уровней разная:

Сам код занимает 440 байт.

И теперь напишем программный код на Assembler, единственно, что возьмем микроконтроллер Atmega8, так как мы пока только начинаем изучать Assembler и нам надо минимально не сложный код для нашего примера. Причем мы напишем два примера кода, который выполняет одно и тоже действие.

.include «m8def.inc»
ldi      r16, 0b00100000 ; регистр r16 = 0x20
out    DDRD, r16 ;  вывод  PD5 на выход
сlr      r17 ; регистр r17 = 0
Gcykle:
   out     PortD, r16 ; PD5 = 1 -такт
   out     PortD, r17 ; PD5 =0 1-такт
rjmp Gcykle ; переход обратно 2 такта

Данный программный код будет выполняться с частотой 1/4 от тактовой частоты, что можно проверить либо осциллографом либо частотомером. При этом весь программный код занимает 12 байтов, но при этом мы используем два регистра:
Как видим ситуация с переключением логических уровней тут уже получше.
И еще один вариант данного кода:

.include «m8def.inc»
ldi      r16, 0b00100000 ; регистр r16 = 0x20
out    DDRD, r16 ;  вывод  PD5 на выход
Gcykle:
   sbi     PortD, 5 ; PD5 = 2 -такт
   cbi     PortD, 5 ; PD5 =0 2-такт
rjmp Gcykle ; переход обратно 2 такта

Данный код не занимает регистры как предыдущий, а на прямую устанавливает/сбрасывает бит в порту D. Таким образом частота на выходе будет не 1/4, а 1/6 от тактовой. Но при этом мы занимаем меньше памяти 10 байт и экономим регистры:


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

Как мы видим, используя программный код на Assembler мы можем использовать максимально все свойства микроконтроллера и самим контролировать оптимизацию программного кода, о чес не скажешь о среде программирования Arduino IDE.