Чому компілятор не використовує безпосередньо LSR


10

Привіт, я працював над проектом, використовуючи 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;
}

Наскільки я бачу, Ardenino IDE використовує компілятор AVR gcc, що надається системою версії 6.2.0-1.fc24. Обидва встановлені через керування пакетами, тому вони повинні бути оновленими.


1
Схоже, збірка не відповідає коду С.
Євген Ш.

Добре я скомпілював його за допомогою Ardenio IDE, а потім використав avr-objdumpфайл ельфів ... Що, здається, не відповідає?
xZise

1
@Eugene Ш.: Це робить відповідає коді C. Це відповідає лише рядкуdata >>= 1;
сир

1
Це один із випадків, коли "використовувати зміни замість поділу" - неправильна порада. Якщо ви зробите / = 2, замість цього компілятор генерує lsr r24; (порада: спробуйте gcc explorer пограти з генерацією коду ASM)
PlasmaHH

Який компілятор? Який процесор? Це дійсно повинно бути очевидним, це необхідна інформація, щоб питання мало сенс.
Олін Латроп

Відповіді:


18

Згідно зі специфікацією мови C, будь-яке значення, розмір якого менший за розмір int(залежить від конкретного компілятора; у вашому випадку intшириною 16 біт), що бере участь у будь-якій операції (у вашому випадку >>), перетворюється на значення intдо початку операції.
Така поведінка компілятора називається цілим просуванням .

І саме це зробив компілятор:

  • r19 = 0 - MSByte цілого цільового значення data.
  • (r19, r18) являє собою загальне ціле ціле значення, dataяке сприяє зміщенню вправо на один біт на asr r19і ror 18.
  • Потім результат неявно повертається до вашої uint8_tзмінної data:
    mov r24, r18тобто MSByte в r19 викидається.

Редагувати:
Звичайно, компілятор може оптимізувати код.
Намагаючись відтворити проблему, я виявив, що принаймні з avr-gcc версії 4.9.2 проблема не виникає. Він створює дуже ефективний код, тобто C-рядок data >>= 1;збирається лише в одну єдину lsr r24інструкцію. Тож, можливо, ви використовуєте дуже стару версію компілятора.


2
Це не загальний відхід, тому що іноді потрібен неоптимізований код для налагодження на рівні асемблера. Тоді ви дуже раді, якщо у вас є неоптимізований код.
Сир

3
Якщо я пам'ятаю правильно, -mint8 - це прапор для створення цілих чисел 8-розрядних. Однак це має багато небажаних побічних ефектів. Вибачте, не можу повністю пригадати, якими вони були зараз, але я ніколи не використовував прапор через них. Я багато часу тому витрачав на порівняння avr-gcc з комерційним компілятором.
Джон

1
О, це правильно, стандарт C вимагає, щоб цілі числа були принаймні 16-бітними, тому використання -mint8 розбиває всі бібліотеки.
Джон

9
Найджел Джонс сказав у "Ефективному кодексі С для 8-бітових мікроконтролерів" щось на кшталт: "... Цілісні правила просування C - це, мабуть, найбільш грізні злочини, вчинені проти тих, хто працює у 8-бітовому світі" ...
Дірче Родрігес-молодший

1
@Jonas Wielicki: найкраще рішення проблеми - використовувати кращий компілятор. Наприклад, з avr-gcc версії 4.9.2 Я не можу відтворити проблему. Для рядка коду С d >>= 1;я отримую лише одну єдину lsr r24інструкцію. Можливо, xZise використовує дуже стару версію компілятора.
Сир
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.