web-dev-qa-db-fra.com

Pourquoi utiliser LDR sur MOV (ou vice versa) dans l'assemblage ARM?

Je regarde ce tutoriel: http://www.cl.cam.ac.uk/freshers/raspberrypi/tutorials/os/ok01.html

La première ligne d'assemblage est:

ldr r0,=0x20200000

le second est:

mov r1,#1

Je pensais que ldr était pour charger des valeurs de la mémoire dans des registres. Mais il semble que le = signifie que 0x20200000 est une valeur et non une adresse mémoire. Les deux lignes semblent charger les valeurs absolues.

25
Jonathan.

C'est un truc/raccourci. dis par exemple

ldr r0,=main

ce qui se passerait, c'est que l'assembleur allouerait un mot de données, près de l'instruction mais en dehors du chemin de l'instruction

ldr r0,main_addr
...
b somewhere
main_addr: .data main

Maintenant, étendez cette astuce aux constantes/immédiats, en particulier à ceux qui ne peuvent pas entrer dans une instruction immédiate de déplacement:

top:
add r1,r2,r3
ldr r0,=0x12345678
eor r1,r2,r3
eor r1,r2,r3
b top

assembler puis démonter

00000000 <top>:
   0:   e0821003    add r1, r2, r3
   4:   e59f0008    ldr r0, [pc, #8]    ; 14 <top+0x14>
   8:   e0221003    eor r1, r2, r3
   c:   e0221003    eor r1, r2, r3
  10:   eafffffa    b   0 <top>
  14:   12345678    eorsne  r5, r4, #125829120  ; 0x7800000

et vous voyez que l'assembleur a ajouté les données Word pour vous et a changé le ldr en un pc relatif pour vous.

maintenant si vous utilisez un immédiat qui correspond à une instruction mov, puis en fonction de l'assembleur peut-être, certainement avec le gnu que j'utilise, il l'a transformé en mov pour moi

top:
add r1,r2,r3
ldr r0,=0x12345678
ldr r5,=1
mov r6,#1
eor r1,r2,r3
eor r1,r2,r3
b top


00000000 <top>:
   0:   e0821003    add r1, r2, r3
   4:   e59f0010    ldr r0, [pc, #16]   ; 1c <top+0x1c>
   8:   e3a05001    mov r5, #1
   c:   e3a06001    mov r6, #1
  10:   e0221003    eor r1, r2, r3
  14:   e0221003    eor r1, r2, r3
  18:   eafffff8    b   0 <top>
  1c:   12345678    eorsne  r5, r4, #125829120  ; 0x7800000

Il s'agit donc essentiellement d'un raccourci de frappe, comprenez que vous donnez à l'assembleur le pouvoir de trouver un endroit pour coller la constante, ce qui fait généralement du bon travail, se plaint parfois, je ne sais pas si je l'ai vu ne pas le faire en toute sécurité. Parfois, vous avez besoin d'un .ltorg ou .pool dans le code pour encourager l'assembleur à trouver une place.

18
old_timer

Une réponse plus courte, venant de quelqu'un qui est plus proche de votre niveau, j'espère que cela aide: dans ARM, les instructions ont 32 bits. Certains bits sont utilisés pour identifier l'opération, certains pour les opérandes et, dans le cas de l'instruction MOV, certains sont disponibles pour une valeur immédiate (# 1, par exemple).

Comme vous pouvez le voir ici (page 33), il n'y a que 12 bits disponibles pour la valeur immédiate. Au lieu d'utiliser chaque bit comme nombre (compris entre 0 et 2 ^ 12-1 ~ 4095), l'instruction calcule le nombre immédiat en tournant à droite (ROR) les 8 premiers bits de deux fois la quantité spécifiée dans les 4 derniers bits . Autrement dit, immediate = first 8 bits ROR 2*(last four bits).

De cette façon, nous pouvons atteindre beaucoup plus de chiffres que juste 4096 (voir page 34 pour un bref résumé des immédiats possibles).

Juste au cas où notre nombre ne peut pas être converti en une instruction comme la précédente (257 ne peut pas être exprimé comme 8 bits tournés deux fois tous les 4 bits), alors, nous devons utiliser LDR r0, = 257

Dans ce cas, le compilateur enregistre le numéro 257 en mémoire, à proximité du code de programme, de sorte qu'il peut être adressé par rapport au PC, et le charge à partir de la mémoire, comme expliqué en détail par dwelch.

Remarque: Si vous suivez ce didacticiel, lorsque vous essayez de `` créer '' avec mov r0, # 257, vous obtenez une erreur et vous devez essayer manuellement ldr r0, = 257.

8
Fernando

Aussi bonnes que soient les autres réponses, je pense que je pourrais être en mesure de simplifier la réponse.

ldr = Registre LoaD

mov = MOVe

Les deux font effectivement la même chose mais de manières différentes.

La différence ressemble beaucoup à la différence entre

#define CONST 5

et

int CONST = 5;

en langage C.

mov est vraiment rapide car il a la valeur associée directement stockée en tant que partie de l'instruction (au format 12 bits décrit dans la réponse ci-dessus). Il a certaines limites en raison de la façon dont il stocke la valeur. Pourquoi? Car

  • 12 bits n'est pas suffisant pour stocker des nombres énormes comme les adresses mémoire 32 bits.
  • 8 premiers bits ROR 2 * (4 derniers bits) ne peut pas représenter n'importe quel nombre, même dans la plage de 12 bits.

ldr, d'autre part, est polyvalent (principalement en raison des optimisations du compilateur). Cela fonctionne comme ceci (comme indiqué dans la routine démontée)

  • Si la valeur peut être représentée au format 12 bits et 8 premiers bits ROR 2 * (4 derniers bits), le compilateur la change en mov instruction accompagnant la valeur.

  • Sinon, la valeur est conservée sous forme de données, chargées dans la RAM, à un emplacement. Et il est chargé dans le registre requis en accédant à partir de la mémoire en utilisant l'offset du compteur de programme.

J'espère que cela a aidé.

2
Suhel Chakraborty