Привет, я работал над проектом с использованием Arduino Uno (так что ATmega328p), где время очень важно, и поэтому я хотел посмотреть, в какие инструкции компилятор преобразовывал мой код. И там у меня есть, uint8_t
который я сдвигаю один бит вправо на каждой итерации, используя, data >>= 1
и кажется, что компилятор перевел это в 5 инструкций ( data
находится в r24
):
mov r18, r24
ldi r19, 0x00
asr r19
ror r18
mov r24, r18
Но если я загляну в документацию по набору инструкций, то увижу инструкцию, которая делает именно это: lsr r24
Я что-то упускаю из виду или почему компилятор тоже не использует это? Регистры r18
и r19
больше нигде не используются.
Я использую Ardunio, но если я прав, он просто использует обычный avr-gcc
компилятор. Это код (обрезанный), который генерирует последовательность:
ISR(PCINT0_vect) {
uint8_t data = 0;
for (uint8_t i = 8; i > 0; --i) {
// asm volatile ("lsr %0": "+w" (data));
data >>= 1;
if (PINB & (1 << PB0))
data |= 0x80;
}
host_data = data;
}
Насколько я вижу, в Ardunino IDE используется компилятор gcc AVR, предоставляемый системой версии 6.2.0-1.fc24. Оба устанавливаются через менеджер пакетов, поэтому должны быть обновлены.
avr-objdump
в файле elf ... Что это, похоже, не соответствует?data >>= 1;
Ответы:
В соответствии со спецификацией языка C любое значение, размер которого меньше размера
int
(зависит от конкретного компилятора; в вашем случаеint
имеет ширину 16 бит), участвующего в любой операции (в вашем случае>>
), передаетсяint
до операции.Такое поведение компилятора называется целочисленным продвижением .
И это именно то, что сделал компилятор:
data
.data
, которое затем сдвигается вправо на один бит наasr r19
иror 18
.uint8_t
переменнойdata
:mov r24, r18
то есть MSByte в r19 выбрасывается.Изменить:
Конечно, компилятор может оптимизировать код.
Пытаясь воспроизвести проблему, я обнаружил, что по крайней мере с avr-gcc версии 4.9.2 проблема не возникает. Это создает очень эффективный код, то есть C-line
data >>= 1;
компилируется в однуlsr r24
инструкцию. Поэтому, возможно, вы используете очень старую версию компилятора.источник
d >>= 1;
я получаю только одну единственнуюlsr r24
инструкцию. Возможно, xZise использует очень старую версию компилятора.