Cześć. Pracowałem nad projektem przy użyciu Arduino Uno (więc ATmega328p), w którym czas jest dość ważny, dlatego chciałem sprawdzić, w które instrukcje kompilator konwertuje mój kod. I tam mam uint8_t
przesunięcie o jeden bit w prawo przy każdej iteracji data >>= 1
i wydaje się, że kompilator przetłumaczył to na 5 instrukcji ( data
jest w r24
):
mov r18, r24
ldi r19, 0x00
asr r19
ror r18
mov r24, r18
Ale jeśli zajrzę do dokumentacji zestawu instrukcji, zobaczę instrukcję, która robi dokładnie to: lsr r24
Czy coś pomijam lub dlaczego kompilator też tego nie używa? Rejestry r18
i r19
nie są używane nigdzie indziej.
Używam Ardunio, ale jeśli mam rację, używa zwykłego avr-gcc
kompilatora. To jest kod (przycięty), który generuje sekwencję:
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;
}
O ile widzę, Ardunino IDE korzysta z kompilatora gcc AVR dostarczonego przez system w wersji 6.2.0-1.fc24. Oba są instalowane za pomocą menedżera pakietów, więc powinny być aktualne.
avr-objdump
w pliku elfa… Co to wydaje się nie odpowiadać?data >>= 1;
Odpowiedzi:
Zgodnie ze specyfikacją języka C każda wartość, której rozmiar jest mniejszy niż rozmiar
int
(zależy od konkretnego kompilatora; w twoim przypadkuint
ma 16 bitów szerokości), zaangażowana w dowolną operację (w twoim przypadku>>
), jest przekazywana do wartościint
przed operacją.Takie zachowanie kompilatora nazywa się promocją liczb całkowitych .
I właśnie to zrobił kompilator:
data
.data
która jest następnie przesuwana w prawo o jeden bit oasr r19
iror 18
.uint8_t
zmiennądata
:mov r24, r18
tj. MSByte w r19 jest wyrzucany.Edycja:
Oczywiście kompilator może zoptymalizować kod.
Próbując odtworzyć problem, stwierdziłem, że przynajmniej w przypadku avr-gcc w wersji 4.9.2 problem nie występuje. Tworzy bardzo wydajny kod, tzn. Linia C
data >>= 1;
jest kompilowana do jednejlsr r24
instrukcji. Więc może używasz bardzo starej wersji kompilatora.źródło
d >>= 1;
otrzymuję tylko jednąlsr r24
instrukcję. Może xZise używa bardzo starej wersji kompilatora.