Operación de bits

Los desplazamientos de bits a veces se consideran operaciones de bits, porque tratan un valor como una serie de bits en lugar de como una cantidad numérica. En estas operaciones, los dígitos se mueven, o se desplazan, a la izquierda o a la derecha. Los registros en un procesador de computadora tienen un ancho fijo, por lo que algunos bits se «desplazarán» del registro en un extremo, mientras que el mismo número de bits se «desplazarán» desde el otro extremo; las diferencias entre los operadores de desplazamiento de bits residen en cómo determinan los valores de los bits desplazados.

Dirección de bitedit

Si el ancho del registro (frecuentemente 32 o incluso 64) es mayor que el número de bits (generalmente 8) de la unidad direccionable más pequeña (elemento atómico), frecuentemente llamada byte, las operaciones de desplazamiento inducen un esquema de direccionamiento en los bits.Sin tener en cuenta los efectos de límite en ambos extremos del registro, las operaciones de desplazamiento aritmético y lógico se comportan de la misma manera, y un desplazamiento de 8 posiciones de bits transporta el patrón de bits por posición de 1 byte de la siguiente manera:

  • Pedidos de Little-endian:
un desplazamiento a la izquierda por 8 posiciones aumenta el byte de dirección 1
  • Little-endian pedido:
un desplazamiento derecha por 8 posiciones disminuye la dirección del byte por 1
  • Big-endian pedido:
un desplazamiento a la izquierda por 8 posiciones disminuye la dirección del byte por 1
  • Big-endian pedido:
un desplazamiento a la derecha en 8 posiciones aumenta la dirección de bytes en 1

Desplazamiento aritméticoeditar

Artículo principal: Desplazamiento aritmético
Desplazamiento aritmético izquierdo

Desplazamiento aritmético a la derecha

En un desplazamiento aritmético, los bits que se desplazan fuera de cada extremo se descartan. En un desplazamiento aritmético izquierdo, los ceros se desplazan hacia la derecha; en un desplazamiento aritmético derecho, el bit de signo (el MSB en el complemento de dos) se desplaza hacia la izquierda, preservando así el signo del operando.

Este ejemplo utiliza un registro de 8 bits, interpretado como complemento de dos:

 00010111 (decimal +23) LEFT-SHIFT= 00101110 (decimal +46)
 10010111 (decimal −105) RIGHT-SHIFT= 11001011 (decimal −53)

En el primer caso, el dígito más a la izquierda se desplazó más allá del final del registro, y un nuevo 0 se desplazó a la posición más a la derecha. En el segundo caso, el 1 situado más a la derecha se desplazó hacia afuera (quizás hacia la bandera de carga), y un nuevo 1 se copió en la posición más a la izquierda, conservando el signo del número. Los turnos múltiples a veces se acortan a un solo turno por un cierto número de dígitos. Por ejemplo:

 00010111 (decimal +23) LEFT-SHIFT-BY-TWO= 01011100 (decimal +92)

Un desplazamiento aritmético izquierdo por n es equivalente a multiplicar por 2n (siempre que el valor no se desborde), mientras que un desplazamiento aritmético derecho por n del valor del complemento de dos es equivalente a dividir por 2n y redondear hacia el infinito negativo. Si el número binario se trata como complemento de uno, la misma operación de desplazamiento a la derecha da como resultado la división por 2n y el redondeo hacia cero.

Desplazamiento lógico (Logical shiftEdit)

Artículo principal: Cambio lógico
desplazamiento lógico a la Izquierda

desplazamiento lógico a la Derecha

En un cambio lógico, los ceros se desplaza en reemplazar la descartados bits. Por lo tanto, los desplazamientos a la izquierda lógicos y aritméticos son exactamente los mismos.

Sin embargo, como el desplazamiento lógico a la derecha inserta un valor de 0 bits en el bit más significativo, en lugar de copiar el bit de signo, es ideal para números binarios sin signo, mientras que el desplazamiento aritmético a la derecha es ideal para números binarios de complemento de dos con signo.

