Hay preguntas que te rondan la cabeza durante días hasta que no te queda más remedio que sentarte a escribir. Esta es una de ellas: ¿tiene sentido que sigamos usando Python, Rust o C++ cuando quien va a escribir el código es una máquina? Y su hermana pequeña, la que de verdad me quita el sueño: ¿acabará la IA programando directamente en ensamblador o en código máquina, y los lenguajes de alto nivel quedarán como una curiosidad histórica?

Voy a contaros de dónde viene la duda, qué he descubierto al darle vueltas (y al discutirlo con una IA, por cierto) y a qué conclusión he llegado. Spoiler: no es tan sencillo como parece, pero tampoco estoy tan equivocado como pensaba.

El día que toqué las tripas del hardware

Recuerdo perfectamente la primera vez que vi ensamblador en la carrera. Hasta ese momento, programar era escribir cosas en un lenguaje cómodo, con nombres de variables bonitos, bucles, funciones, y confiar en que «algo» lo convertía en lo que fuera que ejecutaba el procesador. Era Pseudocódigo, luego Pascal … Era magia. Y de repente, el ensamblador te quita el telón.

Mover un valor a un registro. Sumar. Comparar. Saltar a una dirección. Nada de abstracciones: tú, el procesador y una lista de instrucciones que se ejecutan una detrás de otra. Cuando hice mi primer programa en ASM y vi que aquello funcionaba, sentí algo parecido a abrir el capó de un coche por primera vez y ver el motor entero, pieza a pieza. Era tocar las tripas del hardware.

Y ahí se me quedó grabada una idea que durante años di por cierta, casi como un dogma: el ensamblador es lo más rápido que existe. Si el lenguaje de alto nivel es una capa de comodidad que se interpone entre tú y la máquina, quitar esa capa tiene que ser, por fuerza, más veloz. Menos intermediarios, menos pérdidas. Para todo.

Sí, ya sé lo que estáis pensando los que lleváis más tiempo en esto. Pero dejadme seguir.

La idea: las IAs no necesitan lenguajes «para humanos»

Ahora llega la IA, y mi cabeza hace clic. Piénsalo:

Los lenguajes de alto nivel no se inventaron para las máquinas. Se inventaron para nosotros. Para que un humano con memoria limitada, que se cansa, que se equivoca al contar registros y que necesita entender lo que escribió dentro de seis meses, pudiera programar sin volverse loco. Python, Rust, C++, Java… todos son, en el fondo, un puente entre la forma en que pensamos y la forma en que funciona el procesador.

Pero una IA no se cansa. No se pierde en 50.000 líneas de ensamblador. No necesita que una variable se llame contador_de_usuarios para entenderla. Entonces, ¿para qué va a querer ese puente?

Mi razonamiento era este:

  1. Las IAs escribirán cada vez más código, hasta el punto de que los humanos escribiremos poco o nada.
  2. A una IA le da igual el lenguaje. Un lenguaje de alto nivel es una concesión a nuestras limitaciones, no a las suyas.
  3. Si le da igual, escogerá lo que dé mejor rendimiento: ensamblador o código máquina directo.
  4. Conclusión: en pocos años, los lenguajes de alto nivel tenderán a desaparecer. Nuestras amigas las máquinas lo harán todo en ASM, saltándose el compilador, y las cosas irán más rápido que nunca.

Y ojo, que no hablo de webs, donde el cuello de botella es la red y el navegador. Hablo de aplicaciones de escritorio, de software que corre pegado al metal.

Me pareció una teoría redonda. Así que fui a ponerla a prueba, y la comenté con una IA para ver qué opinaba. La respuesta me hizo replantearme bastantes cosas.

Primer golpe: el ensamblador no siempre es más rápido

Lo primero que me tumbó fue mi «dogma» de juventud. «Ensamblador = más rápido» es, en la mayoría de los casos, un mito.

