2009-11-29 16 views
5

En C, Tengo una palabra de 32 bits que representa una dirección (y la tengo guardada en un mensaje sin firmar, espero que esté bien). Ahora, por lo que sé, parte de una dirección contiene el número de página y la otra parte contiene el desplazamiento. Me preguntaba cómo podría extraer solo los bits que me dan el número de página. Ya he calculado que los primeros 22 bits más significativos son el número de página y los otros 10 bits son el desplazamiento de página. ¿Cómo puedo capturar solo los bits que son el número de página? Estoy pensando que puedo hacer esto con algunas operaciones de bit a bit, pero no estoy seguro de cómo.Extrayendo bits

+0

Buena pregunta - Necesito hacer esto para un desensamblador que estoy escribiendo también. – new123456

Respuesta

11

Utilice los operadores bitshift para extraer los bits que necesita.

pageNumber = x >> 10; 
offset = x & ((1 << 10) - 1); 

Para el número de página, el operador >> desplaza los bits abajo, por lo que pierden los bits menos signifcativas.

Para el desplazamiento, ((1 < < 10) - 1) crea una máscara de bits que consta de 10 unidades que se utiliza para seleccionar solo los 10 bits menos significativos e ignorar los bits más significativos.

+1

Puede ser una buena idea en un código como este para enmascarar los bits después de que los haya cambiado, en caso de que su hardware haga un desplazamiento aritmético (extensión de signo) a la derecha. pagenumber = (x >> 10) & ((1 << 22) - 1); –

2

Soy un gran admirador del método de "dos turnos" de extracción de campo. Funciona tanto firmado como sin firmar. Para extraer un campo de ancho w con el bit menos significativo lsb de word:

#define BITSIN(W) (8*sizeof(W)) 
return (word << (BITSIN(word) - (lsb+width))) >> (BITSIN(word) - width); 

En este caso, BITSIN(word) == 32 y lsb+width == 32, así que mientras la palabra en cuestión no está firmado, sólo puede cambiar de derecha 10 sin enmascarar.

Una advertencia: tenga en cuenta los cambios de 32 bits en los tipos de 32 bits! El estándar C permite al compilador hacer cualquier cosa, y lo que hacen los chips Intel comunes no es útil: x << y cambia x dejado por y % 32 bits (siempre que x tenga un tipo entero de 32 bits). Esto significa que si tratas de desplazar un entero de 32 bits hacia la izquierda o la derecha en 32 bits, el resultado es el mismo que si no se opera. Existe un problema similar con los cambios de 64 bits de los tipos de 64 bits.

+0

"lo que hacen los chips Intel comunes no es útil", ¿qué hacen? – AShelly

+0

@ASHelly: buena pregunta; Edité la respuesta. Quién sabe, podría conseguirme un voto popular :-) –