Salut, je travaille sur un projet utilisant un Arduino Uno (donc ATmega328p) où le timing est assez important et je voulais donc voir dans quelles instructions le compilateur convertissait mon code. Et là, j'en ai un uint8_t
que je décale d'un bit vers la droite à chaque itération en utilisant data >>= 1
et il semble que le compilateur ait traduit cela en 5 instructions ( data
en r24
):
mov r18, r24
ldi r19, 0x00
asr r19
ror r18
mov r24, r18
Mais si je regarde dans la documentation du jeu d'instructions, je vois une instruction qui fait exactement ceci: lsr r24
Dois-je ignorer quelque chose ou pourquoi le compilateur ne l'utilise-t-il pas également? Les registres r18
et r19
ne sont utilisés nulle part ailleurs.
J'utilise un Ardunio mais si j'ai raison, il utilise simplement le avr-gcc
compilateur normal . C'est le code (découpé) qui génère la séquence:
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;
}
Autant que je puisse voir, l'IDE Ardunino utilise le compilateur AVR gcc fourni par le système qui est la version 6.2.0-1.fc24. Les deux sont installés via le gestionnaire de packages et doivent donc être à jour.
avr-objdump
sur le fichier elf… Qu'est-ce qui ne semble pas correspondre?data >>= 1;
Réponses:
Selon la spécification du langage C, toute valeur dont la taille est inférieure à la taille de
int
(dépend du compilateur particulier; dans votre cas, a uneint
largeur de 16 bits) impliquée dans une opération (dans votre cas>>
) est convertie en unint
avant l'opération.Ce comportement du compilateur est appelé promotion d'entiers .
Et c'est exactement ce que le compilateur a fait:
data
.data
qui est ensuite décalée d'un bit vers la droite parasr r19
etror 18
.uint8_t
variabledata
:mov r24, r18
, à savoir le MSByte à R19 est jeté.Edit:
Bien sûr, le complice pourrait optimiser le code.
En essayant de reproduire le problème, j'ai trouvé qu'au moins avec la version avr-gcc 4.9.2, le problème ne se produit pas. Il crée un code très efficace, c'est-à-dire que la ligne C
data >>= 1;
est compilée en une seulelsr r24
instruction. Alors peut-être que vous utilisez une très ancienne version du compilateur.la source
d >>= 1;
je reçois une seulelsr r24
instruction. Peut-être que xZise utilise une très ancienne version du compilateur.