web-dev-qa-db-fra.com

Comment utiliser l'instruction MOV dans ARM avec un nombre immédiat comme deuxième opérande

Je commence tout juste à étudier le langage d'assemblage ARM et je ne vois pas comment utiliser MOV pour transférer un nombre immédiat dans un registre.

À la fois dans le manuel de référence ARM et dans mon manuel, il est dit que la plage du nombre immédiat suivant l'instruction MOV est comprise entre 0 et 255. Mais lorsque je teste mon propre PC dans ADS 1.2 IDE, les instructions

MOV     R2, #0xFFFFFFFF

fonctionne bien. Le nombre 0xFFFFFFFF n'est-il pas hors de portée conformément à la spécification?

J'espère que quelqu'un pourra me donner un coup de main.

Cordialement.

16

Rappelez-vous que le ARM peut effectuer un certain ensemble de manipulations sur la valeur immédiate en tant que partie du déphaseur à barillet incorporé dans les codes d'opération de l'ARM.

Ce petit article fournit l'une des explications les plus claires de certaines astuces qu'un assembleur ARM peut utiliser pour insérer un grand nombre immédiat dans le petit espace disponible d'une instruction ARM:

L'article décrit l'astuce probablement utilisée dans votre exemple spécifique de génération d'un opcode MVN pour charger le complément au niveau du bit de la valeur immédiate.

Ce type de manipulation ne peut pas être fait avec toutes les valeurs immédiates, mais les assembleurs ARM sont supposément assez intelligents à ce sujet (et les compilateurs C le sont certainement). Si aucune astuce de décalage/complément ne peut être exécutée, la valeur sera généralement chargée depuis un emplacement relatif au PC ou peut-être en "construisant" la valeur à partir de plusieurs instructions.

13
Michael Burr

Une seule instruction ARM ne peut coder qu'une constante immédiate pouvant être représentée sous la forme d'une valeur immédiate de 8 bits, décalée de tout même puissance de deux.

Cependant, il existe également une instruction MVN, qui ressemble à MOV mais inverse tous les bits. Ainsi, bien que MOV R2, #0xFFFFFFFF ne puisse pas être codé sous la forme d'une instruction MOV, il peut être codé sous la forme MVN R2, #0. L'assembleur peut bien effectuer cette conversion pour vous.

11
Matthew Slattery

L'instruction MOV peut accepter la valeur imm16 ou la valeur opérateur 2 (en raison de la longueur de l'instruction opposée à l'alignement de la mémoire), qui doit respecter l'une des règles suivantes (copiée à partir du manuel du jeu d'instructions CortexM, X et Y représentant une valeur hexadécimale quelconque):

  • Toute constante pouvant être produite en décalant une valeur de 8 bits laissée par un nombre quelconque de bits dans un mot de À 32 bits.
  • Toute constante de la forme 0x00XY00XY.
  • Toute constante de la forme 0xXY00XY00.
  • Toute constante de la forme 0xXYXYXYXY.

C'est pourquoi 0xFFFFFFFF est accepté (conforme à la 4ème règle).

Si vous souhaitez assembler votre propre constante 32 bits, vous pouvez utiliser l'instructionMOVT, qui écrit dans la moitié supérieure d'un registre.

2
user4219605

Vous pouvez voir des artefacts provenant de l'extension de signe de la valeur d'origine. Si les outils que vous utilisez pour afficher le désassemblage traitent le 0..255 comme un octet signé, puis, lorsqu'il le charge dans un type int (ou un registre) plus grand, il remplira tous les bits supérieurs avec le bit de signe de l'original. valeur. Autrement dit, si 0xFF est un octet signé, sa valeur décimale est -1. Mettez cela dans un registre 32 bits et l'hexagone ressemblera à 0xFFFFFFFF, et sa valeur décimale est toujours -1.

Essayez d’utiliser une valeur sans le bit fort défini, telle que 0x7F. Étant donné que le bit de signe n'est pas défini, je suppose qu'il remplira les bits supérieurs par zéro lorsqu'il sera chargé dans un registre ou un champ de type int plus grand.

Il est également possible que le compilateur/assembleur tronque la valeur fournie. Je considérerais cela comme une erreur de code source, mais les assembleurs sont de drôles de bêtes. Si vous lui donnez 0x7FF, compilez-vous en 0x7FF (non tronqué et supérieur à 0..255) ou en 0xFFFFFFFF (tronqué à 0..255, octet signé)?

1
dthorpe

Il est un peu difficile de déterminer si les constantes données sont dans la plage valide.

Comme Matthew l'a déjà mentionné, l'assembleur vous prête la main en remplaçant les instructions données par des instructions similaires, telles que mov/mvn, cmp/cmn, tst/tne, etc.

1