Desplazamiento circulareditar

Más información: Desplazamiento circular

Otra forma de desplazamiento es el desplazamiento circular, la rotación de bits o la rotación de bits.

rotadoeditar

Desplazamiento circular izquierdo o rotación

Desplazamiento o rotación circular a la derecha

En esta operación, a veces llamada rotación sin carga, los bits se «giran» como si los extremos izquierdo y derecho del registro estuvieran unidos. El valor que se desplaza a la derecha durante un desplazamiento a la izquierda es el valor que se desplazó a la izquierda, y viceversa para una operación de desplazamiento a la derecha. Esto es útil si es necesario conservar todos los bits existentes, y se usa con frecuencia en criptografía digital.

Rotar a través del transporteditar

Girar a la izquierda a través del transporte

Rotación derecha a través de transporte

Rotar a través de acarreo es una variante de la operación de rotación, donde el bit que se desplaza hacia adentro (en cada extremo) es el valor antiguo de la bandera de acarreo, y el bit que se desplaza hacia afuera (en el otro extremo) se convierte en el nuevo valor de la bandera de acarreo.

Una sola rotación puede simular un desplazamiento lógico o aritmético de una posición configurando la bandera de transporte de antemano. Por ejemplo, si el indicador de carga contiene 0, x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE es un desplazamiento lógico a la derecha, y si el indicador de carga contiene una copia del bit de signo, x RIGHT-ROTATE-THROUGH-CARRY-BY-ONE es un desplazamiento aritmético a la derecha. Por esta razón, algunos microcontroladores, como las imágenes de gama baja, solo tienen que rotar y rotar a través de carry, y no se molestan con las instrucciones de cambio aritméticas o lógicas.

Rotar a través de carry es especialmente útil cuando se realizan cambios en números más grandes que el tamaño de palabra nativo del procesador, porque si un gran número se almacena en dos registros, el bit que se desplaza de un extremo del primer registro debe entrar en el otro extremo del segundo. Con rotar-a través de-transportar, esa broca se «guarda» en la bandera de transporte durante el primer turno, lista para cambiar durante el segundo turno sin ninguna preparación adicional.

En idiomas de alto niveleditar

Más información: Turno circular § Implementación de turnos circulares

C-familyEdit

En los lenguajes de la familia C, los operadores de turno lógicos son» << «para el turno izquierdo y» >> » para el turno derecho. El número de lugares a desplazar se da como segundo argumento al operador. Por ejemplo,

x = y << 2;

asigna x el resultado de desplazar y a la izquierda por dos bits, lo que equivale a una multiplicación por cuatro.

Los cambios pueden dar lugar a un comportamiento definido por la implementación o a un comportamiento indefinido, por lo que se debe tener cuidado al usarlos. El resultado de cambiar un número de bits mayor o igual al tamaño de la palabra es un comportamiento indefinido en C y C++. Desplazamiento a la derecha un valor negativo está definido por la implementación y no recomendado por las buenas prácticas de codificación; el resultado del desplazamiento a la izquierda de un valor con signo no está definido si el resultado no se puede representar en el tipo de resultado.

En C#, el desplazamiento a la derecha es un desplazamiento aritmético cuando el primer operando es un int o largo. Si el primer operando es de tipo uint o ulong, el desplazamiento a la derecha es un desplazamiento lógico.

Desplazamientos circulareseditar

La familia de lenguajes C carece de un operador de rotación, pero uno se puede sintetizar a partir de los operadores de turnos. Se debe tener cuidado para garantizar que la declaración esté bien formada para evitar comportamientos indefinidos y ataques de sincronización en el software con requisitos de seguridad. Por ejemplo, una implementación ingenua que izquierda rota un valor sin signo de 32 bits x por n posiciones es simplemente:

uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (32 - n));

Sin embargo, un desplazamiento de 0 bits resulta en un comportamiento indefinido en la expresión de la derecha (x >> (32 - n)) porque 32 - 0 es 32, y 32 está fuera del rango inclusive. Un segundo intento podría resultar en:

