2016-05-22 1 views
0

J'utilise actuellement l'ASM inline suivant pour que le Cortex-M3 se branche sur une adresse spécifique en flash.ASM en ligne - Utiliser une variable C de 16 ou 32 bits (GCC ARM, mode Thumb)

__asm("LDR R0, =0x8000"); // Load the branch address 
__asm("LDR R1, [R0]"); // Get the branch address 
__asm("ORR R1, #1");  // Make sure the Thumb State bit is set. 
__asm("BX R1");   // Branch execution 
  • Cependant, je veux remplacer la valeur codée en dur 0x8014 avec une variable C qui sera calculé en fonction de certaines autres conditions.
  • La plus grande valeur possible que cette variable peut prendre est 0x20000, donc j'avais prévu d'utiliser un uint32_t pour le stocker.
  • Le compilateur utilisé est arm-none-eabi-gcc v4.9.3

J'ai essayé de modifier mon ASM en ligne comme suit:

uint32_t destination_address = 0x8000; 
__asm("LDR R0, =%[dest]" : : [dest]"r"(destination_address)); 

Cependant, cela génère l'erreur du compilateur:

undefined reference to `r3' 

Je suis relativement nouveau à l'ASM en ligne en général. J'ai essayé de rechercher ce problème pendant deux jours, mais j'ai été troublé par des réponses contradictoires en raison de la diversité des compilateurs et du fait que j'utilise des instructions Thumb pour le Cortex-M3.

Je pense mon problème est que je dois trouver la contrainte correcte pour la destination_address variable (gamme 0x0 - 0x20000), mais je ne suis pas sûr.

+1

Les bonnes nouvelles sont que l'erreur est facile à corriger (https://godbolt.org/g/3B9YqC). Si vous allez utiliser inline asm, vous devriez vous habituer à utiliser '-S' (c'est ce que Godbolt utilise ici). L'inconvénient est que gcc n'aime pas quand vous faites des sauts dans l'asm. Cela peut vraiment gâcher l'optimisation, les refs de symboles, etc. –

+0

@DavidWohlferd Je ne suis pas tout à fait sûr que je suis. (i) Réécrire =% [dest] car [% [dest]] permet de compiler le code, selon votre exemple lié! (ii) Mais je ne comprends pas pourquoi?(iii) Que signifie «-S» et plus important encore, où se manifeste-t-il dans votre exemple? (iv) Vous devriez poster ceci comme réponse! (v) En ce qui concerne le saut de l'ASM, dans ce cas d'utilisation je quitte le binaire et je ne reviendrai jamais. – msolters

+1

ii) Comme vous pouvez le voir sur la sortie, 0x8000 est déplacé dans le registre r3 (ce que vous avez fait avec 'LDR R0, = 0x8000'). Votre deuxième ligne ('LDR R1, [R0]') suppose que la valeur est dans r0, mais en utilisant la contrainte "r", gcc peut choisir n'importe quel registre disponible. Plutôt que de deviner ou de supposer, nous substituons s/R0 /% [dest]. Une réponse plus directe serait que faire '=% [dest]' va s'étendre à '= r3', ce qui ne me semble pas être un assembleur valide. iii) -S est documenté ici (https://gcc.gnu.org/onlinedocs/gcc/Overall-Options.html#index-S-83). –

Répondre

0

Pourquoi utilisez-vous l'assemblage en ligne?

extern void HOP (unsigned int); 
... 
unsigned int some_address; 
.. 
some_address = some_math; 
HOP(some_address); 

et quelques lignes de asm réel que vous pouvez utiliser le compilateur c si vous vous sentez vraiment que vous devez faire un objet de créer un lien.

.globl HOP 
HOP: 
    bx r0 

l'avantage supplémentaire est que c'est un lien de branche fondamentalement si vous voulez être.

le compilateur a déjà calculé l'adresse à laquelle il ressemble donc vous "simplement" besoin de l'obtenir dans un registre et bx il. L'assemblage en ligne est extrêmement spécifique au compilateur. Vous devez donc commencer par parler de l'assembleur, de la version, etc. que vous utilisez.

une autre chose que vous pouvez faire est si vous avez cette

unsigned int some_address; 
.. 
some_address = some_math; 

vous pouvez utiliser cette assemblée quelque part dans le projet.

ldr r0,=some_address; 
ldr r0,[r0] 
bx r0 

et l'éditeur de liens résoudra l'adresse à la variable C. donc peut utiliser un véritable assembleur ou en ligne pour quelque chose comme ça. (si l'inline ne supporte pas quelque chose comme mov% 0, some_address, bx% 0 et fait le travail pour vous)