60 votes

Convention d'appel ARM to C, registres à sauvegarder

Il a été un moment depuis que j'ai codé en assembleur arm et je suis un peu rouillé sur les détails. Si j'ai appeler une fonction C de bras, j'ai seulement à vous soucier de sauver r0 r3 et lr, droit? Si la fonction C utilise toutes autres registres, est-il responsable de la sauvegarde de ceux sur la pile et de les restaurer? En d'autres termes, le compilateur de générer du code pour faire cela pour les fonctions C. Par exemple si j'utilise r10 dans une fonction assembleur, je n'ai pas à pousser sa valeur sur la pile, ou à la mémoire, et de la pop/restauration après un C appel, puis-je?

C'est pour arm-eabi-gcc 4.3.0.

Je réalise que j'ai pu lire l'ensemble de la EABI, mais alors shortcutting RTFM est ce qui est DONC, non? :-)

80voto

CesarB Points 18048

Il dépend de l' ABI pour la plate-forme de compilation pour. Sur Linux, il y a deux BRAS ABIs; l'ancien et le nouveau. Autant que je sache, la nouvelle (EABI) est en fait un BRAS de VAMP. J'ai un signet pointant vers http://www.arm.com/pdfs/bsabi.zip comme un endroit pour obtenir les BRAS ABI spécification, mais ce lien semble être obsolète.

À partir de la VAMP, §5.1.1:

  • r0 r3 sont l'argument et de rayer des registres; r0-r1 sont aussi le résultat des registres
  • r4-r8 sont callee-save enregistre
  • r9 peut être un callee-save inscrire ou non (sur certaines variantes de VAMP c'est un registre spécial)
  • r10-r11 sont callee-save enregistre
  • r12-r15 sont des registres spéciaux

Un callee-save registre doit être enregistré par le destinataire de l'appel (en opposition à un caller-save registre, où l'appelant enregistre le registre); donc, si c'est l'ABI que vous utilisez, vous n'avez pas à enregistrer r10 avant d'appeler une autre fonction (la fonction est responsable de l'enregistrer).

Edit: le compilateur que vous utilisez ne fait aucune différence; gcc, en particulier, peut être configuré pour différents ABIs, et il peut même être modifiée sur la ligne de commande. En regardant le prologue/épilogue le code qu'il génère n'est pas très utile, car il est fait sur mesure pour chaque fonction et le compilateur peut utiliser d'autres moyens d'économiser un registre (par exemple, l'enregistrement au moyen d'une fonction).

27voto

Pavel Points 1715

Ajouter info manquante sur NEON registres:

À partir de la VAMP, §5.1.1 Base de registres:

  • r0 r3 sont l'argument et de rayer des registres; r0-r1 sont aussi le résultat des registres
  • r4-r8 sont callee-save enregistre
  • r9 peut être un callee-save inscrire ou non (sur certaines variantes de VAMP c'est un registre spécial)
  • r10-r11 sont callee-save enregistre
  • r12-r15 sont des registres spéciaux

À partir de la VAMP, §5.1.2.1 VFP registre des conventions d'utilisation:

  • s16–s31 (d8–d15, t4–q7) doit être préservé
  • s0–s15 (d0–d7, t0–t3) et d16–d31 (q8–q15) ne doivent pas être conservés

Original post:
bras-de-c-appel-convention-néon-registres à sauvegarder

7voto

Sven Points 119

Les réponses de CesarB et Pavel fourni des citations de VAMP, mais les problèmes demeurent. Ne le destinataire de l'appel enregistrer r9? Ce sujet r12? Qu'en est r14? En outre, les réponses étaient très générales et non spécifiques à l'arm-eabi chaîne d'outils comme demandé. Voici une approche pratique pour savoir qui de s'inscrire sont appelé-sauvé et qui ne le sont pas.

Suivants du code C contient une ligne du bloc d'assemblage, qui prétend modifier les registres r0-r12 et r14. Le compilateur va générer le code pour enregistrer les registres requis par l'ABI.

void foo() {
  asm volatile ( "nop" : : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11", "r12", "r14");
}

Utiliser la ligne de commande arm-eabi-gcc-4.7 -O2 -S -o - foo.c et ajouter les commutateurs pour votre plate-forme (comme -mcpu=arm7tdmi par exemple). La commande imprimer le code assembleur généré sur la sortie standard STDOUT. Il peut ressembler à quelque chose comme ceci:

foo:
    stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    nop
    ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    bx  lr

Notez que le code généré par le compilateur, enregistre et restaure r4-r11. Le compilateur ne pas enregistrer r0 r3, r12. Qu'il restaure r14 (alias lr) est purement accidentelle, comme je le sais par expérience que le code de sortie peut également charger enregistré lr en r0 et puis faire un "bx r0" au lieu de "bx lr". Soit par l'ajout de l' -mcpu=arm7tdmi -mno-thumb-interwork ou en utilisant -mcpu=cortex-m4 -mthumb nous obtenons légèrement différente de l'assemblée de code qui ressemble à ceci:

foo:
    stmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, lr}
    nop
    ldmfd   sp!, {r4, r5, r6, r7, r8, r9, sl, fp, pc}

Encore une fois, r4, r11 sont sauvegardés et restaurés. Mais r14 (alias lr) n'est pas restauré.

Pour résumer:

  • r0 r3 sont pas callee-saved
  • r4-r11 sont callee-saved
  • r12 (alias ip) n'est pas callee-saved
  • r13 (alias sp) est callee-saved
  • r14 est pas callee-saved
  • r15 (alias pc) est le compteur de programme, et est fixé à la valeur de lr avant l'appel de la fonction

Cela tient, au moins pour arm-eabi-gcc par défaut de l'. Il y a des commutateurs de ligne de commande (en particulier les mabi switch) qui peuvent influencer les résultats.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X