2011-05-08 2 views
12

Je voulais remplacer bit/bits (plus de 1) dans un champ de données 32/64 bits sans affecter les autres bits.Say par exemple:Comment remplacer bits dans un champ de bits sans affecter les autres bits en utilisant c

I avoir un registre de 64 bits où les bits 5 & 6 peuvent prendre des valeurs 0,1,2,3.

5:6  
0 0 
0 1 
1 0 
1 1  

Maintenant, quand je lis le registre que je reçois dire la valeur 0x146 (0001 0 10 0 0110) .Maintenant je veux changer la valeur à la position de bit 5 et 6 à 01. (en ce moment, il est 10 qui est 2 en décimal et je veux le remplacer au 1 e 01) sans autres bits se touchés et écrire de nouveau le registre avec des bits seulement 5 & 6 modifié. (il devient 126 après avoir changé)

J'ai essayé de le faire

reg_data=0x146 
reg_data |= 1 << shift (shift in this case is 5) 

Si je fais cette valeur aux positions de bit 5 & 6 deviendra 11 (0x3) pas 01 (0x1) ce que je voulais.

  • Comment faire pour lire/modifier/écrire?
  • Comment est-ce que je remplace seulement certains bits/bits dans des champs de 32/64 bits sans affecter les données entières du champ utilisant C?

Réglage d'un bit est correct, mais plus d'un bit, je trouve cela peu difficile.

Toutes les suggestions sont très appréciées.

Répondre

19

Pourquoi ne pas utiliser un masque? Un peu comme:

new_value = 0, 1, 2 or 3 // (this is the value you will set in) 
bit_mask = (3<<5)   // (mask of the bits you want to set) 
reg_data = (reg_data & (~bit_mask)) | (new_value<<5) 

Ceci préserve les anciens bits et les anciens dans les nouveaux.

8
reg_data &= ~((1 << shift1) | (1 << shift2)); 
reg_data |= ((1 << shift1) | (1 << shift2)); 

La première ligne efface les deux bits en (shift1, shift2) et la deuxième ligne les définit.

+3

+1. De plus, si vous savez qu'ils sont adjacents, cela devient plus simple: par exemple, dans ce cas, 'reg_data = reg_data & (~ (3 << 5)) | (1 << 5) ' – Amadan

0

Vous aurez besoin de faire cela un bit à la fois. Utilisez le bouton ou que vous êtes en train de faire pour mettre un peu à l'un, et utilisez les touches suivantes pour définir quelque chose à 0:

reg_data &= ~ (1 << shift) 
5

est ici un processus générique qui agit sur une longue série considérant une longue bitfield et traite chaque position de bit individuellement

#define set_bit(arr,x) ((arr[(x)>>3]) |= (0x01 << ((x) & 0x07))) 
#define clear_bit(arr,x) (arr[(x)>>3] &= ~(0x01 << ((x) & 0x07))) 
#define get_bit(arr,x) (((arr[(x)>>3]) & (0x01 << ((x) & 0x07))) != 0) 

prend simplement l'indice utilise la partie inférieure 3 BTI de l'indice pour identifier 8 bit différent les positions à l'intérieur de chaque emplacement du tableau char, et les adresses binaires restantes supérieures dans quel emplacement de tableau se produit le bit désigné par x. J'espère que cela t'aides.

Edit1: Pour définir un peu, vous devez ou le mot cible avec un autre mot avec 1 dans cette position binaire spécifique et 0 dans tous les autres avec la cible. Tous les 0 dans les autres positions s'assurent que les 1 existants dans la cible sont comme pendant OR, et le 1 dans les positions spécifiques s'assure que la cible obtient le 1 dans cette position.si nous avons masque 0x02 = 00000010 (1 octet), alors nous pouvons ou que cela ne importe quel mot pour définir ce bit pos

target = 1 0 1 1 0 1 0 0 
OR  + + + + + + + + 
mask  0 0 0 0 0 0 1 0 
     --------------- 
