IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C++ Discussion :

Simuler les registres d'un processeur


Sujet :

C++

  1. #1
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut Simuler les registres d'un processeur
    Bonjour à tou(te)s,

    Je cherche à simuler les registres d'un processeur.
    J'ai donc imaginé des registres un peu comme dans un processeur intel :
    AH
    AL
    AX
    AEX

    Je souhaite obtenir ce genre de modèle en mémoire :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    AEX
    AY                AX
                      AH       AL
    00000000 00000000 00000000 00000000
    Où AY est un "registre" non utilisable, et j'ai naturellement pensé aux structures. Mais je n'arrive pas à bien poser tout ca. En fait, j'ai essayé quelques trucs, mais j'obtiens des trucs vraiment bizarres ou des erreurs de compilo. Quelqu'un a déjà fait ca ? Sinon je poserai le problème bien à plat, parce que là je n'arrive pas trop à me concentrer

    PS : un essai infructueux, ne grondez pas, je n'arrive plus à réfléchir
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    union x_register
    {
        unsigned short int x;
        struct sub
        {
            unsigned char l;
            unsigned char h;
        };
    };
    EDIT : Je vais voir si l'utilisation d'un objet ne serait pas plus simple, et tant pis pour la "perte" de mémoire.
    Mindiell
    "Souvent, femme barrit" - Elephant man

  2. #2
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    Je ne sais pas si tu connais les "union", c'est exactement ce dont tu as besoin. Une petite recherche devrait te donner des exemples.

  3. #3
    screetch
    Invité(e)
    Par défaut
    il me semblait que le coup des unions, c'etait pas loin
    un probleme, c'est que les unions n'ont qu'une garantie, c'est de n'offrir aucune garantie
    du coup il me semble qu'une classe C++ serait mieux
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    class Register
    {
    private:
      unsigned int m_value;
    public:
      unsigned int ex() { return m_value; }
      unsigned short y() { return (m_value >> 16) & 0xffff; }
      unsigned short x() { return m_value & 0xffff; }
      unsigned char h() { return (m_value >> 8) & 0xff; }
      unsigned char l() { return m_value & 0xff; }
    };
    a priori tout sera optimisé au mieux

  4. #4
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    j'aurais fait un truc du genre:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    struct reg
    {
    	union
    	{
    		__int32 eax;
    		struct
    		{
    			__int16 ay;
    			union
    			{
    				__int16 ax;
    				struct
    				{
    					__int8 ah;
    					__int8 al;
    				};
    			};
    		};
    	};
    };
    Il me semble que le seul problème c'est si le compilateur pad pas les champs des structures octet par octet.

    Après dans les deux cas tout ça ne va pas si tu fais tourner ton programme sur une architecture non little-endian.

  5. #5
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    J'avais pensé aux unions, mais j'avais du mal faire un truc car je suis revenu aux structures... Je vous ai dit que j'étais fatigué

    Sinon, sur les archi types Intel, en effet, le contenu des struct est à mettre à l'envers.
    Je vais regarder ta solution Twindruff, merci
    Mindiell
    "Souvent, femme barrit" - Elephant man

  6. #6
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Bon, la solution semble intéressante, mais pour manipuler ca, ca va pas forcément être simple, non ?

    un petit "reg a;" ne me permet pas facilement de manipuler le ax ou les ah et al... Va falloir que je me plonge sérieusement là-dedans moi.
    Mindiell
    "Souvent, femme barrit" - Elephant man

  7. #7
    Membre actif Avatar de Twindruff
    Inscrit en
    Janvier 2005
    Messages
    216
    Détails du profil
    Informations forums :
    Inscription : Janvier 2005
    Messages : 216
    Points : 237
    Points
    237
    Par défaut
    De rien .
    En fait contrairement à ce qu'on pourrait croire on peut accéder à tous les champs directement:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    reg r;
    r.eax = 1;
    r.ay = 2;
    r.ax = 3;
    r.al = 4;
    r.ah = 5;

  8. #8
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Et ca marche parfaitement...
    Merci encore à toi.

    A moi de jouer maintenant
    Mindiell
    "Souvent, femme barrit" - Elephant man

  9. #9
    screetch
    Invité(e)
    Par défaut
    c'est une extension du langage C++ cependant, sous suncc ca va planter lamentablement, et attention a la représentation binaire qui peut changer (rien n'est garanti avec les union)
    donc attention pour la portabilité

  10. #10
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Tu peux mieux expliciter le problème pour suncc ?
    Et pour le binaire, quel est le problème ?

    Merci,
    De toute facon je regarderai les union de plus près.
    Mindiell
    "Souvent, femme barrit" - Elephant man

  11. #11
    screetch
    Invité(e)
    Par défaut
    les "union non nommées" sont une extension du langage si je me souviens bien
    lorsque le compilateur ne les supporte pas, tu dois ecrire
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    struct reg
    {
    	union
    	{
    		__int32 eax;
    		struct
    		{
    			__int16 ay;
    			union
    			{
    				__int16 ax;
    				struct
    				{
    					__int8 ah;
    					__int8 al;
    				} e8;
    			} e16;
    		};
    	} e32;
    };
    du coup pour atteindre ah, tu dois ecrire
    de mémoire, suncc n'a pas cette extension, mais GCC, Intel, MSVC l'ont

    quant a la représentation binaire, le compilateur ne garantit rien; en général ca marche mais aucune garantie

    par exemple, rien ne force le compilateur a partager l'espace memoire
    de plus, si tu as
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    union
    {
      int8 byte;
      int32 dword;
    }
    meme si la memoire est partagée, le compilateur peut utiliser n'importe lequel des 4 octets pour mettre ses données. Il peut tout aligner sur le premier octet de l'union ou sur le dernier... le byte peut se promener dans l'union. Chaque compilateur voudra peut etre faire sa sauce

    bref, les union c'est le mal

  12. #12
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Ok pour ton dernier exemple,
    Mais malgré tout, je ne souhaite mettre que des tailles identiques au final, donc tout devrait être stocké proprement, non ?

    Pour les unions nommés, j'ai bien compris, je vais partir là-dessus, de toute facon je suis le seul à utiliser l'union, les "utilisateurs" potentiels ne les verront même pas.

    Merci encore,
    Mindiell
    "Souvent, femme barrit" - Elephant man

  13. #13
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Pour le problème de réprésentation binaire, c'est une question d'endianness.
    Le code qui suit devrait marcher correctement sur un PC, mais sera faux sur une machine big-endian:
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    union reg16
    {
    	__int16 x;
    	struct
    	{
    		__int8 l;
    		__int8 h;
    	} e8;
    };

    Je pense que le mieux est d'utiliser ta classe, en rajoutant juste les const qu'il faut (et quelques fonctions inline/macros pour faciliter la manipulation):
    Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    /*
    Fonctions d'extraction
     
    Je les mets toutes, mais seules Word0, Word1, Byte0 et Byte1 sont utilisées ici.
    */
    inline unsigned __int16 Word0(unsigned __int64 val) { return (val      ) & 0x000000000000FFFFull; }
    inline unsigned __int16 Word1(unsigned __int64 val) { return (val >> 16) & 0x000000000000FFFFull; }
    inline unsigned __int16 Word2(unsigned __int64 val) { return (val >> 32) & 0x000000000000FFFFull; }
    inline unsigned __int16 Word3(unsigned __int64 val) { return (val >> 48) & 0x000000000000FFFFull; }
     
    inline unsigned __int16 Word0(unsigned __int32 val) { return (val      ) & 0x0000FFFFul; }
    inline unsigned __int16 Word1(unsigned __int32 val) { return (val >> 16) & 0x0000FFFFul; }
     
     
    inline unsigned __int8 Byte0(unsigned __int32 val) { return (val      ) & 0x000000FFul; }
    inline unsigned __int8 Byte1(unsigned __int32 val) { return (val >>  8) & 0x000000FFul; }
    inline unsigned __int8 Byte2(unsigned __int32 val) { return (val >> 16) & 0x000000FFul; }
    inline unsigned __int8 Byte3(unsigned __int32 val) { return (val >> 24) & 0x000000FFul; }
     
    inline unsigned __int8 Byte0(unsigned __int16 val) { return (val      ) & 0x00FFu; }
    inline unsigned __int8 Byte1(unsigned __int16 val) { return (val >>  8) & 0x00FFu; }
     
    /*
    Fonctions de promotion (non-signées)
    */
    inline unsigned __int64 Ext64(unsigned __int32 val) { return val; }
    inline unsigned __int64 Ext64(unsigned __int16 val) { return val; }
    inline unsigned __int64 Ext64(unsigned __int8  val) { return val; }
     
    inline unsigned __int32 Ext32(unsigned __int16 val) { return val; }
    inline unsigned __int32 Ext32(unsigned __int8  val) { return val; }
     
    inline unsigned __int16 Ext16(unsigned __int8  val) { return val; }
     
    /*
    Fonctions de réglage
    */
    inline unsigned __int64 Word0(unsigned __int64 val, unsigned __int16 w) { return (val & 0xFFFFFFFFFFFF0000ull) | (Ext64(w)      ); }
    inline unsigned __int64 Word1(unsigned __int64 val, unsigned __int16 w) { return (val & 0xFFFFFFFF0000FFFFull) | (Ext64(w) << 16); }
    inline unsigned __int64 Word2(unsigned __int64 val, unsigned __int16 w) { return (val & 0xFFFF0000FFFFFFFFull) | (Ext64(w) << 32); }
    inline unsigned __int64 Word3(unsigned __int64 val, unsigned __int16 w) { return (val & 0x0000FFFFFFFFFFFFull) | (Ext64(w) << 48); }
     
    inline unsigned __int32 Word0(unsigned __int32 val, unsigned __int16 w) { return (val & 0xFFFF0000ul) | (Ext32(w)      ); }
    inline unsigned __int32 Word1(unsigned __int32 val, unsigned __int16 w) { return (val & 0x0000FFFFul) | (Ext32(w) << 16); }
     
    inline unsigned __int32 Byte0(unsigned __int32 val, unsigned __int8 b) { return (val & 0xFFFFFF00ul) | (Ext32(b)      ); }
    inline unsigned __int32 Byte1(unsigned __int32 val, unsigned __int8 b) { return (val & 0xFFFF00FFul) | (Ext32(b) <<  8); }
    inline unsigned __int32 Byte2(unsigned __int32 val, unsigned __int8 b) { return (val & 0xFF00FFFFul) | (Ext32(b) << 16); }
    inline unsigned __int32 Byte3(unsigned __int32 val, unsigned __int8 b) { return (val & 0x00FFFFFFul) | (Ext32(b) << 24); }
     
    inline unsigned __int16 Byte0(unsigned __int16 val, unsigned __int8 b) { return (val & 0xFF00u) | (Ext16(b)      ); }
    inline unsigned __int16 Byte1(unsigned __int16 val, unsigned __int8 b) { return (val & 0x00FFu) | (Ext16(b) <<  8); }
     
    /*
    Classe de registre 32 bits.
    */
    class Register32
    {
    private:
    	unsigned __int32 m_value;
    public:
    	unsigned __int32 ex() const { return m_value; }
    	unsigned __int16 y() const { return Word1(m_value); }
    	unsigned __int16 x() const { return Word0(m_value); }
    	unsigned __int8 h() const { return Byte1(m_value); }
    	unsigned __int8 l() const { return Byte0(m_value); }
     
    	void ex(unsigned __int32 dw) { m_value = dw; }
    	void y(unsigned __int16 w) { m_value = Word1(m_value, w); }
    	void x(unsigned __int16 w) { m_value = Word0(m_value, w); }
    	void h(unsigned __int8 b) { m_value = Byte1(m_value, b); }
    	void l(unsigned __int8 b) { m_value = Byte0(m_value, b); }
     
    	signed __int32 exs() const { return ex(); }
    	signed __int16 ys() const { return y(); }
    	signed __int16 xs() const { return x(); }
    	signed __int8 hs() const { return h(); }
    	signed __int8 ls() const { return l(); }
    };
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  14. #14
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Je crois que, finalement, je vais utiliser des variables différentes, et je "perdrais du temps" dans ma classe à remplir correctement les différentes variables.
    Ou alors, j'ai n registres, qui n'ont aucun rapport les uns avec les autres.

    Ca me libère d'un problème (endian) sans me couter trop : après tout, qu'est-ce que 4 ou 20 registres si chacun fait maximum 64 bits ?

    Calculons tout de même :
    (4*64) = 256 bits ( => 32 octets )
    (4*64) + (4*32) + (4*16) + (8*8) = 512 bits ( => 64 octets )

    Ca devrait aller, non ?
    Je vais donc rester simple pour le moment.
    Mindiell
    "Souvent, femme barrit" - Elephant man

  15. #15
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    Utiliser des variables différentes pour le même registre, c'est du suicide, tu perdrais trop de temps à les synchroniser.

    La bonne chose à faire, c'est UNE variable PAR registre, et les conversions/décalages qui s'imposent. Regarde le code que j'ai posté. Bien qu'il soit long, chaque partie est toute simple.
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

  16. #16
    Membre confirmé
    Avatar de Mindiell
    Profil pro
    Inscrit en
    Juin 2006
    Messages
    735
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2006
    Messages : 735
    Points : 546
    Points
    546
    Par défaut
    Non,
    Je n'ai aucun besoin de "synchroniser" les différents registres, dans le sens où ceux-ci sont indépendants. Cette structure existe au sein des microprocesseurs afin de gagner de la place. Je voulais en faire un peu trop, mais entre tout ton code et les problèmes liés à l'endian, je préfèreme dire que si quelqu'un écrit dans un registre ce n'est pas pour écrire dans un autre

    Je vais donc avoir un certain nombre de registres (4 ou 20, tout dépendra de l'architecture souhaitée finalement) indépendants les uns des autres et ca sera plus simple pour tout le monde.

    En tout cas, merci de toute cette aide et de vos différentes solutions et approches : ca reste très instructif.
    Mindiell
    "Souvent, femme barrit" - Elephant man

  17. #17
    Expert éminent sénior
    Avatar de Médinoc
    Homme Profil pro
    Développeur informatique
    Inscrit en
    Septembre 2005
    Messages
    27 369
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France

    Informations professionnelles :
    Activité : Développeur informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2005
    Messages : 27 369
    Points : 41 519
    Points
    41 519
    Par défaut
    J'ai modifié mon message au-dessus: Je voulais dire une seule variable par registre.
    Bien entendu que tous les registres sont dans des variables différentes (ou plutôt, dans différents champs d'une classe ou structure).
    SVP, pas de questions techniques par MP. Surtout si je ne vous ai jamais parlé avant.

    "Aw, come on, who would be so stupid as to insert a cast to make an error go away without actually fixing the error?"
    Apparently everyone.
    -- Raymond Chen.
    Traduction obligatoire: "Oh, voyons, qui serait assez stupide pour mettre un cast pour faire disparaitre un message d'erreur sans vraiment corriger l'erreur?" - Apparemment, tout le monde. -- Raymond Chen.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Besoin d'aide pour un exercice sur les registres
    Par zakuza dans le forum Assembleur
    Réponses: 5
    Dernier message: 14/04/2006, 14h23
  2. Réponses: 1
    Dernier message: 29/11/2005, 10h10
  3. Lire/écrire les registres
    Par Age Piranha dans le forum Windows
    Réponses: 11
    Dernier message: 11/03/2005, 18h31
  4. Exception systeme W32 et registre FS du processeur
    Par heinquoi dans le forum x86 32-bits / 64-bits
    Réponses: 5
    Dernier message: 10/10/2004, 13h58
  5. TASM ne connaît pas les registres FS et GS
    Par forthx dans le forum Assembleur
    Réponses: 4
    Dernier message: 07/06/2003, 00h56

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo