Las operaciones bit a bit son absolutamente esenciales cuando se programan registros de hardware en sistemas embebidos. Por ejemplo, cada procesador que he usado tiene uno o más registros (generalmente una dirección de memoria específica) que controlan si una interrupción está habilitada o deshabilitada. Para permitir que se active una interrupción, el proceso habitual es establecer el bit de habilitación para ese tipo de interrupción y, lo más importante, no modificar ninguno de los otros bits en el registro.
Cuando se dispara una interrupción, generalmente establece un bit en un registro de estado para que una única rutina de servicio pueda determinar la razón precisa de la interrupción. Probar los bits individuales permite una rápida decodificación de la fuente de interrupción.
En muchos sistemas embebidos, la RAM total disponible puede ser de 64, 128 o 256 BYTES (es decir, Bytes, no kilobytes o megabytes). En este entorno, es común usar un byte para almacenar múltiples elementos de datos, banderas booleanas, etc. y luego usar operaciones de bits para configurar y leer estos.
Durante varios años he estado trabajando con un sistema de comunicaciones satelitales donde la carga útil del mensaje es de 10.5 bytes. Para aprovechar al máximo este paquete de datos, la información se debe empaquetar en el bloque de datos sin dejar ningún bit no utilizado entre los campos. Esto significa hacer un uso extensivo de los operadores bit a bit y shift para tomar los valores de información y empaquetarlos en la carga útil que se transmite.
Básicamente, los usa debido a consideraciones de tamaño y velocidad. Las operaciones bit a bit son increíblemente simples y, por lo tanto, generalmente más rápidas que las operaciones aritméticas. Por ejemplo, para obtener la porción verde de un valor rgb, el enfoque aritmético es
(rgb / 256) % 256
. Con operaciones bit a bit harías algo como(rgb >> 8) & 0xFF
. Este último es significativamente más rápido y una vez que te acostumbras, también es más fácil. Generalmente, las operaciones bit a bit entran en juego mucho cuando necesita codificar / decodificar datos de forma compacta y rápida.fuente
BYTE g1 = (rgb / 256) % 256;
00E51013...C1 E9 08...shr ecx,8
00E51016...88 0C 24...mov byte ptr [esp],cl
Este tipo de operaciones a menudo se usan al escribir para sistemas integrados donde la memoria o la potencia de la CPU están restringidas.
Por ejemplo, para ahorrar espacio, puede almacenar múltiples variables en una única variable int de 8 bits utilizando cada bit para representar un valor booleano. Entonces necesita una forma rápida de establecer un bit específico o recuperar el valor del bit.
En general, cuando se programa en lenguajes de nivel superior como C # en una PC de escritorio con Gigabytes de memoria, realmente no le importa que cada uno
bool
ocupe un byte completo . Pero si está programando un microcontrolador en C con 2kb de memoria, cada bit cuenta, por lo que la capacidad de empaquetar 8 bools en un solo byte puede ser crítica.fuente
[Flags]
atributo que permite usar unEnum
campo como bit. Por ejemplo,Font
tiene unStyle
propiedad que es un campo de bits que contiene negrita, cursiva, subrayado y tachado.Las operaciones bit a bit también se usan con frecuencia en códecs de video y audio, por la misma razón que en la electrónica integrada; ser capaz de empacar cinco banderas y un temporizador de once bits en medio int es muy útil cuando quieres hacer un códec de video súper eficiente.
De hecho, MPEG 4 incluso utiliza la codificación exponencial de Golomb para campos de longitud de bits variable. Un valor que tenía 17 o 19 bits de ancho en el último paquete podría tener solo tres o cinco bits de ancho en este paquete, y usted descubriría todo eso con operaciones bit a bit.
fuente
Las personas que han estudiado la construcción de un sumador binario utilizando compuertas lógicas (y, o no) pueden entender los trucos que combinan operaciones lógicas bit a bit, operaciones de desplazamiento bit a bit y operaciones aritméticas. Fuera de ese círculo, es muy difícil de entender sin un comentario detallado.
Es útil al programar unidades SIMD , especialmente si la arquitectura de la CPU omitió intencionalmente algunas instrucciones SIMD porque podrían ser emuladas por algunas otras.
Por ejemplo, la arquitectura puede no definir ninguna instrucción para tomar los valores negativos de un grupo de 16 bytes, pero eso se puede emular negando bit a bit y luego agregando 1. Del mismo modo, también se puede omitir la resta, porque se puede emular tomando lo negativo del segundo operando. La disponibilidad de la "ruta alternativa" es la razón para omitir ciertas instrucciones.
Del mismo modo, el SIMD solo puede admitir la adición paralela de 8 bits, sin implementar la adición para elementos más amplios como 16 bits, 32 bits o 64 bits. Para emularlos, es necesario extraer el bit de signo del resultado del cálculo de 8 bits y luego realizar la operación de acarreo en el siguiente elemento.
fuente
Datos de empaque, operaciones más rápidas (la multiplicación, la división y el módulo son significativamente más rápidos si están alineados con potencias de 2), cambio de bits, etc. Aprenda y comience a usarlos y lentamente comenzará a ver la mayoría de las ventajas por su cuenta.
fuente