2010-08-27 3 views
4

Je regardais la sortie assembleur de mon code et j'ai besoin d'aide pour les instructions ci-dessous.Besoin d'aide pour comprendre ces instructions ARM

- // -

0x00000fe8: e28fc000 .... ADR  r12,{pc}+8 ; 0xff0 

    0x00000fec: e28cca08 .... ADD  r12,r12,#8, 20 ; #0x8000 

- // -

De ma compréhension de la 1ère instruction provoque r12 à charger avec

« {valeur pc} + 8 »qui est

"{Adresse de l'instruction en cours en cours d'exécution (0xfe8) plus 2 instructions avant (8)} + 8"

est donc r12 après le 1er exécution d'une instruction chargé de 0xff8 (0xfe8 + 8 + 8)

en ce qui concerne également la 2e instruction -

Comment calculer la valeur ajoutée et étant stockée à r12? (le commentaire dit 0x8000, bien que je ne sois pas capable de comprendre comment il l'a obtenu)

Répondre

8

La première instruction (en réalité une pseudo-instruction) charge une adresse relative au PC dans R12. Puisque l'instruction est à l'adresse 0xFE8, l'expression {pc} +8 évalue à 0xFF0. Le résultat de la première instruction est donc de charger la valeur 0xFF0 dans R12. Le commentaire indique réellement ceci.

(Notez que l'ADR est pas une vraie instruction ARM, l'assembleur remplace par une instruction telle que ADD. Notez également que la valeur de cette expression est calculée au moment de l'assemblage . Pendant le programme exécution, les points PC en avance de l'instruction en cours, en raison du pipeline du processeur.Que dépend de l'architecture (par exemple ARM7, etc.) et du mode de fonctionnement (Thumb/ARM).) Je risque de donner trop d'informations ici à propos de ADR & Expressions/adressages relatifs au PC, mais il est facile de se faire mordre si vous ne comprenez pas ce qui se passe dans les coulisses.)

La seconde instruction (en train de lire de droite à gauche) indique effectivement "prendre la constante 0x8, la tourner à droite de 20 bits (qui est la même chose qu'un décalage gauche de 12 bits, 32-20 = 12), AJOUTER à R12 (qui contient actuellement 0xFF0), et le stocker dans R12. " 0x8 < < 12 = 0x8000, de sorte que la 2ème instruction entraîne R12 en attente 0x8000 + 0xFF0 = 0x8FF0.

Remarque: Dans votre explication, lorsque vous avez dit "2 instructions à venir", ne tombez pas dans cette habitude, pensez-y comme 8 octets, pas 2 instructions. L'instruction dit ajouter 8 octets, il ne dit rien sur les instructions. Les instructions ne sont pas nécessairement longues de 4 octets (par exemple, dans Thumb, elles sont 2 octets, dans Thumb2, elles sont 2 octets ou 4 octets, selon l'instruction).

+0

