2 votes

Comment puis-je faire ces opérations asm ROR et BT/RCR en C ? Rotation ou décalage d'un bit d'un autre nombre

Je suis en train de convertir du code assembleur en C pour pouvoir l'utiliser avec l'environnement de compilation actuel avec lequel je dois travailler.

J'en suis à 2 opérations que je ne sais pas comment traduire en C. Quelqu'un sait-il comment faire ?

Dans les deux, offset est un entier non signé de 32 bits et shift est une valeur entière signée. C_FLAG est un bool.

OP1 :

__asm {
    __asm mov ecx, shift
    __asm ror offset, cl
}

OP2 :

__asm {
    __asm bt dword ptr C_FLAG, 0
    __asm rcr offset, 1
}

Merci beaucoup pour votre expertise.

P.S. : Je ne suis pas le développeur original, et je n'ai pas vu beaucoup de code assembleur x86...

2voto

Anycorn Points 20521

Discussion sur le droit de rotation : http://www.osix.net/modules/article/?id=320 (web.archive)

des descriptions illustrées : http://www.penguin.cz/~literakl/intel/r.html

J'espère que cela vous aidera

0voto

Thomas Matthews Points 19838

Pour le décalage des bits, comme dans votre premier exemple, utilisez la fonction << opérateur. Dans le langage C, il n'y a pas de enveloppant pour les équipes, souvent qualifiées de tourne . Vous devrez mettre en œuvre l'opération vous-même :

unsigned char carry;
carry = byte & 0x80; // Save the Most Significant bit for 8-bit byte.
byte <<= 1;  // Left shift by one, insert a 0 as the least significant bit.
byte |= carry;  // Put the rotated bit back into the byte.

Certains processeurs disposent également d'un rotation à travers le portage qui fera tourner la valeur de report dans le décalage suivant. Cela suppose que le carry être une variable globale.

Pour tester les bits en langage C, vous utiliserez la fonction & (opérateur ET binaire) et peut-être le ~ opérateur (négation). Pour tester le bit le plus significatif dans un octet de 8 bits :

   if (byte & 0x80)
   {
      // bit is a 1
   }
   else
   {
      // bit is a 0
   }

Avec tout cela dit, vous devrez découvrir pourquoi le transporter drapeau ( C_FLAG ) est utilisé et concevoir un système différent autour de lui. En général, le bit de report est invalide en dehors de la fonction du langage d'assemblage dans laquelle il est utilisé. Certaines fonctions en langage d'assemblage étroitement couplées peuvent violer cette règle. Dans ce cas, réécrivez le langage d'assemblage plutôt que de le déboguer. Redessinez tout le programme !

0voto

aspo Points 106

Pour la deuxième opération

__asm bt dword ptr C_FLAG, 0

met le drapeau du bit de retenue à C_FLAG (donc 1 ou 0)

__asm rcr offset, 1

est Rotate Carry Left qui est une rotation de 33 bits utilisant le drapeau de report comme 33ème bit. (et les résultats mettent le 33ème bit dans le drapeau de retenue. Ce qui (je pense) est la même chose que

offset =  offset << 1 + C_FLAG ? 1:0

(sauf si vous vous souciez du drapeau de report plus tard)

EDIT - pour une raison quelconque, j'ai lu rcr comme rcl. Donc plutôt comme

offset = offset >> 1 | (C_FLAG ? 1<<31 : 0)

0voto

Xandy Points 881

Bien que ce soit plus ou moins couvert, je le ferais de cette façon :

OP 1 : Il s'agit d'une opération de rotation vers la droite. offset , shift des lieux. En C, ça pourrait être quelque chose comme ça :

offset = (offset >> shift) | (offset << (WORD_LENGTH - shift);

Vous pouvez obtenir la longueur des mots avec sizeof(void *) * 8 par exemple.


OP 2 : Je pense que cet OP met en œuvre la méthode de la RRX en assemblage x86. C'est un autre type d'opération de rotation à droite où le drapeau de report est utilisé pour fournir une quantité de 33 bits à décaler. En C, cela pourrait être quelque chose comme ceci :

offset = (C_FLAG << 31) | (offset >> 1);

C_FLAG est le drapeau de report, vous devez trouver plus d'informations sur ce que cela signifie. bool est réellement utilisée dans le code que vous avez.

0voto

caf Points 114951

En supposant que les drapeaux ne sont pas utilisés pour maintenir un état persistant (ce qui est une supposition raisonnable), OP1 est équivalent à :

/* Precondition: `*offset` is in range 0..0xFFFFFFFF */
void inline op1(unsigned long *offset, int shift)
{
    shift = ((unsigned)shift) % 32;

    if (shift)
        *offset = ((*offset >> shift) | (*offset << (32 - shift))) & 0xFFFFFFFFUL;
}

et OP2 est équivalent à :

/* Precondition: `*offset` is in range 0..0xFFFFFFFF */
void inline op2(unsigned long *offset, unsigned long C_FLAG)
{
    *offset = (*offset >> 1) | ((C_FLAG & 1) << 31);
}

(Sur les systèmes avec 32 bits long la condition préalable est automatiquement satisfaite).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X