7
votes

Pourquoi `opcode.value` a-t-il la" fausse "endianness?

faits:

  1. le codage correct pour l'instruction CIL rethrow est la séquence de deux octets Fe 1a .

  2. opcodes.rethrow.value (qui a type court ) a la valeur 0xfe1a sur ma machine petite-Endian.

  3. bitconverter honore l'endansement de la machine lors de la conversion / de séquences d'octets.

  4. sur ma machine à petite Endian, bitconverter.getbytes (opcodes.rethrow.value) Résultats dans la séquence d'octets 1a Fe . < / li>

    Cela signifie, sérialisation d'un opcode.value sur une machine à petite Endian utilisant bitconverter ne produit pas le codage correct pour le code OP; L'ordre des octets est inversé.

    questions:

    • est le commandement d'octets de opcode.value documenté (et si oui, où?) Ou est-ce un "détail de mise en œuvre"?

    • L'étape 4 ci-dessus sur une machine Big-Endian entraîne également le mauvais ordre d'octets? C'est-à-dire que opcodes.rethrow.value soit 0x1afe sur une machine Big-Endian?


3 commentaires

Vous ne pouvez pas combiner l'opcode comme ça. Le lecteur de métadonnées nibrera le contenu et lors de la recherche Fe saura qu'il s'agit d'une version longue. Si cela représentait l'inverse, alors vous auriez du mal à le lire.


@Leppie: Je sais que Fe doit apparaître d'abord dans le flux d'octets d'instructions. Ma question concerne l'ordre d'octet des codages de code OP tel que stocké dans opcode.value .


Probablement pour une lecture plus facile :)


3 Réponses :


3
votes

La propriété de valeur ressemble à ceci dans la source de référence:

foo.m_s1 = opc.Value >> 8;
foo.m_s2 = opc.Value & 0xff;
foo.m_size = opc.Size;


5 commentaires

"Ça ne fait pas quel internalemit () fait" : es-tu alors que l'ordre des octets dans opcode.value est un détail de mise en œuvre (interne)? Ou est-ce que le source de référence .NET a réellement le caractère d'une spécification publique?


La propriété opcode.Value n'est pas un détail de mise en œuvre interne. C'est juste une propriété publique qui vous peut utiliser, la mise en œuvre ne l'utilise pas.


Veuillez relire ma question: je ne demande pas à propos de opcode.value lui-même, mais sur son ordre d'octet .


"qui n'a pas de dépendance de l'endian-ness ": vous vous prouvez comme vous traitant du code qui effectue des opérations de bits. Vous en basez sur votre connaissance de la source de référence, que l'OMHO ne peut remplacer une spécification ou une documentation publique. Même si: avec des déclarations telles que "le faire comme le cadre fait" , vous avez réellement aidé à dessiner mes propres conclusions, à savoir que nous parlons de quelque chose qui est en fait non documenté.


Note latérale: Il y a une inexactitude mineure dans votre réponse: Contrairement au code OP, il est Autres données dans un ruisseau d'octets d'instructions CIL qui a une certaine endansion (toujours petite-Endian Afaik): par exemple. jetons de métadonnées intégrées ou décalages relatifs indiquant des cibles de succursales.



1
votes

J'ai atteint la conclusion qui sérialisant une représentation de code OP basée sur la propriété opcode.value , c'est-à-dire: xxx

est une mauvaise idée, mais Non pas à cause de l'utilisation de bitconverter.getbytes (court) , dont le comportement est bien documenté. Le principal culprit est le opcode.value Propriété, dont la documentation est vague à deux égards:

  1. Il indique que cette propriété contient "la valeur de l'opérande immédiate", qui peut ou non se référer au codage du code OP; Ce terme n'apparaît nulle part dans la spécification CLI.

  2. Même lorsque nous supposons que ce est en fait contient le codage d'un code OP, la documentation ne dit rien à propos de l'ordre d'octet. (L'ordre d'octet est entré en jeu lors de la conversion entre octet [] et court .)

    Pourquoi suis-je en train de baser mon argument sur la documentation MSDN et non sur la norme CLI? Parce que system.reflet.emit ne fait pas partie de la bibliothèque de réflexion telle que définie par la norme CLI. Pour cette raison, je pense qu'il est assez sûr de dire que La documentation de référence MSDN pour cet espace de noms est aussi proche que possible dans une spécification officielle. (Mais contrairement à la réponse de @hans Passant, je ne prendrais pas une étape plus loin et affirmant que la source de référence est de quelque manière qu'une spécification.)

    conclusion: < P> Il existe deux façons de sortir le codage de code OP pour un OPCODE OPCODE

    • séjour avec system.reflet.emit fonctionnalité et utilisez iLGenerator.emit (quelqueopcode) . Cela peut être trop restrictif dans certaines situations.

    • Créez votre propre mappage entre les codages de code OP (I.E. octet [] séquences) et les différents opcode objets.


1 commentaires

Alternative: N'utilisez pas d'objets opcode si vous n'utilisez pas de réflexion? Si vous aimez simplement utiliser opcodes.Rethrow.value pour la lisibilité, vous pouvez obtenir la même chose en utilisant Mono Cecil's OPCODES classe; Son OPCODE STRIT a explicitement op1 et op2 propriétés.