uint32_t x = ..., n = ...;uint32_t y = n ? (x << n) | (x >> (32 - n)) : x;

donde se prueba la cantidad de desplazamiento para asegurarse de que no introduce un comportamiento indefinido. Sin embargo, la rama agrega una ruta de código adicional y presenta una oportunidad para el análisis de tiempo y el ataque, que a menudo no es aceptable en software de alta integridad. Además, el código se compila con múltiples instrucciones de máquina, lo que a menudo es menos eficiente que la instrucción nativa del procesador.

Para evitar el comportamiento indefinido y las ramas bajo GCC y Clang, se recomienda lo siguiente. El patrón es reconocido por muchos compiladores, y el compilador emitirá una sola instrucción de rotación:

uint32_t x = ..., n = ...;uint32_t y = (x << n) | (x >> (-n & 31));

También hay intrínsecos específicos del compilador que implementan cambios circulares, como _rotl8, _rotl16, _rotr8, _rotr16 en Microsoft Visual C++. Clang proporciona algunos intrínsecos de rotación para la compatibilidad con Microsoft que sufre los problemas anteriores. GCC no ofrece rotar intrínsecos. Intel también proporciona intrínsecos x86.

JavaEdit

En Java, todos los tipos enteros están firmados, por lo que los operadores «<<» y «>>» realizan turnos aritméticos. Java añade el operador «>>> » para realizar desplazamientos lógicos a la derecha, pero dado que las operaciones lógicas y aritméticas de desplazamiento a la izquierda son idénticas para enteros con signo, no hay ningún operador «<<<» en Java.

Más detalles de los operadores de turnos Java:

  • Los operadores << (turno izquierdo), >> (turno derecho con signo) y >>> (turno derecho sin signo) se denominan operadores de turno.
  • El tipo de expresión shift es el tipo promovido del operando izquierdo. Por ejemplo, aByte >>> 2 es equivalente a ((int) aByte) >>> 2.
  • Si el tipo promovido del operando izquierdo es int, solo se utilizan los cinco bits de orden más bajo del operando derecho como distancia de desplazamiento. Es como si el operando de la derecha estuviera sujeto a un operador lógico y de bits & con el valor de máscara 0x1f (0b11111). Por lo tanto, la distancia de desplazamiento realmente utilizada está siempre en el rango de 0 a 31, ambos inclusive.
  • Si el tipo promocionado del operando izquierdo es largo, entonces solo se utilizan los seis bits de orden más bajo del operando derecho como distancia de desplazamiento. Es como si el operando de la derecha estuviera sujeto a un operador lógico y de bits & con el valor de máscara 0x3f (0b111111). Por lo tanto, la distancia de desplazamiento realmente utilizada está siempre en el rango de 0 a 63, inclusive.
  • El valor de n > > > s es n posiciones de bits s desplazadas a la derecha con extensión cero.
  • En operaciones de bits y desplazamiento, el tipo byte se convierte implícitamente a int. Si el valor del byte es negativo, el bit más alto es uno, entonces se usan unos para llenar los bytes adicionales en el int. Así que byte b1 = -5; int i = b1 / 0x0200; dará como resultado i = = -5.

JavaScriptEdit

JavaScript utiliza operaciones de bits para evaluar cada una de dos o más unidades en lugar de 1 o 0.

PascalEdit

En Pascal, así como en todos sus dialectos (como Object Pascal y Standard Pascal), los operadores lógicos de desplazamiento izquierdo y derecho son «shl» y «shr«, respectivamente. Incluso para enteros con signo, shr se comporta como un desplazamiento lógico y no copia el bit de signo. El número de lugares a desplazar se da como segundo argumento. Por ejemplo, lo siguiente asigna x el resultado de desplazar y a la izquierda en dos bits:

x := y shl 2;

Deja una respuesta

Tu dirección de correo electrónico no será publicada.

More: