8
votes

Assemblage des bras d'appel de C, GCC (métal nu)

J'essaie de faire une programmation de métaux nu avec le bras avec GCC et des tests sur QEMU. Chaque fois que j'appelle une étiquette de bras de C, mon programme est suspendu. J'ai un exemple simple de code qui montre le problème chez https://gist.github.com/1654392 - Lorsque j'appelle activé () dans ce code, il se bloque.

J'ai observé avec Objdump que lorsque je fais un BL d'assemblage au code C (à partir de _start), il génère une petite emballeuse qui passe aux instructions du pouce. Il semble que le code C soit généré dans les instructions du pouce, mais tout mon montage est généré dans des instructions du bras (32 bits). Je ne peux pas comprendre pourquoi c'est ou comment le réparer.


9 commentaires

Kernel.o :(. Arm.exidx + 0x0): Référence non définie à `__aeabi_unwind_cpp_pr1 'Make: *** [Kernel.elf] Erreur 1


essayez-vous de construire une application Bras Linux? ou une application intégrée (sans système d'exploitation)? Si une application Linux, vous n'avez pas besoin de code de démarrage, lachaise doit faire tout cela pour vous, vous vous inquiétez de la principale () comme point d'entrée.


Pouvez-vous fournir des décharges de montage des zones confuses?


Utilisation de CodeSourcery's (LITE) Toolchain (Maintenant Mentor Graphics) Je ne vois aucun code de pouce, il produit un code de bras de 32 bits. L'armv6 prend en charge le mode pouce.


J'ai de nombreux exemples de ceci à github.com/dwelch67


Donc, il semble que le compilateur croisé du bras GCC Ubuntu génère le pouce par défaut. Je ne suis pas sûr de savoir s'il y a une façon de travailler avec cela, mais j'ai enfin trouvé l'option -Marm et utiliser cela se débarrasse de toute la sortie d'instruction de pouce. Sur le problème suivant :)


Ce noyau prend en charge le mode thumb. La clé Voici comment vous appelez votre code d'ASM. Vous ne pouvez pas utiliser BL par exemple, BLX devrait fonctionner si votre noyau le supporte. une solution plus compatible est LDR RX, thumb_func_addr; MOV LR, PC; BX RX, où Rx est un registre que vous avez alloué dans la fonction d'appel ou est R0-R3 et vous n'utilisez pas tous les quatre.


Donc, la vraie question, qui est une question intéressante, est de savoir comment appeler le thumb c fonctionne de l'assemblage du bras. Et je pense qu'il y a déjà une réponse si j'ai écrite, testée et posté du code pour quelqu'un.


Maintenant que vous connaissez-lemmourd, construisez au moins un module C avec -Marm et au moins un avec -MThumb (peut-être besoin d'activer l'interfonctionnement) et de les relier et de voir ce que le compilateur produit. Peut-être que définir simplement l'interfonctionnement placera le code de trampoline et le lieur choisira de l'appeler ou de passer directement.


4 Réponses :


3
votes

voir http://github.com/dwelch67/yagbat annuaire QEMU.

Voici Un couple d'exemples de bras d'appel ou de pouce de bras p> xxx pré>

Si vous examinez la référence d'instructions, vous verrez que vous devez utiliser BX ou Blx pour basculer entre bras et Thumb stipule. Blx n'est pas aussi largement pris en charge que BX. P>

à partir d'un point de vue de la définition Le compteur de programme, PC est deux instructions à venir lors de l'exécution d'une instruction. Pour le pouce de 4 octets, pour le bras 8 octets. Soit deux instructions. Pour simuler un BL qui ne peut pas être utilisé pour changer d'état, vous devez charger le registre de liaison avec l'adresse de retour et utiliser une branche BX sur la fonction changeant état en fonction du LSBIT de l'adresse de l'adresse. Donc, le p> xxx pré>

Le MOV LR, PC ci-dessus charge l'adresse d'ici: Notre adresse de retour, BX R1 de manière indépendante de l'État appelle la fonction. Le LSBIT de l'adresse LR indique le mode de retour et vous devez toujours utiliser BX pour revenir P>

    push {r2,lr}
    ;@ call an arm function from thumb asm
    ldr r2,=PUT32
    mov lr,pc
    bx r2
    pop {r2}
    mov lr,r2
    pop {r2}
    bx lr


0 commentaires

0
votes

Si vous assemblez votre code ASM en tant que pouce, vous devez marquer la fonction sous forme de fonction de pouce, de sorte que la liaison utilise des instructions correctes lors de la ramification à celle-ci (E.G. BLX ou BX à une adresse avec le jeu de bits bas). Ceci est fait avec la directive .THumb_funcCuncunc:

.code 32
.global activate
activate:
    b test


0 commentaires

0
votes

Éliminer la confusion:

Le problème était que le compilateur croisé GCC de Ubuntu pour le bras génère des instructions de pouce (16 bits) par défaut. Au fur et à mesure que d'autres réponses montrent, l'appel entre les deux est possible, mais tandis que l'assembleur GNU a détecté que le code C générant des instructions au pouce et a donc généré des calees générées avec BX pour définir correctement le mode pour appeler dans c Je n'ai aucun contrôle sur ce que GCC lui-même est généré pour les fonctions d'appel, et cela les appelait avec juste bl, qui s'est cassé parce que mon code de montage doit être des instructions de bras (32 bits).

La solution (qui est mal documentée) consiste à envoyer GCC -Marm, qui permettra au moins tout le code du même type.

S'il y a un commutateur pour obtenir GCC pour générer des appels BX pour des fonctions, cela fonctionnerait probablement aussi.


1 commentaires

GCC -MARM ne fonctionne pas pour moi. J'ai besoin du code de montage pour ARM-V4T-Linux-Gnueabi



7
votes

Pour appeler une fonction Mode Bras définie dans l'assemblage à partir d'une fonction MODE POUVOIR définie dans C, vous devez définir un symbole dans l'assemblage en fonction de la fonction et que les outils (Linaro GCC) produiront un blx < / code> instruction au lieu de BL .

Exemple: xxx


1 commentaires

Merci! Cela semble fonctionner parfaitement et me permet de relier le code de la bibliothèque!