Hallo, ich habe an einem Projekt mit einem Arduino Uno (also ATmega328p) gearbeitet, bei dem das Timing sehr wichtig ist, und wollte wissen, in welche Anweisungen der Compiler meinen Code konvertiert. Und da drin habe ich eine, uint8_t
die ich bei jeder Iteration mit ein Bit nach rechts verschiebe, data >>= 1
und es scheint, dass der Compiler dies in 5 Anweisungen übersetzt hat ( data
ist in r24
):
mov r18, r24
ldi r19, 0x00
asr r19
ror r18
mov r24, r18
Wenn ich mir aber die Dokumentation zum Befehlssatz ansehe, sehe ich eine Anweisung, die genau dies tut: lsr r24
Übersehe ich etwas oder warum verwendet der Compiler dies nicht auch? Die Register r18
und r19
werden nirgendwo anders verwendet.
Ich benutze ein Ardunio, aber wenn ich richtig bin, benutzt es nur den normalen avr-gcc
Compiler. Dies ist der Code (getrimmt), der die Sequenz generiert:
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;
}
Soweit ich sehen kann, verwendet die Ardunino-IDE den vom System bereitgestellten AVR-gcc-Compiler, der Version 6.2.0-1.fc24 ist. Beide werden über die Paketverwaltung installiert und sollten daher auf dem neuesten Stand sein.
avr-objdump
für die Elf-Datei verwendet. Was scheint nicht zu entsprechen?data >>= 1;
Antworten:
Gemäß der C-Sprachspezifikation wird jeder Wert, dessen Größe kleiner als die Größe von
int
(abhängig vom jeweiligen Compiler; in Ihrem Fallint
16 Bit breit) ist, der an einer Operation (in Ihrem Fall>>
) beteiligt ist, auf einen Wertint
vor der Operation übertragen.Dieses Verhalten des Compilers wird als Integer-Promotion bezeichnet .
Und genau das hat der Compiler getan:
data
.data
daß dann nach rechts um ein Bit verschoben wirdasr r19
undror 18
.uint8_t
Variable zurückgesetztdata
:mov r24, r18
dh der MSByte in r19 wird weggeworfen.Bearbeiten:
Natürlich könnte der Complier den Code optimieren.
Beim Versuch, das Problem zu reproduzieren, stellte ich fest, dass das Problem zumindest mit avr-gcc Version 4.9.2 nicht auftritt. Es wird sehr effizienter Code erstellt, dh die C-Zeile
data >>= 1;
wird zu nur einer einzigenlsr r24
Anweisung kompiliert . Vielleicht verwenden Sie eine sehr alte Compilerversion.quelle
d >>= 1;
bekomme ich nur eine einzigelsr r24
Anweisung. Möglicherweise verwendet xZise eine sehr alte Compilerversion.