Articulo de referencia

Campo de bits

Un campo de bits es una estructura de datos que se asigna a uno o más bits adyacentes que se han asignado para propósitos específicos, de modo que cualquier bit individual o gru...

Un campo de bits es una estructura de datos que se asigna a uno o más bits adyacentes que se han asignado para propósitos específicos, de modo que cualquier bit individual o grupo de bits dentro de la estructura se puede establecer o inspeccionar. [ 1 ] [ 2 ] Un campo de bits se usa más comúnmente para representar tipos enteros de ancho de bits fijo y conocido, como booleanos de un solo bit .

El significado de los bits individuales dentro del campo lo determina el programador; por ejemplo, el primer bit en un campo de bits (ubicado en la dirección base del campo ) a veces se utiliza para determinar el estado de un atributo particular asociado con el campo de bits. [ 3 ]

En las CPU y otros dispositivos lógicos, se suelen usar conjuntos de campos de bits llamados indicadores para controlar o indicar el resultado de operaciones específicas. [ 4 ] Los procesadores tienen un registro de estado compuesto por indicadores. Por ejemplo, si el resultado de una suma no se puede representar en el destino, se activa un desbordamiento aritmético . Los indicadores se pueden usar para decidir operaciones posteriores, como las instrucciones de salto condicional . Por ejemplo, una instrucción (Saltar si es igual) en el lenguaje ensamblador x86 dará como resultado un salto si el indicador Z (cero) se activó mediante alguna operación anterior.JE...

Un campo de bits se distingue de una matriz de bits en que esta última se utiliza para almacenar un conjunto grande de bits indexados por enteros y suele ser más ancha que cualquier tipo entero compatible con el lenguaje. Los campos de bits, por otro lado, normalmente caben dentro de una palabra de máquina [ 3 ] y la denotación de los bits es independiente de su índice numérico [ 2 ] .

Implementación

Los campos de bits pueden utilizarse para reducir el consumo de memoria cuando un programa requiere varias variables enteras que siempre tendrán valores bajos. Por ejemplo, en muchos sistemas, almacenar un valor entero requiere dos bytes (16 bits) de memoria; a veces, los valores que se van a almacenar solo necesitan uno o dos bits. El hecho de que varias de estas pequeñas variables compartan un campo de bits permite una organización eficiente de los datos en la memoria. [ 5 ]

En C, los campos de bits definidos por la implementación nativa se pueden crear usando int, [ a ]unsigned int ​​, signed int, _Bool(en C99 ), _BitInt(N), unsigned _BitInt(N)(en C23 ) u otros tipos definidos por la implementación. En C++, se pueden crear usando cualquier tipo entero o de enumeración; la mayoría de los compiladores de C también lo permiten. En este caso, el programador puede declarar una estructura para un campo de bits que etiqueta y determina el ancho de varios subcampos. [ 6 ] Los campos de bits declarados adyacentemente del mismo tipo pueden ser empaquetados por el compilador en un número reducido de palabras, en comparación con la memoria utilizada si cada 'campo' se declarara por separado.

Para lenguajes que carecen de campos de bits nativos, o cuando el programador desea controlar la representación de bits resultante, es posible manipular manualmente los bits dentro de un tipo de palabra más grande. En este caso, el programador puede establecer, probar y cambiar los bits en el campo utilizando combinaciones de enmascaramiento y operaciones bit a bit . [ 7 ]

Ejemplos

do

Los campos de bits se pueden usar dentro de estructuras en C y C++ . [ 6 ]

