Question

Supposons qu'on a deux entiers et les variables caractères:

int adad=12345;
char character;

En supposant que nous discutons d'une plate-forme dans laquelle, la longueur d'une variable entière est supérieure ou égale à trois octets, je veux accéder à la troisième octet de cet entier et le mettre dans la variable de caractère, que nous avons dit que je écrire comme ceci:

character=*((char *)(&adad)+2);

Étant donné que la ligne de code et le fait que je ne suis pas un compilateur ou un ensemble d'experts, je connais un peu les modes d'adressage dans l'assemblage et je me demande adresse du troisième octet ( ou je suppose qu'il vaut mieux dire décalage du troisième octet ) serait ici dans les instructions générées par cette ligne de code eux-mêmes, ou il serait dans une variable distincte dont adresse (ou Impression offset ) est dans ces instructions?

Était-ce utile?

La solution

La meilleure chose à faire dans des situations comme celle-ci est de l'essayer. Voici un exemple de programme:

int main(int argc, char **argv)
{
  int adad=12345;
  volatile char character;

  character=*((char *)(&adad)+2);

  return 0;
}

J'ai ajouté le volatile pour éviter la ligne d'affectation étant complètement optimisé loin. Maintenant, voici ce que le compilateur est venu avec (pour -Oz sur mon Mac):

_main:
    pushq   %rbp
    movq    %rsp,%rbp
    movl    $0x00003039,0xf8(%rbp)
    movb    0xfa(%rbp),%al
    movb    %al,0xff(%rbp)
    xorl    %eax,%eax
    leave
    ret

Les trois lignes que nous nous soucions sont:

    movl    $0x00003039,0xf8(%rbp)
    movb    0xfa(%rbp),%al
    movb    %al,0xff(%rbp)

Le movl est l'initialisation de adad. Ensuite, comme vous pouvez le voir, il lit le 3ème octet de adad, et le stocke dans la mémoire de retour (le volatile oblige ce retour du magasin).

Je suppose une bonne question est pourquoi il vous importe ce qui sera assembleur généré? Par exemple, en changeant mon drapeau d'optimisation pour -O0, la sortie d'assemblage de la partie intéressante du code est:

    movl    $0x00003039,0xf8(%rbp)
    leaq    0xf8(%rbp),%rax
    addq    $0x02,%rax
    movzbl  (%rax),%eax
    movb    %al,0xff(%rbp)

Ce qui est assez vu comme les carrément opérations logiques exactes de votre code:

  1. Initialiser adad
  2. Prenez l'adresse de adad
  3. Ajoutez 2 à cette adresse
  4. Charger un octet par déréférencement la nouvelle adresse
  5. Magasin un octet dans character

Diverses optimisations changeront la sortie ... si vous avez vraiment besoin un comportement spécifique / mode d'adressage pour une raison quelconque, vous pourriez avoir à écrire vous-même assemblée.

Autres conseils

Sans rien savoir sur le compilateur et l'architecture du processeur sous-jacente ne peut être donné de réponse définitive. Par exemple, toutes les architectures CPU permettent l'adressage de chaque octet arbitraire dans la mémoire (si je crois que tous les actuellement plus populaires faire): sur une CPU de mot adressé, au lieu d'octet adressé, ce que le compilateur va générer va inévitablement d'être le chargement dans un certain registre de l'ensemble du mot adad (vraisemblablement par un décalage à partir d'un registre de pointeur de base, si la variable en question est sur la pile [1]), suivi de déplacement et de masquage pour isoler l'octet d'intérêt.

[1] A noter que, sans savoir ce que l'architecture du processeur dont nous parlons et comment l'utilisation du compilateur, on ne peut même pas dire si « charger un mot à un décalage fixe d'un registre de base » est quelque chose qui fait en ligne au sein de l'instruction (comme on pourrait l'espérer, et de nombreuses architectures populaires faire certainement un soutien ;-) ou a besoin arithmétique d'adresse séparée dans un registre auxiliaire.

OIEau, que ce soit une bonne idée ou non, il est certainement possible pour définir une architecture de CPU qui ne peut pas charger / registres de magasins, sauf d'autres registres ou adresses mémoire définies par d'autres registres ou constante, et certains de telles architectures existent (bien qu'ils ne peuvent pas être tout ce populaire à cette époque; -).

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top