Resulta que los compiladores modernos, como LLVM o GCC, llevan décadas acumulando optimizaciones: reordenan instrucciones para aprovechar la segmentación del procesador, desenrollan bucles, vectorizan operaciones, eliminan código muerto, colocan los datos de forma que la caché los agradezca. Eso es el trabajo de miles de ingenieros durante más de cincuenta años, aplicado de forma sistemática.

Un programador humano escribiendo ensamblador a mano puede ganarle al compilador en una función pequeña y muy concreta. Pero en un programa grande, casi siempre pierde, porque no es capaz de mantener en la cabeza todas esas optimizaciones a la vez. Y una IA, aunque no se canse, tampoco tiene por qué ganar a base de «escribir ASM a lo bruto»: lo que le da ventaja no es el lenguaje, sino la capacidad de buscar y probar. Más sobre eso enseguida.

Segundo golpe: el alto nivel no solo sirve para leerse

Aquí es donde mi teoría hacía aguas de verdad. Yo pensaba que los lenguajes de alto nivel eran solo una cuestión de comodidad. Pero también son una cuestión de garantías.

Tomemos Rust. Su gran virtud es que el compilador te demuestra, antes de ejecutar nada, que tu programa no tiene ciertos tipos de errores de memoria. Eso no es comodidad: es una propiedad verificable. El lenguaje es un contrato entre lo que quieres y lo que va a ejecutarse.

Si una IA escribe ensamblador directamente, ¿quién comprueba que está bien? En ensamblador, la información se pierde: no sabes qué punteros pueden solaparse, qué datos son inmutables, qué bucles se pueden paralelizar sin riesgo. Auditar eso es casi imposible. Y yo había dado por hecho que el software de IA «no tendrá fallos y se autocorregirá».

Pues justo ahí está el problema. Para corregir un fallo hay que saber qué es «correcto». Y muchos errores no son errores de ejecución, sino de intención: el programa hace exactamente lo que le pediste, pero no lo que querías. Además, hay límites teóricos conocidos desde Turing: no se puede verificar automáticamente cualquier propiedad de cualquier programa. Una IA que se autocorrige necesita un comprobador, y ese comprobador necesita una especificación formal.

Es decir, que la solución a «la IA también se equivoca» no es quitar el nivel intermedio, sino tener uno más formal, no menos.

Tercer golpe: la portabilidad

El código máquina es específico de cada arquitectura. Lo que funciona en x86 no vale en ARM, y no digamos en RISC-V. Con un lenguaje de alto nivel (o con una representación intermedia), compilas una vez y apuntas a varias plataformas.

Si la IA escribiera todo en ensamblador, tendría que regenerar el programa entero para cada procesador, cada generación de procesador incluso. Y mientras haya humanos responsables del software, ya sea por razones legales, de seguridad o de negocio, necesitarán poder leer qué hace aquello.

Pero ojo: mi intuición no iba desencaminada. El caso DeepSeek

Hasta aquí parece que me han desmontado la idea. Pero hay una parte de mi intuición que se sostiene, y el mejor ejemplo es DeepSeek.

Cuando DeepSeek sorprendió al mundo con modelos de primer nivel entrenados con una fracción de los recursos habituales, se habló mucho de cómo habían exprimido un hardware limitado. Las GPU a las que tenían acceso (las H800 de NVIDIA, una versión recortada en ancho de banda de comunicación entre chips) no daban para fuerza bruta. Tuvieron que ser listos.

Y una de las cosas que hicieron fue bajar de nivel. No escribieron todo en código máquina, ojo: trabajaron en PTX, el lenguaje intermedio parecido al ensamblador que hay por debajo de CUDA. Lo usaron en partes muy concretas, como la gestión de la comunicación entre GPUs y el reparto de las unidades de cómputo, dedicando parte de la GPU a mover datos mientras el resto calculaba. Un control fino que CUDA «normal» no les permitía.

Esto es lo importante: no fue «todo en bajo nivel», fue cirugía en el cuello de botella. Pero demuestra algo fascinante: cuando el hardware es el límite y cada porcentaje de rendimiento vale millones, bajar a las tripas compensa. Mi yo universitario, ese que tocó el ASM por primera vez y se enamoró del metal, sonrió al leerlo.

