Pourquoi est-ce code étant généré par gcc et AVR-comment ça marche?
-
20-09-2019 - |
Question
Ceci est un extrait de code AVR démontées à partir d'un projet C je travaille. J'ai remarqué ce code curieux généré, et je ne peux pas comprendre comment cela fonctionne. Je suppose que c'est une sorte d'optimisation ridicule ...
Quelle est l'explication?
92: ticks++; // unsigned char ticks;
+0000009F: 91900104 LDS R25,0x0104 Load direct from data space
+000000A1: 5F9F SUBI R25,0xFF Subtract immediate
+000000A2: 93900104 STS 0x0104,R25 Store direct to data space
95: if (ticks == 0) {
+000000A4: 2399 TST R25 Test for Zero or Minus
+000000A5: F009 BREQ PC+0x02 Branch if equal
+000000A6: C067 RJMP PC+0x0068 Relative jump
Plus précisément, pourquoi la deuxième Soustraire d'instruction de 0xFF R25 au lieu de simplement INC R25
?
La solution
L'instruction SUBI peut être utilisé pour ajouter / soustraire les 8 bits constant vers / à partir d'une valeur de 8 bits. Il a le même coût que INC, à savoir la taille de l'instruction et le temps d'exécution. Alors SUBI est préféré par le compilateur car il est plus général. Il n'y a pas d'instruction ADDI correspondante, probablement parce qu'il serait superflu.
Autres conseils
tl;. Dr le compilateur a été conçu pour utiliser la solution plus portable, efficace et général ici
SUBI
instruction active C
(carry) et H
( demi-carry) flags CPU pour une utilisation avec les instructions suivantes (il n'y a pas ADDI
dans AVR 8 bits BTW, afin d'ajouter une valeur immédiate de x
nous soustrayons -x
de celui-ci), alors que INC
ne fonctionne pas. Depuis les deux SUBI
et INC
ont 2 octets de longueur et exécuter pendant 1 cycle d'horloge, vous ne perdez rien en utilisant SUBI
- OTOH, si vous utilisez une contre-taille 8 bits, vous pouvez facilement détecter si elle a roulé sur (par < a href = "http://www.atmel.com/webdoc/avrassembler/avrassembler.wb_BRCC.html" rel = "nofollow noreferrer"> BRCC
/ BRCS
), et si vous avez un contre-taille 32 bits ou 16-, il vous permet d'incrémenter en d'une manière très simple - avec juste INC
, 0x00FF
se serait passé à 0x0000
, de sorte que vous auriez à vérifier si l'octet le plus bas est 0xFF
avant INC
ing. OTOH, avec SUBI
vous venez SUBI -1
l'octet le plus bas, puis ADC 0
pour les octets suivants, assurant tous les bits de report potentiels a été pris en compte.
Pour en savoir plus:
https: //lists.gnu .org / archive / html /-gcc-AVR liste / 2008-11 / msg00029.html
http: //-gcc-AVR liste .nongnu.narkive.com / SMMzdBkW / foo-Subi-vs-inc