peron:~$ cat verdaderos_programadores_fortran.txt
Tal vez lo hagan ahora, en esta decadente era de cervezas en lata, calculadoras de mano y software "amigable". Pero en los Buenos Viejos Tiempos - cuando el término "software" sonaba a chiste y las Verdaderas Computadoras estaban hechas con memorias de tambor magnético y válvulas de vacío - los Verdaderos Programadores escribían en código máquina. No lo hacían en FORTRAN. Ni en RATFOR. Ni siquiera en lenguaje ensamblador. Usaban Código máquina. Directamente, en números hexadecimales crudos. Sinadornos. Inescrutables.
Ya que una entera y nueva generación de programadores ha crecido en la ignorancia de este pasado glorioso, me siento en el deber de describir - saltando como mejor pueda la brecha generacional - como los Verdaderos Programadores escribían código. Lo llamaré Mel, porque tal era su nombre.
Conocí a Mel por vez primera cuando fui a buscar trabajo a la Royal McBee Computer Corp., subsidiaria ya difunta de la compañía de máquinas de escribir. La firma fabricaba la LGP-30, una computadora con memoria de tambor magnético pequeña y barata (para los estándares del momento). Y habían iniciado producción de la RPC-4000, una muy mejorada, mayor, mejor y más rápida ... máquina de tambor magnético.
La memoria de núcleo costaba mucho, y de todas maneras no estábamos allí para quedarnos (ese es el motivo por el cual probablemente no hayan oído de esta compañía o sus computadoras).
Me habían contratado para escribir un compilador de FORTRAN para este nuevo prodigio, y Mel fue mi guía de sus maravillas. Mel no aprobaba el uso de compiladores.
"Si un programa no puede reescribir su propio código", me preguntó "qué sentido tiene?".
Mel había escrito - en hexadecimal - el programa de computadora más popular que poseía la compañía. Corría en la LGP-30 y jugaba blackjack con potenciales compradores en las exposiciones de computación. Su efecto era siempre dramático. El stand de la LGP-30 rebozaba en todas las exposiciones, y los vendedores de IBM se aparecían, y hablaban entre sí. Si este programa servía para vender computadoras o no, fue algo que nunca discutimos.
El trabajo de Mel consistía en reescribir su programa de blackjack para la RPC-4000. (¿Portar? ¿Qué es eso?). La nueva computadora constaba de un esquema de direccionamiento uno mas uno, en el cual cada instrucción de máquina, además de ser el opcode y la dirección del operando requerido, constaba de una segunda dirección que indicaba dónde se localizaba la siguiente instrucción en el tambor rotativo.
En terminología moderna, podría decirse que cada instrucción venía seguida de un GOTO. Coloca eso en tu pipa de PASCAL y fuma.
Mel adoraba la RPC-4000 porque podía optimizar su código: o sea, disponer las instrucciones en el tambor magnético de tal manera que cuando una finalizase su ejecución, la siguiente estuviese llegando ya al "cabezal de lectura" y estuviese disponible para su ejecución inmediata. Existía un programa que cumplía precisamente esta función: era un "optimizador de ensamblador". Pero Mel se negaba a utilizarlo.
"Nunca puedes saber donde va a colocar las cosas", explicaba, "así que tú tendrás que usar constantes separadas".
Pasó un largo tiempo antes que fuese capaz de entender el significado de este uso de palabras. Como Mel conocía el valor numérico de cada opcode, y asignaba sus propias direcciones en el tambor, cada instrucción que él escribía podía también ser considerada como una constante numérica. Podía escoger una instrucción anterior "ADD", y - digamos - multiplicar por ella, si es que esta contenía el valor numérico adecuado. No era sencillo que alguien que no fuese él modificara su código.
Comparé los programas optimizados a mano por Mel con el mismo código masajeado por el programa optimizador de ensamblador, y el de Mel siempre corría más rápido. Esto se debía a que el método de diseño de programacion "de arriba a abajo" aún no se había inventado, y en todo caso, Mel no lo hubiese utilizado. Él escribía las partes más internas de sus bucles en primer lugar, de modo que obtuviesen la primera opción dentro de las localizaciones de direccionado óptimas. El optimizador de ensamblador no era lo suficientemente listo como para hacerlo de esta manera.
Mel tampoco escribía bucles de retraso de tiempo de ejecución, incluso aunque la ruidosa Flexowriter requería de ciertos retrasos entre los caracteres de salida para funcionar correctamente. Él simplemente dispononía las instrucciones en el tambor de modo que cada una de las sucesivas se viese justo a continuación en el momento que el cabezal de lectura la necesitaba. Le evitaba al tambor tener que completar otra revolución completa para encontrar la siguiente instrucción. Acuñó un término inolvidable para este procedimiento. Si bien "óptimo" es un término absoluto, tal como "único", se ha hecho una práctica verbal común tornarlo en relativo: "no es tan óptimo" o "menos óptimo", o "no demasiado óptimo". Mel llamaba a las localizaciones máximas de retraso de tiempo de ejecución como las "más pésimas".
Tras finalizar el programa de blackjack y lograr que corriera ("incluso el inicializador está optimisado", dijo orgulloso), recibió una Solicitud de Cambio del departamento de ventas. El programa usaba un generador de números aleatorios elegante (optimizado) que barajaba las "cartas" y sacaba desde el "mazo", pero alguno de los vendedores sintió que era demasiado justo, ya que a veces los clientes perdían. Querían que Mel modificase el programa de modo que fuese posible establecer un conmutador de posibilidades de juego en la consola, con el fin de hacerlo capaz de ajustar la frecuencia en la que el cliente ganaría.
Mel estalló. Sintió que esto era patentemente deshonesto - que lo era - y que inflingía su integridad personal como programador - que lo hacía. De modo que se negó a hacerlo. El Jefe del Sector Ventas habló con Mel, el Jefe hablço con él, y bajo solicitud del Jefe, varios programadores más también lo hicieron. Mel finalmente cedió y escribió el código, pero hizo un cambio el sentido de la evaluación del bucle, y cuando el conmutador de posibilidades se activaba, el programa haría trampa, ganando cada vez. Mel quedó extasiado con esto, declamando que su subconciente era incontrolablemente ético, y inflexiblemente se negó a corregirlo.
Luego que Mel hubo abandonado la Compañía en busca de pa$tura$ ma$ verde$, el Jefe me pidió que revisara el código y me fijase si podía encontrar la evaluación y deshacerla. De mala gana acepté a miralo. Rastrear el código de Mel era una verdadera aventura.
A menudo siento que la programación es una forma de arte, cuyo valor real sólo puede ser apreciado por otro versado en el mismo arte arcano. Entre las rocas existen gemas brillantes ocultas de la vista y admiración de los hombres - a veces para siempre - por la propia naturaleza del proceso. Puedes aprender mucho de un individuo con sólo leer su código, incluso en hexadecimal. Mel era, creo, un genio inapreciado.
Tal vez mi sorpresa más grande fue cuando encontré un bucle inocente que no tenía una evaluación en él. Sin test. Ninguno. El sentido común diría que tenía que tratarse de un bucle cerrado, donde el programa debería girar sobre si mismo, sin fin y para siempre. Sin embargo, el programa de control circulaba a través de él y salía - seguro - del otro lado. Me llevó dos semanas comprenderlo.
La computadora RPC-4000 tenía una característica realmente moderna llamada el índice de registro. Le permitía al programador escribir un bucle de programación que usara una instrucción indizada en su interior.
Toda vez que el registro pasara a través del bucle, el número en el ñindice de registro se sumaba a la dirección de dicha instrucción, de manera que refiriese al dato siguiente en una serie. Él sólo tenía que incrementar el índice de registro de cada vez que pasara. Mel nunca lo usó.
En lugar de ello, colocaba la instrucción en un registro de máquina, sumaba uno a su dirección, y la almacenaba nuevamente. A continuación ejecutaría la instrucción modificada directamente desde el registro. El bucle estaba escrito de manera tal que este tiempo de ejecución adicional había sido tenido en cuenta: justo cuando finalizaba la ejecución de esta instrucción, la siguiente se encontraría ya directamente bajo el cabezal de lectura lista para ser leída. Pero el bucle no contenía una evaluación en él.
La pista vital vino cuando noté que el bit del índice de registro, el bit qye se encontraba entre la dirección y el opcode en la word de instrucción, estaba encendido... a pesar de que Mel nunca había usado el índice de registro, dejándolo todo el tiempo en cero. Cuando la luz se encendío casi me cegó.
Él había colocado los datos con los que estaba trabajando cerca de la parte superior de la memoria... las localizaciones más grandes que las instrucciones podrían direccionar... de manera tal que al entregar el último dato, en el momento de incrementar las direcciones de memoria se provocaría un desbordamiento de enteros. El resto sería sumar uno al opcode, convirtiéndolo en la siguiente del conjunto de instrucciones: esta era la instrucción "JUMP". Obviamente, la siguiente instrucción del programa se localizaba en la dirección de memoria cero, y el programa continuaba feliz y contento su camino.
No me he mantenido en contacto con Mel, de modo que no sé si alguna vez se rindió al torrente de cambio que se azotaron las técnicas de programación desde aquellos días largamente pasados. Me gustaría pensar que no lo ha hecho. De cualquier manera, quedé lo suficientemente impresionado que dejé de buscar la evaluación ofensiva, y le dije al Jefe que no la había podido encontrar. No pareció soprenderse.
Cuando dejé la compañía, el programa blackjack aún hacía trampa si activabas el interruptor de posibilidades, y pienso que tal es la forma en la que debería suceder.
Al fin y al cabo, no me sentía cómodo hackeando el código de un Verdadero Programador.
peron:~$ █