2011-05-08 21 views
12

Yo quería reemplazar bit/bits (más de 1) en un campo de datos de 32/64 bits sin afectar a otros bits.Say por ejemplo:Cómo sustituir bits en un campo de bits sin afectar a otros bits utilizando c

I tener un registro de 64 bits donde los bits 5 & 6 pueden tomar valores de 0,1,2,3.

5:6  
0 0 
0 1 
1 0 
1 1  

Ahora cuando leí el registro me sale decir el valor 0x146 (0001 0 10 0 0110) .Ahora quiero cambiar el valor de la posición de bit 5 y 6 a 01. (ahora es 10, que es 2 en decimal y quiero reemplazarlo a 1 e 01) y sin otros bits obtener afectados y escribir de nuevo el registro con sólo los bits 5 & 6 modificado. (por lo que se convierten en 126 después de cambiar)

he intentado hacer esto

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

Si hago este valor en las posiciones de bit 5 & 6 se convertirá en 11 (0x3) no 01 (0x1) que yo quería.

  • ¿Cómo hago para leer/modificar/escribir?
  • ¿Cómo reemplazo solo ciertos bits/bits en un campo de 32/64 bits sin afectar los datos completos del campo usando C?

Establecer un poco está bien, pero más de un bit, me resulta un poco difícil.

Cualquier sugerencia es muy apreciada.

Respuesta

19

¿Por qué no usar una máscara de bits? Algo así como:

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) 

Esto conserva los bits y OR anteriores en los nuevos.

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

La primera línea borra los dos bits en (shift1, shift2) y la segunda línea los establece.

+3

+1. Además, si sabes que son adyacentes, se vuelve más simple: por ejemplo, en este caso, 'reg_data = reg_data & (~ (3 << 5)) | (1 << 5) ' – Amadan

0

Tendrás que hacer eso de a poco. Utilice el o que estás haciendo actualmente para establecer un bit de uno, y usar lo siguiente para establecer algo a 0:

reg_data &= ~ (1 << shift) 
5

Aquí es un proceso genérico que actúa sobre una larga serie considerándolo un largo campo de bits y se dirige a cada posición de bit individual

#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) 

simplemente toma el índice utiliza el inferior 3 IAV del índice para identificar 8 bits diferente posiciones dentro de cada ubicación de la matriz char, y las direcciones de bits restantes superiores en qué ubicación de matriz aparece el bit denotado por x. Espero que esto ayude.

Edit1: para establecer un bit que necesitas o la palabra de destino con otra palabra con 1 en esa posición de bit específico y 0 en todos los demás con el objetivo. Todos los 0 en las otras posiciones aseguran que los 1 existentes en el objetivo estén como están durante O, y el 1 en las posiciones específicas asegura que el objetivo obtenga el 1 en esa posición.si tenemos máscara = 0x02 = 00000010 (1 byte) entonces podemos O esto a cualquier palabra para establecer que las OP bits

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 

Para borrar un poco lo que necesita y la palabra objetivo con otra palabra con 0 en ese posición de bit específica y 1 en total. Todos los 1 en todas las otras posiciones de bit aseguran que durante AND el objetivo conserve sus 0 y 1 como estaban en esas ubicaciones, y un 0 en la posición de bit a borrar también establecería esa posición de bit 0 en la palabra objetivo. si tenemos la misma máscara = 0x02, entonces podemos preparar esta mascarilla para limpiar por ~ máscara

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. aplicar una mascarilla contra el campo de bits para mantener los bits que no desee cnange. Esto también eliminará los bits que va a cambiar.

  2. Asegúrese de tener un campo de bits que contenga solo los bits que desea establecer/borrar.

  3. Utilice el operador o en "o" los dos campos de bits, o simplemente agréguelos.

Por ejemplo, si desea cambiar sólo 2 bits a través de 5 basadas en la entrada del 0 al 15.

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

La pregunta era acerca de cómo implementar en C, pero como al busca "replace bits" conducen a aquí. Proporcionaré mi implementación en VB.Net. Ha sido probado en pruebas unitarias. Para aquellos que se preguntan lo que la extensión ToBinaryString parece: 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 
Cuestiones relacionadas