#include <stdint.h>// opaco y mostrar enumeración Visibilidad : uint8_t { NO = 0 , = 1 };// estilos de línea enum LineStyle : uint8_t { SOLID = 1 , DOTTED = 2 , DASHED = 3 };// Colores enum Color : uint8_t { NEGRO = 0 , ROJO = 0b001 , VERDE = 0b010 , AZUL = 0b100 , AMARILLO = ROJO | VERDE , // 011 MAGENTA = ROJO | AZUL , // 101 CIAN = VERDE | AZUL , // 110 BLANCO = ROJO | VERDE | AZUL // 111 };const char * colors [ 8 ] = { "Negro" , "Rojo" , "Verde" , "Amarillo" , "Azul" , "Magenta" , "Cian" , "Blanco" };// Propiedades de la caja de campo de bits struct BoxProps { uint32_t opaco : 1 ; uint32_t color_relleno : 3 ; [[ maybe_unused ]] uint32_t relleno_a : 4 ; // rellenar a 8 bitsuint32_t mostrar_borde : 1 ; uint32_t color_borde : 3 ; uint32_t estilo_borde : 2 ;[[ maybe_unused ]] uint8_t filler_b : 0 ; // rellenar al byte más cercano (16 bits)uint8_t ancho : 4 ; // Divide un byte en 2 campos de 4 bits uint8_t alto : 4 ; };int main () { BoxProps my_box = { . opaco = , . color_relleno = ROJO , . mostrar_borde = , . color_borde = AZUL , . estilo_borde = SÓLIDO , . ancho = 5 , . alto = 10 }; }

La disposición de los campos de bits en C structdepende de la implementación . Para un comportamiento predecible entre compiladores, puede ser preferible emular los campos de bits con operadores primitivos y de bits:

#include <stdint.h>/** * Cada una de estas directivas de preprocesador define un solo bit, * correspondiente a un botón del controlador. * El orden de los botones coincide con el de Nintendo Entertainment System. */ enum Key : uint8_t { KEY_RIGHT = 0b00000001 , KEY_LEFT = 0b00000010 , KEY_DOWN = 0b00000100 , KEY_UP = 0b00001000 , KEY_START = 0b00010000 , KEY_SELECT = 0b00100000 , KEY_B = 0b01000000 , KEY_A = 0b10000000 };// estado global uint8_t gameControllerStatus = 0 ;// Establece el estado del controlador de juego usando OR void onKeyPressed ( uint8_t key ) { gameControllerStatus |= key ; }// Borra el gameControllerStatus usando AND y ~ (NOT binario) void onKeyReleased ( uint8_t key ) { gameControllerStatus &= ~ key ; }// Comprueba si un bit está activado usando AND uint8_t isPressed ( uint8_t key ) { return gameControllerStatus & key ; }

Óxido

Si bien Rust carece de campos de bits nativos al estilo de C, esto se logra mediante el uso de máscaras.