Otro ejemplo: cuando una IA le gana a los humanos en ensamblador

Hay otro caso que me parece todavía más revelador. AlphaDev, de DeepMind, un sistema entrenado con aprendizaje por refuerzo, se puso a buscar mejores rutinas de ordenación. Pero no lo hizo escribiendo código bonito: lo planteó como un juego en el que cada movimiento era elegir una instrucción de ensamblador, y la recompensa era que el resultado fuera correcto y rápido.

El resultado: encontró secuencias de instrucciones para ordenar listas cortas que eran más rápidas que las que llevaban décadas siendo el estándar, con algunos trucos que a los humanos no se les habían ocurrido. Tan buenas que se incorporaron a la biblioteca estándar de C++ de LLVM. Algo que usan millones de programas, mejorado por una máquina trabajando directamente con ensamblador.

Pero fijaos en la clave: AlphaDev no «escribe ensamblador porque le da igual el lenguaje». Lo hace porque la búsqueda funciona mejor ahí, en un espacio de instrucciones pequeñas donde puede probar, medir y verificar que el resultado es correcto. Se trata de superoptimización: en lugar de aplicar reglas fijas como un compilador, la IA explora miles de variantes y se queda con la mejor, comprobando que sigue haciendo lo mismo que el original.

¿Cómo sería entonces un lenguaje hecho solo para IAs?

Aquí viene lo más interesante, y donde mi intuición dio un giro de 180 grados. Yo imaginaba un lenguaje para IA como «ensamblador, pero más bestia todavía». La realidad probablemente sería lo contrario.

El ensamblador, para una IA, es pobre en información. Lo que necesita para optimizar a tope no es menos contexto, sino más. Un lenguaje diseñado para máquinas probablemente tendría:

  • Intención y restricciones explícitas. No solo «haz esto», sino «estos datos no se solapan», «este bucle es paralelizable», «esto es inmutable». Algo parecido a lo que ya se hace con representaciones como MLIR o grafos de flujo de datos. Más información significa más margen de optimización.
  • Un modelo explícito del hardware. Jerarquía de memoria, registros, latencias, ancho de banda… todo como parte del programa, no escondido tras el compilador. Justo lo que DeepSeek tuvo que hacer a mano en las partes críticas.
  • Superoptimización por búsqueda. Exploración automática de variantes, con comprobación de equivalencia.
  • Pruebas incrustadas. Código que viaja acompañado de una demostración formal de que cumple su especificación (lo que se conoce como proof-carrying code), de modo que la verificación sea automática.
  • Sin sintaxis para humanos. Grafos o formatos binarios compactos en lugar de texto con sangrías y llaves.

Es decir: un lenguaje que a nosotros nos resultaría ilegible, pero que sería más abstracto y más formal que Python, no menos. Irónico, ¿verdad? Para que la máquina vaya más rápido, lo que necesita no es bajar al metal sin red, sino subir a un nivel de descripción más rico, y dejar que la optimización baje sola.

Dónde sí y dónde no tiene sentido bajar al metal

Tampoco quiero pasarme de listo en el sentido contrario. Hay territorios donde bajar a muy bajo nivel va a ser la norma, con IA o sin ella:

  • Kernels de GPU y aceleradores de IA. Aquí cada ciclo cuenta, y es donde la IA ya está ayudando a generar y ajustar código muy específico.
  • Inferencia y entrenamiento de modelos. Los costes energéticos y económicos hacen que cualquier mejora del 5 % valga una fortuna.
  • Criptografía, códecs, bucles críticos. Zonas pequeñas, muy calientes, donde el ajuste fino se amortiza.

Pero para una aplicación de escritorio típica, un editor, un gestor de archivos, una herramienta de oficina, no tiene sentido. El cuello de botella suele ser el disco, la red o la lógica del programa, no las instrucciones que ejecuta el procesador. Optimizar eso a mano (o con IA) a cambio de perder portabilidad y capacidad de auditoría es mal negocio. Aquí, mi «ensamblador para todo» de la carrera se queda en una romántica ilusión.

