Cómo funcionan las computadoras: una explicación desde lo más básico


Empezando por una pulsación de tecla

Presionas la letra ‘A’ en tu teclado.

En menos de 1 milisegundo, el carácter aparece en la pantalla.

¿Parece sencillo? En realidad, en ese milisegundo, una señal eléctrica atraviesa al menos 6 capas de abstracción, pasa por docenas de componentes de hardware y cruza múltiples buses para completar esta interacción “sencilla”.

La esencia de las computadoras no es el cálculo, sino la abstracción.

Cada capa oculta la complejidad subyacente y solo expone una interfaz limpia a la capa superior. Gracias a estas abstracciones, los programadores pueden escribir código en lenguajes de alto nivel sin preocuparse de cómo fluyen los electrones a través de los transistores.

Hoy, seguimos el viaje completo de una señal de pulsación de tecla, observando cómo las computadoras, capa tras capa de abstracción, transforman una acción física en un carácter en la pantalla.

Primera capa: de la señal física al código de exploración

Imagen

Lo que presionas no es una letra, sino un interruptor.

Debajo de cada tecla del teclado hay un interruptor mecánico. Cuando presionas la tecla ‘A’, el interruptor se cierra y la corriente fluye. Esta es la realidad física más básica: solo encendido y apagado, no hay ‘A’.

El trabajo del controlador del teclado es traducir esta señal física a números que la computadora pueda entender.

¿Cómo lo hace?

Exploración matricial

Más de 100 teclas en un teclado. Si cada una tuviera su propio cable conectado a la computadora, el cable del teclado sería más grueso que tu dedo. Por eso el teclado usa un diseño inteligente: la exploración matricial.

Imagina un tablero de ajedrez, con líneas de filas y líneas de columnas que se cruzan. Cada tecla está en una intersección. El controlador energiza rápidamente cada fila y detecta si hay corriente en cada columna. Si la columna 5 detecta corriente cuando la fila 3 está energizada, significa que la tecla en la fila 3, columna 5 ha sido presionada.

De aquí viene el código de exploración (scan code): un número que representa la posición de una tecla.

Presionar ‘A’ podría generar el código de exploración 0x1E. Soltar ‘A’ genera 0x9E (con un bit alto adicional que indica “liberación”).

Primera capa completa: acción física → codificación digital.

Pero aún no ha terminado. El código de exploración todavía está en el búfer interno del teclado, esperando ser enviado.

Segunda capa: del dispositivo de E/S a la memoria

Imagen

El código de exploración debe llegar a la CPU, pero la CPU no puede quedarse esperando la entrada del teclado.

La CPU opera a miles de millones de operaciones por segundo; la entrada del teclado llega a decenas de entradas por segundo. Si la CPU verificara “¿hay entrada del teclado?” antes de cada instrucción, el 99.9999% de su tiempo se desperdiciaría.

¿Cuál es la solución? El mecanismo de interrupción.

Interrupciones: la versión hardware de “llámame cuando estés listo”

La filosofía de diseño de las interrupciones refleja la vida cotidiana: no llamas al repartidor cada 5 minutos preguntando “¿ha llegado mi paquete?” En cambio, el repartidor te llama cuando llega.

Después de que el controlador del teclado genera un código de exploración, envía una señal de Solicitud de Interrupción (IRQ) a la CPU.

Esta señal pasa a través del controlador de interrupciones (8259A o su equivalente moderno) y se le asigna un número de interrupción. El teclado es típicamente IRQ1, número de interrupción 0x21.

Después de ejecutar cada instrucción, la CPU verifica si hay señales de interrupción. Si hay una, pausa su trabajo actual y maneja la interrupción.

La tabla de vectores de interrupción

¿Cómo sabe la CPU cómo manejar una interrupción del teclado?

En la memoria hay una Tabla de Vectores de Interrupción (Interrupt Vector Table) que almacena la dirección de la rutina de manejo para cada número de interrupción. Es como una guía telefónica: el número de interrupción 0x21 corresponde a la dirección del manejador del teclado.

Cuando la CPU recibe una interrupción del teclado:

  1. Empuja el Contador de Programa (PC), el registro de estado, etc. a la pila
  2. Busca en la tabla usando el número de interrupción para encontrar la dirección del manejador
  3. Salta al manejador y lo ejecuta

El manejador del teclado lee el código de exploración a través de un puerto de E/S (típicamente 0x60) y luego lo almacena en el búfer del teclado en memoria.

Segunda capa completa: evento de E/S → datos en memoria.

Ahora el código de exploración está seguro en la memoria. Pero sigue siendo un código de exploración, no el carácter ‘A’.

Tercera capa: del código de exploración al carácter

Imagen

El código de exploración 0x1E representa “la posición de la tecla A en el teclado”, no el carácter ‘A’.

¿Por qué? Porque la misma tecla puede representar diferentes caracteres en teclados de diferentes países. Los estadounidenses la presionan y obtienen ‘A’; los franceses la presionan y obtienen ‘Q’ (la distribución de su teclado es diferente).

El sistema operativo es responsable de convertir los códigos de exploración en caracteres.

El subsistema de entrada

