Почему этот код генерируется avr-gcc и как он работает?
Это фрагмент дизассемблированного кода AVR из C-проекта, над которым я работаю. Я заметил, что генерируется этот любопытный код, и я не могу понять, как он работает. Я предполагаю, что это какая-то нелепая оптимизация...
Какое объяснение?
92: ticks++; // unsigned char ticks;
+0000009F: 91900104 LDS R25,0x0104 Load direct from data space
+000000A1: 5F9F SUBI R25,0xFF Subtract immediate
+000000A2: 93900104 STS 0x0104,R25 Store direct to data space
95: if (ticks == 0) {
+000000A4: 2399 TST R25 Test for Zero or Minus
+000000A5: F009 BREQ PC+0x02 Branch if equal
+000000A6: C067 RJMP PC+0x0068 Relative jump
В частности, почему вторая инструкция вычитает 0xFF из R25 вместо просто INC R25
?
2 ответа
Инструкция SUBI может использоваться для добавления / вычитания любой 8-битной константы в / из 8-битного значения. Он имеет ту же стоимость, что и INC, то есть размер инструкции и время выполнения. Так что SUBI предпочитает компилятор, потому что он более общий. Нет соответствующей инструкции ADDI, вероятно, потому что она будет избыточной.
Компилятор был спроектирован таким образом, чтобы использовать более переносимое, эффективное и общее решение.
SUBI
наборы инструкций C
(нести) и H
(половина переноса) Флаги процессора для использования с последующими инструкциями (нет ADDI
в 8-битном AVR BTW, так что добавить немедленное значение x
мы вычитаем -x
от этого), тогда как INC
не. Поскольку оба SUBI
& INC
имеют длину 2 байта и выполняются в течение 1 такта, вы ничего не потеряете при использовании SUBI
- OTOH, если вы используете 8-битный счетчик, вы можете легко определить, перевернулся ли он (BRCC
/ BRCS
), и если у вас есть счетчик размером 16 или 32 бита, он позволяет увеличить его очень простым способом - просто INC
, 0x00FF
будет увеличен до 0x0000
так что вам нужно проверить, является ли младший байт 0xFF
до INC
ING. ОТОХ, с SUBI
ты только SUBI -1
младший байт, а затем ADC 0
для следующих байтов, гарантируя, что все потенциальные биты переноса были учтены.
Дальнейшее чтение:
https://lists.gnu.org/archive/html/avr-gcc-list/2008-11/msg00029.html
http://avr-gcc-list.nongnu.narkive.com/SMMzdBkW/foo-subi-vs-inc