Bonjour à tous,
J'écris ici car il y a quelque chose qui m'échappe totalement.
en adressage absolu, c'est pas compliqué.
movl data,%eax
en simili C
eax = *data
en adressage indexé non plus
movl 42(%esi),%eax
eax = *(esi + 42)
mais en adressage relatif, je suis perdu
movl data(%rip),%eax
#du code
#ici aussi
movl %eax,data(%rip)
La même instruction est utilisée, pour référencer le même endroit, sauf qu'entre les deux rip a changé. Donc, la sémantique le movl change si rip est l'une des opérandes ?
Je ne comprend pas comment ça marche.
Lors de la phase d'assemblage, les décalage sont recalculés ? (en désassemblant on retrouve des constantes), mais en lisant le fichier octet par octet je me rend compte deux deux instructions semblable à deux endroits différent se retrouvent encodée de la même manière dans le binaire, donc, je ne comprend pas.
Merci beaucoup si vous pouvez m'éclairer.
ajout : effectivement, movl data(%rip),%eax et movl data(%rsi),%eax sont deux instructions différentes, elles ne font même pas la même taille.
En fait, à l'exécution (au linkage ?) il connait la différence entre l'adresse 0 de la première instruction et l'adresse data, et à chaque fois qu'il y a un data(%rpi) il y ajoute cette différence ?
# Questions pas très claire
Posté par Michaël (site web personnel) . Évalué à 3.
Je n'ai pas compris toutes les questions que tu poses, entre les fautes de frappe sur les registres et les imprécisions… je vais cependant faire de mon mieux.
Je ne comprend pas trop ce que tu veux dire… dans le schéma de travail
Source -> Assemblage -> Fichier objet
Fichier objets -> Édition des liens -> Fichier final
beaucoup d'adresses sont inconnues à l'assemblage, donc le fichier objet les recense et elles sont résolues à l'édition des liens. Notamment ton data est inconnue l'assemblage mais l'est à l'édition des liens.
C'est parceque l'architecture Intel est une architecture basée sur des registres spécialisés. Ainsi les registres ne sont pas interchangeables et ont des rôles préassignés. AX est l'accumulateur, CX est le compteur de boucle, SI le source indicator et DI le destination indicator, BP est le base pointer. Ainsi les lectures et écritures sur des adresses mémoire de type {DI,SI,BP} + offset sont des formes attendues et sont représentées par une instruction courte, tandis que si tu utilises un autre registre, le nom du registre doit aussi être codé dans l'instruction. C'est comme si il y avait des instructions
movl_from_si
movl_from_bp
movl_from_generic
movl_to_di
movl_to_bp
movl_to_generic
De quelles instructions s'agit-il? Sont-elles semblables ou identiques? Si elles sont identiques, c'est plutôt normal non?
[^] # Re: Questions pas très claire
Posté par Zylabon . Évalué à 1.
Désolé pour la forme du premier message, je sais pas pourquoi à chaque fois que je tape rip je me dis « Non, ça peut pas être ça » (je l'ai
corrigéchangé partout) bref !La première et la dernière instruction sont identiques, en tout point. Elles font la même chose, et pourtant si %rip vaut 0 lors de la première instruction, lors de la dernière il vaut 10.
La question c'est comment est-ce que le processeur fait pour calculer des positions fixes dans en mémoire en utilisant rip qui change à chaque instructions traitées ?
Please do not feed the trolls
[^] # Re: Questions pas très claire
Posté par Michaël (site web personnel) . Évalué à 2. Dernière modification le 01 avril 2012 à 23:25.
Mh… j'ai toujours quelques problèmes. Tu parles de deux choses: le code assembleur et sa traduction en binaire, mais tu ne donnes que l'une…
J'ai l'impression que tu confonds le registre et son contenu.
Ce qui est commun aux instructions c'est le registre, pas son contenu.
[^] # Re: Questions pas très claire
Posté par Zylabon . Évalué à 1. Dernière modification le 02 avril 2012 à 00:05.
Lors de la première instruction, rip contient 0, lors de la seconde instruction rip contient 10.
Et pourtant, le résultat de ces deux instructions est de mettre ce qu'il y a dans la mémoire à l'adresse data dans %eax. Non ?
Je ne comprend pas comment il fait pour calculer.
rip c'est bien le compteur ordinal ? Raw Instruction Pointer. Autrement dit, le contenu de ce registre change à chaque nouvelle instructions.
Un peu de vrai code :
l'assembleur généré :
et le binaire généré a.o :
Dans le AMD64 Architechture Programmer's Manual v1 on lit :
Autrement dit la valeur contenue dans ce registre change après chaque instruction traitée par le processeur.
Et pourtant dans mon code C, il n'y a qu'un seul 'a', qui a une position fixe dans la mémoire. Et dans le code assembleur généré, et dans le binaire il est question du registre rip pour y accéder, avec la même syntaxe que pour le l'adressage indexé. mov offset(registre),registre. Bref, on accède à une position fixe grâce à un registre dont la valeur qu'il contient change après chaque instruction traitée.
La question : Comment ça marche ?
Please do not feed the trolls
[^] # Re: Questions pas très claire
Posté par Amand Tihon (site web personnel) . Évalué à 2.
Regarder le fichier .o n'a pas beaucoup de sens. Tant que l'édition de liens n'a pas été faite, les offsets des différentes instructions sont généralement à zéro.
Après application des relocations par le linker, tu devrais voir des
0xtruc(%rip)
, avec "truc" qui change, de manière à toujours pointer au même endroit.[^] # Re: Questions pas très claire
Posté par Zylabon . Évalué à 1.
D'accord, je vois ! Tout s’éclaircit
Dans mon esprit d'édition de lien c'était pas grand chose de plus que plein ce copie de code dans un gros fichier exécutable.
Merci beaucoup.
Please do not feed the trolls
# Confusion ?
Posté par Kerro . Évalué à 5. Dernière modification le 01 avril 2012 à 12:51.
Je n'ai as bien compris ton problème. Ton explication n'est pas claire, et c'est peut-être dû à une confusion que tu fais.
Dans cet exemple, c'est exactement la même instruction dans les deux cas. "data" est une constante que tu as défini précédemment dans ton code.
Il n'y a pas d'adressage relatif pour les données. Il y en a pour les sauts (jmp et call), probablement pour gagner de la place. Mais pas pour les données.
Adressage relatif = par rapport au pointeur d'instruction
Tu ne peux pas dire que tu veux accéder à une donnée située 42 octets plus loin que le pointeur d'instruction.
Suivre le flux des commentaires
Note : les commentaires appartiennent à celles et ceux qui les ont postés. Nous n’en sommes pas responsables.