Pero en los 80 lo hacíamos todo en código máquina, ¿no?

Aquí es donde los veteranos me estarán esperando con el dedo levantado, y con razón. En los 80, los juegos de 8 bits se programaban directamente en código máquina, y eran una maravilla de eficiencia. Un Spectrum, un Commodore 64, un MSX o un Atari metían mundos enteros en 16 o 48 KB. ¿No demuestra eso que el ensamblador es lo más eficiente que hay?

Demuestra algo más interesante: que era la mejor opción en aquel contexto, no la mejor opción siempre. Fíjate en lo que había entonces:

  • Los compiladores eran malos para aquellas CPUs. Un 6502 o un Z80 tienen pocos registros, 8 bits y modos de direccionamiento limitados. Un compilador de C generaba un código bastante peor que el de una persona con paciencia y papel cuadriculado.
  • La alternativa era BASIC, que era interpretado, y por tanto entre decenas y cientos de veces más lento. No era “C contra ensamblador”: era “ensamblador contra algo que no daba para hacer un juego”.
  • El hardware era pequeño y predecible. Sin caché, sin pipeline, sin predicción de saltos, sin ejecución fuera de orden. Podías contar los ciclos de cada instrucción y saber exactamente cuánto tardaba. Con eso se hicieron auténticas proezas, como los programadores del Atari 2600, que sincronizaban su código con el haz de electrones del televisor, línea a línea.
  • Un solo hardware y programas diminutos. Todo el juego cabía en la cabeza de una persona, y no había que portarlo a nin

Mi conclusión (de momento)

Después de darle vueltas, creo que el futuro más probable se parece a esto:

  1. Los lenguajes de alto nivel no desaparecen, pero cambian de lector. Los humanos acabaremos escribiendo más en lenguaje natural y especificaciones, y el código intermedio será algo que la IA genera y que casi nadie toca. Como pasó con el ensamblador: no se extinguió, simplemente casi nadie lo escribe a mano.
  2. Aparecerán lenguajes pensados para máquinas, más formales, más ricos en información, más fáciles de verificar. No más «bajos», sino más precisos.
  3. Las partes calientes se optimizarán a muy bajo nivel por IA, igual que hizo AlphaDev con la ordenación o DeepSeek con PTX, mientras que por encima seguirá existiendo una capa que da portabilidad y garantías.
  4. Lo que de verdad se vuelve imprescindible es la verificación. Cuanto más código escriba la IA, más valor tendrá poder comprobar, de forma automática y fiable, que hace lo que debe.

Lo que no veo es un mundo en el que las máquinas escupan ensamblador a lo loco, sin red, sin pruebas y sin posibilidad de entender qué hace cada cosa. Ese mundo sería rapidísimo y, a la vez, frágil e inauditable. Y por muy bonito que fuera aquel primer programa en ASM que escribí en la carrera, no lo cambiaría por un sistema en el que nadie sepa por qué funciona.

Curiosamente, lo que más me quedó de todo este razonamiento es que mi intuición de estudiante no estaba equivocada: estaba incompleta. Sí, bajar a las tripas del hardware da un control que nada más da. Pero lo que hace que ese control sea útil no es el ensamblador en sí, sino saber cuándo y dónde usarlo, y poder demostrar que lo has hecho bien. Eso lo sabía el DeepSeek que ajustó su PTX en el cuello de botella, y lo sabe el AlphaDev que mejoró una rutina de ordenación. Y lo está aprendiendo, poco a poco, el estudiante de ingeniería que llevo dentro.

Y ahora te toca a ti

¿Tú qué opinas? ¿Crees que veremos a las IAs saltarse el compilador y hablar directamente con el procesador, o que el alto nivel se reinventará para ser más formal que nunca? ¿Has tocado ensamblador alguna vez y te dejó la misma huella que a mí?

Déjame tu opinión en los comentarios. Esta es de esas conversaciones que mejoran cuanta más gente se apunta.