¿Hay seres humanos que codifican en lenguaje de máquina?

Con la advertencia de Matt Schoen de que está preguntando sobre el lenguaje ensamblador en lugar del lenguaje de máquina, sí. Las personas que trabajan en los kernels del sistema operativo, los controladores de dispositivos, los compiladores y algunas aplicaciones sensibles al rendimiento escribirán en ensamblador. Y no debo olvidar las herramientas de reescritura binaria como dyninst y pin, cuyos autores también pasan mucho tiempo en el montaje.

Si está escribiendo malware o trabajando en un procesador (o controlador integrado o microcontrolador) que no tiene un buen ensamblador, podría estar pensando en codificar en bits reales: “Puedo ocultar mi programa en estos dieciocho bytes, ahora qué instrucciones particulares debo elegir para lograr eso? “.

Una situación más en la que puede ver el lenguaje de máquina real: firmware. El conjunto de instrucciones x86 es clásicamente CISC, pero el hardware subyacente divide algunas de las instrucciones más complejas en rutinas usando la arquitectura RISC subyacente. Dudo que encuentre un ensamblador a ese nivel, por lo que la gente que está escribiendo firmware probablemente esté seleccionando las instrucciones a mano.

¿Está distinguiendo “lenguaje de máquina” de “lenguaje ensamblador”? Si es así, entonces apuesto a que la respuesta sigue siendo “sí” si estás diseñando una nueva arquitectura o algo así: alguien tiene que construir el primer compilador.

De lo contrario, el lenguaje ensamblador todavía se usa ampliamente. Los desarrolladores de juegos lo usan todo el tiempo, y juegos sorprendentemente modernos como RollerCoaster Tycoon fueron escritos completamente en ensamblador. Incluso hoy en día, las funciones críticas (especialmente en las GPU o las SPU de PS3) están optimizadas a mano en lenguaje ensamblador (¡lo cual es una locura!).

Usar asm.js es algo así como programar en ensamblaje.

Sí, lo hago cuando sucede que un binario ya compilado debe comportarse de manera diferente, y el código fuente que lo produjo se ha perdido en las arenas del tiempo.
Sin embargo, no es una cosa intelectualmente desafiante, requiere mucha más paciencia y persistencia que inteligencia.
No lo recomendaría si hubiera alguna otra opción, es solo un ejercicio tedioso al sustituir números por palabras más legibles en lenguaje ensamblador.

Sí, si quieres escribir un virus, a menudo necesitas parchear un poco de código binario existente. O si desea deshacer el trabajo de un virus, a menudo necesita deshacer un parche binario.

En los viejos tiempos solíamos parchear programas distribuyendo algunas palabras de código de parche. Cuando no había Internet, era más fácil enviar una CARTA a alguien por correo con las instrucciones:

OBTENER SYS FORT
.ODT
3270/4223 7000
3271/4715 7300
^ C
.SAVE SYS FORT
.

——

Eso pondría en un NOOP sobre una llamada a una función local
y luego reemplace una llamada a una función remota con “CLA CLL”.

Hoy nos limitamos a poner el código parcheado, que podría tener una longitud de muchos megabytes, pero sin sudor.

Recuerdo que hace años, cuando se lanzaron los microcomputadores Sinclair ZX Spectrum, no había ensambladores para ellos. Se podían programar en BASIC, pero en un giro sorprendente, el manual del usuario incluía una tabla con todos los códigos ASCII y tenía una columna con el código de operación de código de máquina equivalente para cada valor. Acabé de conseguir un manual de Intel 8080 y 8085 –
El Spectrum usó un procesador Z80A, que era básicamente una versión 8080 extendida.

Pasé muchas noches programando para el Spectrum. Primero tuvo que escribir su programa en forma de ensamblador y luego descubrió los códigos numéricos reales para cada instrucción (¡tampoco el hexadecimal!). Luego ingresó a un programa BÁSICO en el espectro que cobra los valores en la ubicación de memoria deseada y luego, ¡primero guardó este programa en cinta! Luego, podría saltar al punto de inicio en la memoria y su código se ejecutaría (y, a menudo, bloquearía la computadora; de ahí el importante ahorro antes de ejecutar el paso). ¡Lo primero que hice fue escribir mi propio desensamblador Z80A!

Fue muy divertido en ese entonces, ¡pero no me gustaría hacer nada de eso por trabajo!

Sí. Yo si. El problema que tuve en 1975 fue que cuando un RCA 70/45 se estrellaba, los operadores se asustaban y no revisaban el panel frontal principal para asegurarse de que no se había configurado un botón (interruptor) crítico. Si lo fuera, el mazo de cartas de volcado no se cargaría y no se podría tomar un volcado de núcleo. Entonces, escribí una tarjeta de arranque de 112 bytes que se cargaría primero, apagaría el interruptor y cargaría la primera tarjeta de la cubierta de volcado sobre sí misma.

Tenga en cuenta que las tarjetas perforadas tenían una longitud de 80 bytes. Básicamente tuve que meter 14 galones de agua en un sombrero de 10 galones. Esto requería no solo el código de la máquina, sino la capacidad de estructurarlo de modo que el código se superpusiera de tal manera que se pudieran volver a ejecutar las instrucciones para realizar la tarea.

Utilicé tarjetas de color ROJO para esta (primera) tarjeta de inicio para que pudiera saber inmediatamente si los operadores habían usado mi sistema en sus cubiertas de volcado. Esto aseguró que la plataforma de volcado funcionaría CADA VEZ y obtendría un buen volcado de núcleo para el análisis.

PD. Los sistemas de la serie RCA 70 utilizan IBM BAL. De hecho, pasé una entrevista de trabajo cuando el entrevistador me pidió que explicara la operación precisa y el uso de la instrucción BXLE. (Era uno de mis favoritos y lo pasé con mucho éxito.)