Bits, bytes y bajo nivel

Binario y hexadecimal, operadores de bits, máscaras, overflow, punto flotante, endianness, padding y un display de 7 segmentos: la máquina por dentro, dibujada en una placa.

13 aulas · 11 horas de práctica · en el navegador, sin instalar nada

Temario

  1. Binario y hexadecimal — Un número es una fila de luces: cada dígito binario prende o apaga una. Cuánto vale cada luz, cómo pasar de binario a decimal y de vuelta, y por qué el hexadecimal es la forma cómoda de escribir bits.
  2. sizeof y enteros de tamaño fijo — Cuántos bytes ocupa cada tipo (y por qué depende de la máquina), sizeof para medirlo, y los enteros de <cstdint> que miden lo mismo en todas partes: uint8_t, int16_t, uint32_t, int64_t y sus límites.
  3. Los operadores de bits: &, |, ^ y ~ — Operar dos números luz por luz: & (las dos), | (alguna), ^ (una sola) y ~ (al revés). Con eso se prende, se apaga y se da vuelta cualquier LED sin tocar los demás. Y la trampa de ~ sobre un uint8_t.
  4. Desplazamientos: << y >> — Correr los bits a la izquierda o a la derecha: 1 << n es el bit n, x << 1 duplica y x >> 1 divide por 2. Con desplazamientos y máscaras se lee un bit suelto y se empaquetan varios números en uno (un color de 16 bits).
  5. Bitmasks y flags — Muchas opciones de sí o no en un solo número: un bit con nombre por opción, | para juntarlas, & para preguntar, & ~ para sacarlas. Con eso, el controlador de un cruce decide la luz de cada minuto según lo que vieron sus sensores.
  6. Con signo, sin signo y overflow — Cómo se guarda un negativo (complemento a dos), qué pasa cuando un número no entra en su caja: los sin signo dan la vuelta, los con signo rompen el programa. Y la historia real del Ariane 5, que explotó por una conversión a 16 bits.
  7. Punto flotante: por qué 0.1 + 0.2 ≠ 0.3 — Un double no guarda 0,1: guarda el número binario más cercano. Por qué pasa, cómo son los 32 bits de un float (signo, exponente y mantisa) y las dos formas sanas de manejar plata: centavos enteros o comparar con tolerancia.
  8. Bytes y endianness — La memoria es una fila de bytes con dirección, y un número de 4 bytes ocupa 4 seguidos. ¿En qué orden? En casi todas las máquinas, el byte más bajo primero (little-endian); en la red, al revés. Mirar los bytes con memcpy y un unsigned char*, y pasar de un orden al otro.
  9. Alineación y padding — Un struct ocupa más que la suma de sus campos: cada campo tiene que empezar en una dirección múltiplo de su tamaño, y el compilador mete bytes de relleno. Verlos en el depósito, medirlos con sizeof y offsetof, y achicar un struct cambiando el orden.
  10. Display de 7 segmentos — El display de las calculadoras y los relojes: siete rayitas y un punto, cada una un bit de un byte. Armar la máscara de cada dígito, juntar dos dígitos en 16 bits, prender el punto decimal y hacer una cuenta regresiva sin el cero de adelante.
  11. Compresión RLE — La compresión más simple que existe: en vez de repetir, contar. "WWWWWWBBB" pasa a "6W3B". Descomprimir el mapa de un pasillo para encontrar la puerta, comprimir bytes con un contador de un byte, y saber cuándo comprimir no conviene.
  12. Taller: el controlador de un semáforo embebido — Un microcontrolador maneja un semáforo escribiendo un byte por tick en un puerto: un bit por lámpara. El ciclo básico, las fases en una tabla, el botón del peatón como máquina de estados, el amarillo titilante de la falla y la cuenta regresiva empaquetada en el mismo byte.
  13. Taller: checksums — Un número chico que resume un mensaje, para saber si llegó entero: la suma de bytes, el XOR, Fletcher-16 y el CRC-8 de los protocolos de verdad. Cada paquete de la radio de un globo trae el checksum del anterior, y la cadena se corta donde tu cuenta no coincide.

Es parte de