Salut Dan, Merci beaucoup! :) Beaucoup de fumée a été nettoyée maintenant !! ;) Oui, vous avez raison à propos de l'ADR évalué à ADD. Il se résume à ADD r12, pc, 0 Désolé d'être naïf, (mais je suis toujours :(jusqu'à ce que je reçois un certain temps) Donc, au moment d'assemblage {pc} +8 signifie que je interprète simplement comme l'adresse de l'instruction en cours + 8? Est-ce que je dois garder à l'esprit ..? –

3

Je suis respectueusement en désaccord avec Dan, c'est deux instructions à venir, c'est ainsi que fonctionne le pipeline. La taille de l'instruction est de 2 octets pour le pouce ou de 4 octets pour le bras, de sorte que deux instructions à venir aboutissent à 4 ou 8 octets. Ce n'est pas un octet X arbitraire devant, c'est deux instructions qui vont devant.

La plupart des gens utiliseront simplement des étiquettes et n'auront jamais besoin de savoir comment cela fonctionne.Pour les gestionnaires d'exceptions SI vous utilisez le mode pouce, vous devrez le gérer et toutes les versions de ARM ARM ne sont pas claires, certaines versions disent simplement que le registre de retour contient l'adresse + 8 quand ils signifient adresse + deux instructions (ce qui signifie 4 ou 8 selon le mode qui est indiqué par l'adresse de l'adresse), au fil du temps le bras ARM s'améliore mais les plus anciens ont beaucoup de bugs. La plupart des gens n'ont jamais besoin de savoir ou de s'inquiéter de cette instruction à deux choses.

La réponse principale à vos questions se trouve dans le ARM ARM (le manuel de référence de l'architecture ARM), dans le codage des instructions. Afin d'avoir des instructions de longueur fixe, ce qui signifie que toutes les instructions de mode ARM sont de 32 bits, les valeurs immédiates doivent être assez limitées. Donc, pour de nombreuses instructions comme l'ajout, vous pouvez seulement dire 8 "bits significatifs" et quelques bits pour le décalage. Donc, le nombre 0x1001 ne fonctionnerait pas, en binaire, cette valeur est 0b0001000000000001. Les premier et dernier bits non-nuls (bits significatifs) nécessitent 13 bits de stockage. mais le 0x8000 dans votre exemple a seulement 1 bit significatif de sorte que peut facilement être stocké et déplacé de plusieurs manières dans l'instruction. Pour les jeux d'instructions ayant des instructions de longueur variable, x86 par exemple, vous pouvez avoir des immédiates complets, vous pouvez charger ou ajouter la valeur 0x12345678 car 0x12345678 n'est pas encodé dans l'opcode principal lui-même il suit l'opcode en mémoire et peut être de tailles variables pour répondre aux besoins de l'ensemble d'instructions. Il y a des avantages et des inconvénients à la longueur fixe et variable qui est au-delà de cette discussion. Le point étant que le ARM ARM inclut non seulement des définitions de champ de bits mais chaque instruction a un pseudo code expliquant comment les différents champs de bits sont utilisés, y compris des choses comme le pc étant deux devancées de l'instruction en cours d'exécution.

L'adressage relatif de PC n'est pas quelque chose que vous traitez normalement avec les messages instantanés limités que vous traiterez tout le temps, il est bon de savoir quelles instructions ont quelles longueurs immédiates. Il devient plus difficile avec le mode pouce que le mode bras de se souvenir quelles opérations permettent quelle taille immédiatement.

+0

Merci Dwelch pour explication détaillée! :) –

+2

aussi respectueusement, je pense que vous avez mal compris mon commentaire sur la façon de penser à la +8. (Ou peut-être que j'ai mal compris votre commentaire?) +8 est équivalent à +2 instructions * seulement parce que * nous sommes en mode ARM. Si vous êtes en mode Thumb, +8 signifie +4 instructions. Le nombre d'instructions +8 traduites dépend du mode de fonctionnement de la CPU. Cette même ligne de code, exécutée en mode Thumb, * sautera encore 8 octets, mais maintenant elle saute 4 instructions *. La seule chose que vous pouvez dire sans plus de contexte est qu'il saute 8 octets. Pipelining affecte la distance à laquelle le PC pointe, mais pas ce que signifie +8. – Dan

+0

Probablement une meilleure façon d'expliquer ce que je voulais dire: en C, si "fooptr" est une variable ptr, alors fooptr ++ signifie littéralement "avance d'un foo". Si cela pointe vers char, c'est prob. 1 octet S'il pointe vers un int, il avance probablement de 4 octets. Mais le code C signifie littéralement "avance par un truc", peu importe ce que cela signifie. Mon point est que le "+8" signifie littéralement "+8 octets", indépendamment du nombre d'instructions qui se traduit par. J'ai du mal à l'expliquer mieux que ça. – Dan

Questions connexes