answer 1 0 1 1 0 1 1 0 

Pour effacer un peu que vous devez et le mot cible avec un autre mot avec 0 dans ce position de bit spécifique et 1 en tout. Tous les 1 dans toutes les autres positions de bits assurent que pendant ET la cible conserve ses 0 et 1 comme ils étaient dans ces emplacements, et un 0 dans la position de bit à effacer établirait également cette position de bit 0 dans le mot cible. si nous avons le même masque = 0x02, alors nous pouvons préparer ce masque pour la compensation par ~ masque

mask = 0 0 0 0 0 0 1 0 
~mask = 1 1 1 1 1 1 0 1 
AND  . . . . . . . . 
target 1 0 1 1 0 1 1 0 
     --------------- 
answer 1 0 1 1 0 1 0 0 
1
  1. Appliquer un masque contre la bitfield pour maintenir les bits que vous ne voulez pas cnange. Cela effacera également les bits que vous allez changer.

  2. Vérifiez que vous disposez d'un champ de bits contenant uniquement les bits que vous souhaitez définir/effacer. Utilisez l'opérateur or pour "ou" les deux champs de bits, ou simplement ajoutez-les.

Par exemple, si vous vouliez changer seulement bits 2 à travers 5 sur la base de l'entrée de 0 à travers 15.

byte newVal = (byte)value & 0x0F; 
newVal = (byte)value << 2; 
oldVal = oldVal & 0xC3; 
oldVal = oldval + newVal; 
2

La question était sur la façon de mettre en œuvre en C, mais comme al cherche "remplacer les bits" conduit ici à fournir mon implémentation dans VB.Net. Il a été testé en unité de test. Pour ceux qui se demandent ce que l'extension ToBinaryString ressemble: Convert.ToString(value,2)

 ''' <summary> 
    ''' Replace the bits in the enumValue with the bits in the bits parameter, starting from the position that corresponds to 2 to the power of the position parameter. 
    ''' </summary> 
    ''' <param name="enumValue">The integer value to place the bits in.</param> 
    ''' <param name="bits">The bits to place. It must be smaller or equal to 2 to the power of the position parameter.</param> 
    '''<param name="length">The number of bits that the bits should replace.</param> 
    ''' <param name="position">The exponent of 2 where the bits must be placed.</param> 
    ''' <returns></returns> 
    ''' <remarks></remarks>' 
    <Extension> 
    Public Function PlaceBits(enumValue As Integer, bits As Integer, length As Integer, position As Integer) As Integer 
     If position > 31 Then 
      Throw New ArgumentOutOfRangeException(String.Format("The position {0} is out of range for a 32 bit integer.", 
                   position)) 
     End If 
     Dim positionToPlace = 2 << position 
     If bits > positionToPlace Then 
      Throw New ArgumentOutOfRangeException(String.Format("The bits {0} must be smaler than or equal to {1}.", 
                   bits, positionToPlace)) 
     End If 

     'Create a bitmask (a series of ones for the bits to retain and a series of zeroes for bits to discard).' 
     Dim mask As Integer = (1 << length) - 1 
     'Use for debugging.' 
     'Dim maskAsBinaryString = mask.ToBinaryString' 

     'Shift the mask to left to the desired position' 
     Dim leftShift = position - length + 1 
     mask <<= leftShift 
     'Use for debugging.' 
     'Dim shiftedMaskAsBinaryString = mask.ToBinaryString' 

     'Shift the bits to left to the desired position.' 
     Dim shiftedBits = bits << leftShift 
     'Use for debugging.' 
     'Dim shiftedBitsAsBinaryString = shiftedBits.ToBinaryString' 

     'First clear (And Not) the bits to replace, then set (Or) them.' 
     Dim result = (enumValue And Not mask) Or shiftedBits 
     'Use for debugging.' 
     'Dim resultAsBinaryString = result.ToBinaryString' 

     Return result 
    End Function 
Questions connexes