Los sistemas operativos modernos tienen un Subsistema de Entrada (Input Subsystem), que maneja:

  1. Leer los códigos de exploración del búfer del kernel
  2. Convertirlos en caracteres según la distribución actual del teclado
  3. Manejar las teclas modificadoras (Shift+A = ‘A’ mayúscula, Ctrl+C = comando copiar)
  4. Entregar el carácter a la ventana activa

Esta conversión implica una tabla de mapeo de distribución del teclado. El registro de Windows contiene HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layouts, que almacena el mapeo para varios idiomas.

Después de la conversión, el carácter ‘A’ se coloca en una cola de mensajes, esperando ser leído por la aplicación.

Tercera capa completa: codificación dependiente del hardware → codificación de caracteres unificada.

Cuarta capa: del carácter al píxel

Imagen

La aplicación recibe el carácter ‘A’ y necesita mostrarlo en la pantalla.

Pero lo que ves no es un carácter, son píxeles.

Un monitor solo entiende píxeles: de qué color es cada punto. El carácter ‘A’ es un patrón formado por un conjunto de píxeles, almacenado en un archivo de fuente.

Renderizado de fuentes

Cuando escribes ‘A’, la aplicación:

  1. Busca el archivo de fuente (por ejemplo, Microsoft YaHei, SimSun)
  2. Obtiene la descripción del glifo para ‘A’ (curvas vectoriales o mapa de bits)
  3. Escala el glifo según el tamaño de la fuente
  4. Rasteriza: convierte las curvas vectoriales en una cuadrícula de píxeles
  5. Aplica suavizado (anti-aliasing) para bordes más suaves

Estos datos de píxeles se escriben en la memoria de video (VRAM), que es la memoria de la tarjeta gráfica.

De la VRAM a la pantalla

El controlador de visualización de la tarjeta gráfica lee datos de la VRAM 60 veces por segundo (60 Hz), los convierte en una señal de video y la envía al monitor.

El monitor recibe la señal, controla el color de cada píxel, y ves el carácter ‘A’.

Cuarta capa completa: codificación de caracteres → matriz de píxeles.

Quinta capa: cómo ejecuta la CPU estas instrucciones

Imagen

Todas las operaciones mencionadas anteriormente — exploración, interrupciones, conversión, renderizado — deben ser ejecutadas por la CPU.

¿Cómo ejecuta la CPU las instrucciones?

El ciclo de instrucción: buscar-decodificar-ejecutar

La ejecución de una instrucción tiene tres etapas:

  1. Buscar (Fetch)

    • El Contador de Programa (PC) almacena la dirección de la siguiente instrucción
    • Envía la dirección a la memoria, recupera la instrucción
    • Almacena la instrucción en el Registro de Instrucción (IR)
  2. Decodificar (Decode)

    • La unidad de control analiza el código de operación de la instrucción
    • Determina qué operación realizar (suma, carga, salto)
    • Determina dónde están los operandos
  3. Ejecutar (Execute)

    • La Unidad Aritmético-Lógica (ALU) realiza el cálculo
    • O accede a la memoria para leer/escribir datos
    • Actualiza el Contador de Programa

Luego se repite.

Un ejemplo

Supongamos que la CPU necesita ejecutar ADD R1, R2, R3 (sumar los valores en R2 y R3, almacenar en R1):

  1. Buscar: leer el código máquina para esta instrucción desde la memoria
  2. Decodificar: reconocer esto como una instrucción de suma, operandos en R2 y R3
  3. Ejecutar: la ALU envía los valores de R2 y R3 al sumador, escribe el resultado en R1

Cada instrucción se completa en nanosegundos.

Quinta capa completa: lenguaje de alto nivel → instrucciones de máquina → señales eléctricas.

El costo de la abstracción

La abstracción no es gratuita.

Cada capa de abstracción tiene un costo de rendimiento:

  • Exploración del teclado: unos microsegundos
  • Manejo de interrupción: decenas de microsegundos
  • Conversión del sistema operativo: cientos de microsegundos
  • Renderizado de fuentes: unos milisegundos
  • Escritura en VRAM: unos microsegundos

En conjunto, esto es el “retardo de entrada” (input lag) que experimentas, típicamente entre 10 y 50 milisegundos.

Para una persona común, este retardo es insignificante. Pero para los jugadores de esports, es una diferencia de vida o muerte. Por eso usan teclados mecánicos (activación más rápida), monitores de alta tasa de refresco (144 Hz o más) y conexiones por cable (el wifi añade latencia adicional).

Una conclusión

La esencia de las computadoras es la abstracción: encapsular la complejidad, exponer solo una interfaz simple.

El viaje de una señal de pulsación de tecla:

Interruptor físico → código de exploración → interrupción → búfer de memoria → codificación de caracteres → cola de mensajes → renderizado de fuentes → VRAM → píxel

Cada capa hace solo una cosa: recibir la salida simplificada de la capa inferior, procesarla y proporcionar una interfaz simplificada a la capa superior.

Es precisamente esta abstracción en capas la que permite a los humanos dominar sistemas informáticos increíblemente complejos.

Los programadores no necesitan saber cómo funciona la exploración del teclado — solo necesitan leer el valor de retorno de getchar().

Los programadores no necesitan saber cómo renderiza la tarjeta gráfica — solo necesitan llamar a la función DrawText().

El poder de la abstracción es hacer manejable la complejidad.

Imagen