impl BoxProps { // Byte 0 const OPAQUE : u8 = 0b0000_0001 ; const FILL_COLOR_MASK : u8 = 0b0000_1110 ;// Byte 1 const SHOW_BORDER : u8 = 0b0000_0001 ; const BORDER_COLOR_MASK : u8 = 0b0000_1110 ; const BORDER_STYLE_MASK : u8 = 0b0011_0000 ;// Byte 2 const ANCHO_MÁSCARA : u8 = 0b0000_1111 ; const ALTO_MÁSCARA : u8 = 0b1111_0000 ; }impl BoxProps { fn opaque ( & self ) -> bool { self . raw [ 0 ] & Self :: OPAQUE != 0 }fn set_opaque ( & mut self , v : bool ) { self . raw [ 0 ] = ( self . raw [ 0 ] & ! Self :: OPAQUE ) | ( v as u8 ); }fn fill_color ( & self ) -> u8 { ( self . raw [ 0 ] & Self :: FILL_COLOR_MASK ) >> 1 }fn set_fill_color ( & mut self , v : u8 ) { self . raw [ 0 ] = ( self . raw [ 0 ] & ! Self :: FILL_COLOR_MASK ) | (( v & 0b111 ) << 1 ); }fn width ( & self ) -> u8 { self . raw [ 2 ] & Self :: WIDTH_MASK }fn altura ( & self ) -> u8 { ( self . raw [ 2 ] & Self :: HEIGHT_MASK ) >> 4 } }

Registro de estado del procesador

El registro de estado de un procesador es un campo de bits compuesto por varios bits de bandera. Cada bit de bandera describe información sobre el estado actual del procesador. [ 8 ] A modo de ejemplo, el registro de estado del procesador 6502 se muestra a continuación:

Estos bits son configurados por el procesador tras el resultado de una operación. Ciertos bits (como los indicadores de acarreo, deshabilitación de interrupciones y decimal) pueden controlarse explícitamente mediante instrucciones de configuración y borrado. Además, se definen instrucciones de bifurcación para modificar la ejecución en función del estado actual de un indicador.

Por ejemplo, después de una ADCinstrucción (Suma con acarreo), BVSse puede usar la instrucción (Salto por desbordamiento establecido) para saltar en función de si el procesador estableció el indicador de desbordamiento después del resultado de la instrucción de suma.

Extracción de bits de palabras de banderas

Se puede extraer un subconjunto de indicadores en un campo de indicadores mediante la operación AND con una máscara . Un gran número de lenguajes admiten el operador de desplazamiento ( << ), que alinea1 << n un solo bit a la enésima posición. La mayoría también admite el uso del operador AND (&) para aislar el valor de uno o más bits.

Si el byte de estado de un dispositivo es 0x67 y el quinto bit de la bandera indica que hay datos disponibles, el byte de máscara es 2^5 = 0x20. Al aplicar la operación AND al byte de estado 0x67 ( en binario) con el byte de máscara 0x20 ( en binario), el resultado es 0x20. Esto significa que el bit de la bandera está activado, es decir, el dispositivo tiene datos disponibles. Si el bit de la bandera no estuviera activado, el resultado sería 0, es decir, no hay datos disponibles del dispositivo.0110 01110010 0000

Para comprobar el n -ésimo bit de una variable v , realice cualquiera de las siguientes acciones: (ambas son equivalentes)

bool nth_is_set = ( v & ( 1 << n )) != 0 ; bool nth_is_set = ( v >> n ) & 1 ;

Cambiar bits en palabras de banderas

La escritura, lectura o conmutación de bits en indicadores solo se puede realizar mediante las operaciones OR, AND y NOT, operaciones que el procesador puede ejecutar rápidamente. Para establecer un bit, se aplica la operación OR al byte de estado con un byte de máscara. Cualquier bit establecido en el byte de máscara o en el byte de estado se establecerá en el resultado.

Para alternar un bit, aplique la operación XOR al byte de estado y al byte de máscara. Esto activará un bit si está desactivado o lo desactivará si está activado.

Véase también

Notas

  1. En C, el tipo de dato (con o sin signo) de un campo de bits de tipo int depende de la implementación. En C++, siempre es con signo para coincidir con el tipo subyacente.

Referencias

  1. Penn Brumm; Don Brumm (agosto de 1988). 80386 Assembly Language: A Complete Tutorial and Subroutine Library . McGraw-Hill School Education Group. pág.  606. ISBN 978-0-8306-9047-3.
  2. 1 2 Steve Oualline (1997). Programación práctica en C. O'Reilly Media, Inc. págs. 403 –. ISBN  978-1-56592-306-5.
  3. 1 2 Michael A. Miller (enero de 1992). La familia de microprocesadores 68000: arquitectura, programación y aplicaciones . Merrill. pág. 323. ISBN  978-0-02-381560-7.
  4. Ian Griffiths; Matthew Adams; Jesse Liberty (30 de julio de 2010). Programación en C# 4.0: Creación de aplicaciones para Windows, web y RIA para el marco .NET 4.0 . O'Reilly Media, Inc. págs. 81–. ISBN  978-1-4493-9972-6.
  5. Tibet Mimar (1991). Programación y diseño con la familia 68000: Incluye 68000, 68010/12, 68020 y 68030. Prentice Hall. pág. 275. ISBN  978-0-13-731498-0.
  6. ^ Prata , Stephen (2007). C primer plus (5ª ed.). Indianápolis, Indiana: Sams. ISBN  978-0-672-32696-7.
  7. ^ Mark E. Daggett (13 de noviembre de 2013). JavaScript experto . Presione. págs.68– . ISBN  978-1-4302-6097-4.
  8. EnCider . W. Green. Enero de 1986. pág. 108. 
  • Explicación de un libro
  • Descripción de otra wiki
  • Caso de uso en una guía de C++
  • Biblioteca de bits libbit de C++ ( URL alternativa )
  • Trucos para manipular bits : varios fragmentos de código C que manipulan campos de bits.