unsigned int fun1 ( unsigned int a, unsigned int b )
{
return(a+b);
}
unsigned char fun2 ( unsigned int a, unsigned int b )
{
return(a+b);
}
unsigned int fun3 ( unsigned char a, unsigned char b )
{
return(a+b);
}
unsigned char fun4 ( unsigned char a, unsigned char b )
{
return(a+b);
}
comme fun1 attendu est tous les pouces, tout comme les mathématiques 16 bits
00000000 <fun1>:
0: 86 0f add r24, r22
2: 97 1f adc r25, r23
4: 08 95 ret
Bien que techniquement incorrect car il s'agit d'un ajout 16 bits appelé par le code, même non optimisé, ce compilateur a supprimé l'adc en raison de la taille du résultat.
00000006 <fun2>:
6: 86 0f add r24, r22
8: 08 95 ret
pas vraiment surpris ici que la promotion se produise, les compilateurs ne le faisaient pas, je ne sais pas quelle version a fait que ce début se produise, je l'ai rencontré tôt dans ma carrière et malgré les compilateurs faisant la promotion hors service (comme ci-dessus), faisant la promotion même si je lui a dit de faire des mathématiques uchar, pas surpris.
0000000a <fun3>:
a: 70 e0 ldi r23, 0x00 ; 0
c: 26 2f mov r18, r22
e: 37 2f mov r19, r23
10: 28 0f add r18, r24
12: 31 1d adc r19, r1
14: 82 2f mov r24, r18
16: 93 2f mov r25, r19
18: 08 95 ret
et l'idéal, je sais que c'est 8 bits, je veux un résultat 8 bits alors je lui ai simplement dit de faire 8 bits tout au long.
0000001a <fun4>:
1a: 86 0f add r24, r22
1c: 08 95 ret
Donc, en général, il vaut mieux viser la taille du registre, qui est idéalement la taille d'un (u) int, pour un mcu 8 bits comme celui-ci, les auteurs du compilateur ont dû faire un compromis ... Le point étant de ne pas prendre l'habitude de utiliser uchar pour les mathématiques que vous savez n'a pas besoin de plus de 8 bits comme lorsque vous déplacez ce code ou écrivez un nouveau code comme celui-ci sur un processeur avec des registres plus grands, le compilateur doit maintenant commencer à masquer et à étendre les signes, ce que certains font nativement dans certaines instructions, et d'autres non.
00000000 <fun1>:
0: e0800001 add r0, r0, r1
4: e12fff1e bx lr
00000008 <fun2>:
8: e0800001 add r0, r0, r1
c: e20000ff and r0, r0, #255 ; 0xff
10: e12fff1e bx lr
forcer 8 bits coûte plus cher. J'ai triché un peu / beaucoup, j'aurais besoin d'exemples un peu plus compliqués pour en voir plus de manière juste.
EDIT basé sur la discussion des commentaires
unsigned int fun ( unsigned char a, unsigned char b )
{
unsigned int c;
c = (a<<8)|b;
return(c);
}
00000000 <fun>:
0: 70 e0 ldi r23, 0x00 ; 0
2: 26 2f mov r18, r22
4: 37 2f mov r19, r23
6: 38 2b or r19, r24
8: 82 2f mov r24, r18
a: 93 2f mov r25, r19
c: 08 95 ret
00000000 <fun>:
0: e1810400 orr r0, r1, r0, lsl #8
4: e12fff1e bx lr
pas de surprise. Bien que l'optimiseur ait laissé cette instruction supplémentaire, ne pouvez-vous pas utiliser ldi sur r19? (Je connaissais la réponse quand je l'ai posée).
EDIT2
pour avr
avr-gcc --version
avr-gcc (GCC) 4.9.2
Copyright (C) 2014 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
pour éviter la mauvaise habitude ou pas la comparaison 8 bits
arm-none-eabi-gcc --version
arm-none-eabi-gcc (GCC) 7.2.0
Copyright (C) 2017 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
il est clair que l'optimisation était activée ne prend qu'une seconde pour essayer avec votre propre compilateur pour voir comment il se compare à ma sortie, mais de toute façon:
whatever-gcc -O2 -c so.c -o so.o
whatever-objdump -D so.o
Et oui, utiliser des octets pour des variables de taille octet, certainement sur un avr, pic, etc., vous fera économiser de la mémoire et vous voulez vraiment essayer de le conserver ... si vous l'utilisez réellement, mais comme indiqué ici le moins possible est va être en mémoire, autant dans les registres que possible, donc les économies de flash viennent en n'ayant pas de variables supplémentaires, les économies de RAM peuvent être réelles ou non.