Articulo de referencia

Código automodificable

En informática , el código automodificable ( SMC o SMoC ) es aquel que altera sus propias instrucciones durante su ejecución , generalmente para reducir la longitud de la ruta d...

En informática , el código automodificable ( SMC o SMoC ) es aquel que altera sus propias instrucciones durante su ejecución , generalmente para reducir la longitud de la ruta de instrucciones y mejorar el rendimiento , o simplemente para reducir la repetición de código similar , simplificando así el mantenimiento . El término se aplica normalmente solo al código donde la automodificación es intencional, no a situaciones en las que el código se modifica accidentalmente debido a un error como un desbordamiento de búfer .

El código automodificable puede implicar la sobrescritura de instrucciones existentes o la generación de código nuevo en tiempo de ejecución y la transferencia del control a ese código.

La automodificación puede utilizarse como alternativa al método de "establecimiento de indicadores" y a la bifurcación condicional del programa, que se utiliza principalmente para reducir el número de veces que es necesario comprobar una condición.

Este método se utiliza con frecuencia para invocar condicionalmente código de prueba/depuración sin requerir una sobrecarga computacional adicional en cada ciclo de entrada/salida .

Las modificaciones pueden realizarse:

  • solo durante la inicialización , en función de los parámetros de entrada (cuando el proceso se describe más comúnmente como " configuración " de software y es algo análogo, en términos de hardware, a la configuración de puentes para placas de circuitos impresos ). La alteración de los punteros de entrada del programa es un método indirecto equivalente de automodificación, pero requiere la coexistencia de una o más rutas de instrucciones alternativas, lo que aumenta el tamaño del programa .
  • a lo largo de la ejecución ("sobre la marcha") – en función de los estados particulares del programa que se hayan alcanzado durante la ejecución

En ambos casos, las modificaciones pueden realizarse directamente en las propias instrucciones del código máquina , superponiendo nuevas instrucciones sobre las existentes (por ejemplo, cambiando una comparación y un salto a un salto incondicional o, alternativamente, a una NOP ).

En la arquitectura IBM System/360 y sus sucesoras hasta z/Architecture , una instrucción EXECUTE (EX) superpone lógicamente  el segundo byte de su instrucción objetivo con los 8 bits de orden inferior del registro  1. Esto proporciona el efecto de automodificación, aunque la instrucción real almacenada no se altera.

Aplicación en lenguajes de bajo y alto nivel.

La automodificación se puede lograr de diversas maneras, dependiendo del lenguaje de programación y su compatibilidad con punteros y/o acceso a "motores" de compilador o intérprete dinámicos:

  • superposición de instrucciones existentes (o partes de instrucciones como código de operación, registro, indicadores o direcciones)
  • creación directa de instrucciones completas o secuencias de instrucciones en la memoria
  • creación o modificación de instrucciones de código fuente seguidas de una "mini compilación" o una interpretación dinámica (ver instrucción eval )
  • crear un programa completo de forma dinámica y luego ejecutarlo

lenguaje ensamblador

El código automodificable es bastante sencillo de implementar cuando se utiliza lenguaje ensamblador . Las instrucciones se pueden crear dinámicamente en la memoria (o bien superponerse sobre el código existente en el almacenamiento de programa no protegido), [ 1 ] en una secuencia equivalente a las que un compilador estándar puede generar como código objeto . Con los procesadores modernos, pueden existir efectos secundarios no deseados en la caché de la CPU que deben tenerse en cuenta. El método se utilizaba frecuentemente para probar condiciones de "primera vez", como en este ejemplo de ensamblador IBM/360 debidamente comentado . Utiliza la superposición de instrucciones para reducir la longitud de la ruta de instrucciones en ( N × 1) − 1 , donde N es el número de registros en el archivo (−1 es la sobrecarga para realizar la superposición).

¿SUBRTN NOP ABRIÓ AQUÍ POR PRIMERA VEZ? * El NOP es x'4700' < Dirección_de_apertura> OI SUBRTN+1,X'F0' SÍ, CAMBIAR NOP A RAMIFICACIÓN INCONDICIONAL (47F0...) ABRIR ENTRADA Y ABRIR EL ARCHIVO DE ENTRADA YA QUE ES LA PRIMERA VEZ ABIERTO. OBTENGA LA ENTRADA. EL PROCESAMIENTO NORMAL SE REANUDA AQUÍ. ...

El código alternativo podría implicar probar una "bandera" en cada iteración. La bifurcación incondicional es ligeramente más rápida que una instrucción de comparación, además de reducir la longitud total de la ruta. En sistemas operativos posteriores, para programas que residen en almacenamiento protegido , esta técnica no se podía utilizar, por lo que se cambiaba el puntero a la subrutina . El puntero residía en almacenamiento dinámico y podía modificarse a voluntad después de la primera pasada para evitar la OPEN(tener que cargar primero un puntero en lugar de una bifurcación directa y enlazar con la subrutina añadiría N instrucciones a la longitud de la ruta  , pero habría una reducción correspondiente de N para la bifurcación incondicional que ya no sería necesaria).

A continuación se muestra un ejemplo en lenguaje ensamblador Zilog Z80 . El código incrementa el registro Ben el rango [0,  5]. La CPinstrucción de comparación se modifica en cada iteración del bucle.

;========== ORG 0H CALL FUNC00 HALT ;========== FUNC00: LD A , 6 LD HL , label01 + 1 LD B ,( HL ) label00: INC B LD ( HL ), B label01: CP $ 0 JP NZ , label00 RET ;==========

En ocasiones, se utiliza código automodificable para superar las limitaciones del conjunto de instrucciones de una máquina. Por ejemplo, en el conjunto de instrucciones del Intel 8080 , no es posible introducir un byte desde un puerto de entrada especificado en un registro. El puerto de entrada se codifica estáticamente en la propia instrucción, como el segundo byte de una instrucción de dos bytes. Mediante código automodificable, es posible almacenar el contenido de un registro en el segundo byte de la instrucción y, a continuación, ejecutar la instrucción modificada para lograr el efecto deseado.

Lenguajes de alto nivel

Algunos lenguajes compilados permiten explícitamente el código automodificable. Por ejemplo, el ALTERverbo en COBOL puede implementarse como una instrucción de salto que se modifica durante la ejecución. [ 2 ] Algunas técnicas de programación por lotes implican el uso de código automodificable. Clipper y SPITBOL también proporcionan herramientas para la automodificación explícita. El compilador Algol en los sistemas B6700 ofrecía una interfaz al sistema operativo mediante la cual el código en ejecución podía pasar una cadena de texto o un archivo de disco con nombre al compilador Algol y luego podía invocar la nueva versión de un procedimiento.

En los lenguajes interpretados, el "código máquina" es el texto fuente y puede ser susceptible de edición sobre la marcha: en SNOBOL, las instrucciones fuente que se ejecutan son elementos de una matriz de texto. Otros lenguajes, como Perl y Python , permiten que los programas creen código nuevo en tiempo de ejecución y lo ejecuten mediante una función `eval` , pero no permiten modificar el código existente. La ilusión de modificación (aunque en realidad no se sobrescribe ningún código máquina) se logra modificando punteros a funciones, como en este ejemplo de JavaScript:

var f = function ( x ) { return x + 1 };// Asignar una nueva definición a f: f = new Function ( 'x' , 'return x + 2' );

Las macros de Lisp también permiten la generación de código en tiempo de ejecución sin necesidad de analizar una cadena que contenga código de programa.

El lenguaje de programación Push es un sistema de programación genética diseñado específicamente para crear programas automodificables. Si bien no es un lenguaje de alto nivel, tampoco es tan de bajo nivel como el lenguaje ensamblador. [ 3 ]

Modificación de compuestos

Antes de la llegada de las ventanas múltiples, los sistemas de línea de comandos podían ofrecer un sistema de menú que implicaba la modificación de un script de comandos en ejecución. Supongamos que un archivo por lotes de MS-DOS MENU.BAT contiene lo siguiente: [ 4 ] [ nb 1 ]

 :comenzar SHOWMENU.EXE

Al iniciar MENU.BAT desde la línea de comandos, SHOWMENU presenta un menú en pantalla, con posible información de ayuda, ejemplos de uso, etc. Finalmente, el usuario realiza una selección que requiere que se ejecute un comando SOMENAME : SHOWMENU sale después de reescribir el archivo MENU.BAT para contener

 :comenzar SHOWMENU.EXE LLAMAR ALGÚN NOMBRE.BAT IR A INICIO

Dado que el intérprete de comandos no compila un archivo de script para luego ejecutarlo, ni lee el archivo completo en la memoria antes de comenzar la ejecución, ni depende del contenido de un búfer de registro, cuando SHOWMENU finaliza, el intérprete de comandos encuentra un nuevo comando para ejecutar (que consiste en invocar el archivo de script SOMENAME , en una ubicación de directorio y mediante un protocolo conocido por SHOWMENU). Una vez que ese comando se completa, regresa al inicio del archivo de script y reactiva SHOWMENU para la siguiente selección. Si la opción del menú es salir, el archivo se reescribirá a su estado original. Aunque este estado inicial no tiene utilidad para la etiqueta, esta, o una cantidad equivalente de texto, es necesaria, porque el intérprete de comandos recuerda la posición de bytes del siguiente comando cuando debe iniciarlo; por lo tanto, el archivo reescrito debe mantener la alineación para que el punto de inicio del siguiente comando sea realmente el inicio del siguiente comando.

Además de la comodidad de un sistema de menús (y posibles funciones auxiliares), este esquema implica que el sistema SHOWMENU.EXE no está en memoria cuando se activa el comando seleccionado, una ventaja significativa cuando la memoria es limitada. [ 4 ] [ 5 ]

Tablas de control

Los intérpretes de tablas de control pueden considerarse, en cierto sentido, "automodificados" por valores de datos extraídos de las entradas de la tabla (en lugar de codificados manualmente en declaraciones condicionales de la forma IF inputx = 'yyy').

Programas del canal

Algunos métodos de acceso de IBM utilizaban tradicionalmente programas de canal automodificables , en los que un valor, como una dirección de disco, se leía en un área a la que hacía referencia un programa de canal, donde un comando de canal posterior lo utilizaba para acceder al disco.

Historia

El IBM SSEC , presentado en enero de 1948, tenía la capacidad de modificar sus instrucciones o tratarlas exactamente como datos. Sin embargo, esta capacidad rara vez se utilizó en la práctica. [ 6 ] En los inicios de la informática, el código automodificable se utilizaba a menudo para reducir el uso de memoria limitada, mejorar el rendimiento o ambas cosas. También se utilizaba a veces para implementar llamadas y retornos de subrutinas cuando el conjunto de instrucciones solo proporcionaba instrucciones simples de bifurcación o salto para variar el flujo de control . [ 7 ] [ 8 ] Este uso sigue siendo relevante en ciertas arquitecturas ultra- RISC , al menos teóricamente; véase, por ejemplo, la computadora de un conjunto de instrucciones . La arquitectura MIX de Donald Knuth también utilizaba código automodificable para implementar llamadas a subrutinas. [ 9 ]

Uso

El código automodificable puede utilizarse para diversos fines:

  • Optimización semiautomática de un bucle dependiente del estado.
  • Optimización dinámica del código in situ para la velocidad en función del entorno de carga. [ 10 ] [ 11 ] [ nb 2 ]
  • Generación de código en tiempo de ejecución , o especialización de un algoritmo en tiempo de ejecución o de carga (lo cual es popular, por ejemplo, en el ámbito de los gráficos en tiempo real), como una utilidad de ordenación general  : preparar el código para realizar la comparación de claves descrita en una invocación específica.
  • Alteración del estado en línea de un objeto o simulación de la construcción de alto nivel de cierres .
  • La modificación de la dirección de llamada de la subrutina ( puntero ), que normalmente se realiza en el momento de la carga/inicialización de las bibliotecas dinámicas , o bien en cada invocación, modifica las referencias internas de la subrutina a sus parámetros para utilizar sus direcciones reales (es decir, automodificación indirecta).
  • Sistemas de computación evolutiva como la neuroevolución , la programación genética y otros algoritmos evolutivos .
  • Ocultar código para evitar la ingeniería inversa (mediante el uso de un desensamblador o depurador ) o para eludir la detección por parte de software antivirus/spyware y similares.
  • Llenar toda la memoria (en algunas arquitecturas) con un patrón continuo de códigos de operación repetitivos , para borrar todos los programas y datos, o para someter a prueba el hardware o realizar pruebas de RAM . [ 12 ]
  • Comprimir código para descomprimirlo y ejecutarlo en tiempo de ejecución, por ejemplo, cuando la memoria o el espacio en disco son limitados. [ 10 ] [ 11 ]
  • Algunos conjuntos de instrucciones muy limitados no dejan otra opción que usar código automodificable para realizar ciertas funciones. Por ejemplo, una máquina con un conjunto de instrucciones único (OISC) que solo usa la instrucción de resta y salto si es negativo no puede hacer una copia indirecta (algo así como el equivalente *a = **ben el lenguaje C ) sin usar código automodificable.
  • Arranque . Los primeros microordenadores solían utilizar código automodificable en sus gestores de arranque. Dado que el gestor de arranque se activaba mediante el panel frontal cada vez que se encendía, no importaba si se modificaba a sí mismo. Sin embargo, incluso hoy en día, muchos gestores de arranque se reubican automáticamente , e incluso algunos se automodifican. [ nb 3 ]
  • Modificación de las instrucciones para la tolerancia a fallos. [ 13 ]

Optimización de un bucle dependiente del estado

Ejemplo de pseudocódigo :

repetir N veces { si ESTADO es 1 aumentar A en uno demás disminuir A en uno hacer algo con A }

En este caso, el código automodificable consistiría simplemente en reescribir el bucle de esta manera:

repetir N veces { incrementar A en uno hacer algo con A cuando el ESTADO tiene que cambiar { Reemplace el código de operación "increase" anterior con el código de operación para disminuir, o viceversa. } }

Tenga en cuenta que el reemplazo de dos estados del código de operación se puede escribir fácilmente como "xor var en la dirección con el valor opcodeOf(Inc) xor opcodeOf(dec)".

La elección de esta solución debe depender del valor de N y de la frecuencia de cambio de estado.

Especialización

Supongamos que se va a calcular un conjunto de estadísticas, como la media, los extremos, la ubicación de los extremos, la desviación estándar, etc., para un conjunto de datos grande. En una situación general, podría existir la opción de asociar ponderaciones a los datos, de modo que cada x i se asocie con un w i , y en lugar de comprobar la presencia de ponderaciones en cada valor de índice, podría haber dos versiones del cálculo, una para usar con ponderaciones y otra sin ellas, con una comprobación al inicio. Ahora bien, consideremos otra opción: que cada valor tenga asociado un valor booleano para indicar si se debe omitir o no. Esto podría gestionarse generando cuatro lotes de código, uno para cada permutación, lo que resultaría en un aumento de tamaño del código. Alternativamente, los arrays de ponderación y de omisión podrían fusionarse en un array temporal (con ponderaciones cero para los valores que se omitan), a costa de un mayor procesamiento y aún así se produciría un aumento de tamaño del código. Sin embargo, modificando el código, se podría añadir a la plantilla para calcular las estadísticas, según corresponda, el código para omitir valores no deseados y para aplicar ponderaciones. No se repetirían las pruebas de las opciones y se accedería al array de datos una sola vez, al igual que a los arrays de pesos y de saltos, si estuvieran involucrados.

Utilizar como camuflaje

El código automodificable es más complejo de analizar que el código estándar y, por lo tanto, puede utilizarse como protección contra la ingeniería inversa y la piratería informática . Este tipo de código se empleaba para ocultar las instrucciones de protección contra copias en programas basados ​​en disco de la década de 1980 para sistemas como los compatibles con IBM PC y Apple II . Por ejemplo, en un IBM  PC, la instrucción de acceso a la unidad de disqueteint 0x13 no aparecía en la imagen del programa ejecutable, sino que se escribía en la imagen de memoria del ejecutable una vez que el programa comenzaba a ejecutarse.

El código automodificable también lo utilizan a veces programas que no desean revelar su presencia, como los virus informáticos y algunos shellcodes . Los virus y shellcodes que utilizan código automodificable suelen hacerlo en combinación con código polimórfico . La modificación de un fragmento de código en ejecución también se utiliza en ciertos ataques, como los desbordamientos de búfer .

Sistemas de aprendizaje automático autorreferenciales

Los sistemas tradicionales de aprendizaje automático tienen un algoritmo de aprendizaje fijo y preprogramado para ajustar sus parámetros . Sin embargo, desde la década de 1980, Jürgen Schmidhuber ha publicado varios sistemas auto-modificables con la capacidad de cambiar su propio algoritmo de aprendizaje. Estos sistemas evitan el peligro de auto-reescrituras catastróficas al garantizar que las auto-modificaciones solo sobrevivan si son útiles según una función de aptitud , error o recompensa definida por el usuario . [ 14 ]

Sistemas operativos

El kernel de Linux hace un uso notablemente amplio de código automodificable; lo hace para poder distribuir una única imagen binaria para cada arquitectura principal (por ejemplo, IA-32 , x86-64 , ARM de 32 bits , ARM64 ...) mientras adapta el código del kernel en memoria durante el arranque dependiendo del modelo de CPU específico detectado, por ejemplo, para poder aprovechar nuevas instrucciones de CPU o para solucionar errores de hardware. [ 15 ] [ 16 ] En menor medida, el kernel de DR-DOS también optimiza secciones críticas de velocidad de sí mismo en tiempo de carga dependiendo de la generación del procesador subyacente. [ 10 ] [ 11 ] [ nb 2 ]

De todos modos, a un nivel meta , los programas aún pueden modificar su propio comportamiento cambiando datos almacenados en otro lugar (véase metaprogramación ) o mediante el uso de polimorfismo .

Núcleo de síntesis de Massalin

El núcleo Synthesis presentado en la tesis doctoral de Alexia Massalin [ 17 ] [ 18 ] es un pequeño núcleo Unix que adopta un enfoque estructurado , o incluso orientado a objetos , para el código automodificable, donde el código se crea para quajects individuales , como los descriptores de archivo. La generación de código para tareas específicas permite al núcleo Synthesis (como lo haría un intérprete JIT) aplicar una serie de optimizaciones, como el plegado de constantes o la eliminación de subexpresiones comunes .

El núcleo Synthesis era muy rápido, pero estaba escrito completamente en lenguaje ensamblador. La consiguiente falta de portabilidad ha impedido que las ideas de optimización de Massalin se incorporen a ningún núcleo de producción. Sin embargo, la estructura de las técnicas sugiere que podrían integrarse en un lenguaje de alto nivel , aunque más complejo que los lenguajes de nivel medio existentes. Dicho lenguaje y compilador permitirían el desarrollo de sistemas operativos y aplicaciones más rápidos.

Paul Haeberli y Bruce Karsh se han opuesto a la "marginalización" del código automodificable y a la optimización en general, en favor de la reducción de los costos de desarrollo. [ 19 ]

Interacción entre la caché y el código automodificable

En arquitecturas sin caché de datos e instrucciones acopladas (por ejemplo, algunos núcleos SPARC , ARM y MIPS ), la sincronización de la caché debe ser realizada explícitamente por el código que realiza la modificación (vaciar la caché de datos e invalidar la caché de instrucciones para el área de memoria modificada).

En algunos casos, las secciones cortas de código automodificable se ejecutan más lentamente en los procesadores modernos. Esto se debe a que un procesador moderno suele intentar mantener bloques de código en su memoria caché. Cada vez que el programa reescribe una parte de sí mismo, la parte reescrita debe cargarse de nuevo en la caché, lo que provoca un ligero retraso si el fragmento de código modificado comparte la misma línea de caché con el código que lo modifica, como ocurre cuando la dirección de memoria modificada se encuentra a pocos bytes de la del código que lo modifica.

El problema de la invalidación de la caché en los procesadores modernos generalmente significa que el código automodificable seguirá siendo más rápido solo cuando la modificación ocurra con poca frecuencia, como en el caso de un cambio de estado dentro de un bucle interno.

La mayoría de los procesadores modernos cargan el código máquina antes de ejecutarlo, lo que significa que si se modifica una instrucción demasiado cercana al puntero de instrucción , el procesador no lo detectará y ejecutará el código tal como estaba antes de la modificación. Véase la cola de entrada de precarga (PIQ). Los procesadores de PC deben gestionar correctamente el código automodificable por motivos de compatibilidad con versiones anteriores, pero su eficiencia al hacerlo es considerable.

Problemas de seguridad

Debido a las implicaciones de seguridad que conlleva el código automodificable, todos los principales sistemas operativos se esfuerzan por eliminar dichas vulnerabilidades a medida que se descubren. La preocupación no radica en que los programas se modifiquen intencionalmente, sino en que puedan ser alterados maliciosamente mediante una vulnerabilidad .

Un mecanismo para prevenir la modificación maliciosa del código es una característica del sistema operativo llamada W^X (por "write xor execute"). Este mecanismo impide que un programa haga que una página de memoria sea tanto escribible como ejecutable. Algunos sistemas impiden que una página escribible se convierta en ejecutable, incluso si se elimina el permiso de escritura. Otros sistemas proporcionan una especie de " puerta trasera ", que permite que múltiples asignaciones de una página de memoria tengan permisos diferentes. Una forma relativamente portátil de eludir W^X es crear un archivo con todos los permisos y luego asignarlo a la memoria dos veces. En Linux, se puede usar una bandera de memoria compartida SysV no documentada para obtener memoria compartida ejecutable sin necesidad de crear un archivo.

Ventajas

Desventajas

El código automodificable es más difícil de leer y mantener porque las instrucciones en el listado del programa fuente no son necesariamente las que se ejecutarán. La automodificación que consiste en la sustitución de punteros a funciones podría no ser tan críptica si queda claro que los nombres de las funciones que se van a llamar son marcadores de posición para funciones que se identificarán posteriormente.

El código automodificable se puede reescribir como código que prueba una bandera y se ramifica a secuencias alternativas en función del resultado de la prueba, pero el código automodificable generalmente se ejecuta más rápido.

El código que se automodifica entra en conflicto con la autenticación del código y puede requerir excepciones a las políticas que exigen que todo el código que se ejecuta en un sistema esté firmado.

El código modificado debe almacenarse por separado de su forma original, lo que entra en conflicto con las soluciones de gestión de memoria que normalmente descartan el código en la RAM y lo recargan desde el archivo ejecutable según sea necesario.

En los procesadores modernos con segmentación de instrucciones , el código que se modifica con frecuencia puede ejecutarse más lentamente si modifica instrucciones que el procesador ya ha leído de la memoria y almacenado en la segmentación. En algunos de estos procesadores, la única forma de garantizar que las instrucciones modificadas se ejecuten correctamente es vaciar la segmentación y releer muchas instrucciones.

En algunos entornos, como por ejemplo los siguientes, no se puede utilizar código automodificable:

Véase también

Notas

  1. Las versiones posteriores de DOS (desde la versión 6.0) introdujeron elcomando externo CHOICE (en DR-DOS también el comando interno yla directiva CONFIG.SYS SWITCH ), por lo que, para esta aplicación de ejemplo específica de un sistema de menús, ya no era necesario hacer referencia a trabajos por lotes automodificables; sin embargo, para otras aplicaciones siguió siendo una solución viable.
  2. 1 2 Por ejemplo, al ejecutarse enprocesadores 386 o superiores, las actualizaciones posteriores de Novell DOS 7 , así como DR-DOS 7.02 y versiones posteriores, reemplazarán dinámicamente algunas secuencias predeterminadas deREP MOVSWinstrucciones de 16 bits ("copiar palabras") en la imagen de tiempo de ejecución del kernel por instrucciones de 32 bitsREP MOVSD("copiar palabras dobles") al copiar datos de una ubicación de memoria a otra (y la mitad del número de repeticiones necesarias) para acelerar las transferencias de datos del disco. Se tienen en cuenta los casos límite, como los recuentos impares. [ 10 ] [ 11 ]
  3. Por ejemplo, los MBR y sectores de arranque de DR-DOS (que también contienen la tabla de particiones y el bloque de parámetros del BIOS , dejando menos de 446 y 423 bytes respectivamente para el código) tradicionalmente podían localizar el archivo de arranque en el sistema de archivos FAT12 o FAT16 por sí mismos y cargarlo en la memoria como un todo, a diferencia de sus contrapartes de MS-DOS / PC DOS , que en cambio dependían de que los archivos del sistema ocuparan las dos primeras entradas de directorio en el sistema de archivos y los tres primeros sectores de IBMBIO.COM se almacenaran al comienzo del área de datos en sectores contiguos que contenían un cargador secundario para cargar el resto del archivo en la memoria (lo que requería que SYS se encargara de todas estas condiciones). Cuandose agregó la compatibilidad con FAT32 y LBA , Microsoft incluso optó por requerir instrucciones 386 y dividir el código de arranque en dos sectores por razones de tamaño, lo cual no era una opción para DR-DOS, ya que habría roto la retrocompatibilidad y la compatibilidad cruzada con otros sistemas operativos en escenarios de arranque múltiple y carga en cadena , así como con PC más antiguos . En cambio, los sectores de arranque de DR-DOS 7.07 recurrieron a código automodificable, programación a nivel de código de operación en lenguaje máquina , utilización controlada de efectos secundarios (documentados) , superposición de datos/código de varios nivelesy técnicas de plegado algorítmico para aún así acomodar todo en un sector físico de solo 512 bytes sin renunciar a ninguna de sus funcionalidades extendidas.

Referencias

  1. "HP 9100A/B" . MoHPC - Museo de Calculadoras HP . 1998. Memoria de datos y programa superpuesta / Código automodificable. Archivado del original el 23/09/2023 . Consultado el 23/09/2023 .
  2. "La instrucción ALTER". Referencia del lenguaje COBOL . Micro Focus .
  3. Spector, Lee. "Computación evolutiva con Push: Push, PushGP y Pushpop" . Recuperado el 25 de abril de 2023 .
  4. 1 2 Fosdal, Lars (2001). "Archivo por lotes automodificable" . Archivado del original el 21 de abril de 2008.
  5. ^ Paul, Matthias R. (13 de octubre de 1996) [21 de agosto de 1996, 1994]. Konzepte zur Unterstützung administrador Aufgaben en PC-Netzen y deren Realisierung für eine konkrete Novell-LAN-Umgebung unter Benutzung der Batchsprache von DOS . 3.11 (en alemán). Aquisgrán, Alemania: Lehrstuhl für Kommunikationsnetze ( ComNets ) & Institut für Kunststoffverarbeitung (IKV), RWTH. págs. 51, 71 y 72. (110+3 páginas, disquete) (Nota: Diseño e implementación de un sistema de gestión distribuida modular controlado centralmente para la configuración automática de clientes y el despliegue de software con mecanismo de actualización autorreparable en entornos LAN , basado en trabajos por lotes autorreplicantes y automodificables indirectamente con un consumo de memoria nulo, en lugar de requerir software de gestión residente en los clientes).
  6. Bashe, Charles J.; Buchholz, Werner ; Hawkins, George V.; Ingram, J. James; Rochester, Nathaniel (septiembre de 1981). "La arquitectura de las primeras computadoras de IBM" (PDF) . IBM Journal of Research and Development . 25 (5): 363–376 . CiteSeerX 10.1.1.93.8952 . doi : 10.1147/rd.255.0363 . ISSN 0018-8646 . Recuperado el 25 de abril de 2023. pág. 365: El SSEC fue la primera computadora operativa capaz de tratar sus propias instrucciones almacenadas exactamente como datos, modificándolas y actuando sobre el resultado.   
  7. Miller, Barton P. (30 de octubre de 2006). "Parcheo de código binario: un arte antiguo perfeccionado para el siglo XXI" . Serie de conferencias distinguidas de ciencias de la computación de Triangle - Seminarios 2006-2007. Universidad Estatal de Carolina del Norte , Departamento de Ciencias de la Computación . Recuperado el 25 de abril de 2023 .
  8. Wenzl, Matthias; Merzdovnik, Georg; Ullrich, Johanna; Weippl, Edgar R. (junio de 2019) [febrero de 2019, noviembre de 2018, mayo de 2018]. "Del hack a la técnica elaborada: una revisión sobre la reescritura binaria" (PDF) . ACM Computing Surveys . 52 (3). Viena, Austria: 49:1–49:36 [49:1]. doi : 10.1145/3316415 . S2CID 195357367. Artículo 49. Archivado (PDF) del original el 15 de enero de 2021. Recuperado el 28 de noviembre de 2021. p. 49:1: […] Originalmente, la reescritura binaria fue motivada por la necesidad de cambiar partes de un programa durante su ejecución (por ejemplo, la aplicación de parches en tiempo de ejecución en el PDP-1 en la década de 1960) […]  (36 páginas)
  9. Knuth, Donald Ervin (2009) [1997]. "MMIX 2009: una computadora RISC para el tercer milenio" . Archivado del original el 27 de noviembre de 2021. Consultado el 28 de noviembre de 2021 .
  10. 1 2 3 "Caldera OpenDOS Machine Readable Source Kit (MRS) 7.01" . Caldera, Inc. 1997-05-01. Archivado del original el 2021-08-07 . Recuperado el 2022-01-02 .
  11. 1 2 3 Paul, Matthias R. (1997-10-02). "Caldera OpenDOS 7.01/7.02 Update Alpha 3 IBMBIO.COM README.TXT" . Archivado del original el 4 de octubre de 2003. Recuperado el 29 de marzo de 2009 .
  12. Wilkinson, William "Bill" Albert (2003) [1996, 1984]. "El gusano H89: Prueba de memoria del H89" . Página de Bill Wilkinson en Heath Company . Archivado del original el 13 de diciembre de 2021. Recuperado el 13 de diciembre de 2021. [ …] Además de obtener una instrucción, el Z80 usa la mitad del ciclo para actualizar la RAM dinámica . […] dado que el Z80 debe pasar la mitad de cada ciclo de obtención de instrucciones realizando otras tareas, no tiene tanto tiempo para obtener un byte de instrucción como para obtener un byte de datos. Si uno de los chips de RAM en la ubicación de memoria a la que se accede es un poco lento, el Z80 puede obtener el patrón de bits incorrecto cuando obtiene una instrucción, pero obtiene el correcto cuando lee datos. […] la prueba de memoria integrada no detectará este tipo de problema […] es estrictamente una prueba de lectura/escritura de datos. Durante la prueba, todas las instrucciones se obtienen de la ROM , no de la RAM […] lo que hace que el H89 pase la prueba de memoria, pero siga funcionando de forma errática en algunos programas. […] Este es un programa que prueba la memoria reubicándose a través de la RAM. Al hacerlo, la CPU imprime la dirección actual del programa en el CRT y luego obtiene la instrucción en esa dirección. Si los circuitos integrados de la RAM están bien en esa dirección, la CPU reubica el programa de prueba en la siguiente ubicación de memoria, imprime la nueva dirección y repite el procedimiento. Pero, si uno de los circuitos integrados de la RAM es lo suficientemente lento como para devolver un patrón de bits incorrecto, la CPU malinterpretará la instrucción y se comportará de forma impredecible. Sin embargo, es probable que la pantalla se bloquee mostrando la dirección del circuito integrado defectuoso. Esto reduce el problema a ocho circuitos integrados, lo que supone una mejora con respecto a tener que comprobar hasta 32. […] El […] programa realizará una prueba de gusano empujando una instrucción RST 7 (REINICIO 7) desde el extremo inferior de la memoria hasta la última dirección que funciona. El resto del programa permanece estático y se encarga de mostrar la ubicación actual del comando RST 7 y su reubicación . Cabe mencionar que el programa se denomina prueba de gusano porque, a medida que la instrucción RST 7 asciende por la memoria, deja tras de sí un rastro de NOPs (NO OPERATION). […]
  13. Ortiz, Carlos Enrique (29-08-2015) [18-08-2007]. "Sobre el código automodificable y el sistema operativo del transbordador espacial" . Recuperado el 25-04-2023 .
  14. Publicaciones de Jürgen Schmidhuber sobre código automodificable para sistemas de aprendizaje automático autorreferenciales.
  15. Paltsev, Evgeniy (30 de enero de 2020). "Código automodificable en el kernel de Linux: qué, dónde y cómo" . Recuperado el 27 de noviembre de 2022 .
  16. Wieczorkiewicz, Pawel. "Alternativas al kernel de Linux" . Consultado el 27 de noviembre de 2022 .
  17. Pu, Calton ; Massalin, Henry ; Ioannidis, John (1992). Síntesis: una implementación eficiente de servicios fundamentales del sistema operativo (PDF) (tesis doctoral). Nueva York, EE. UU.: Departamento de Ciencias de la Computación, Universidad de Columbia . Número de pedido UMI GAX92-32050 . Consultado el 25 de abril de 2023 .
  18. Henson, Valerie (2008-02-20). "KHB: Synthesis: An Efficient Implementation of Fundamental Operating Systems Services" . LWN.net . Archivado del original el 17 de agosto de 2021. Consultado el 19 de mayo de 2022 .
  19. Haeberli, Paul ; Karsh, Bruce (3 de febrero de 1994). "Io Noi Boccioni - Antecedentes de la programación futurista" . Gráfica Oscura . Consultado el 25 de abril de 2023 .

Lecturas adicionales

  • Åkesson, Linus (31 de marzo de 2013). "Decodificación GCR sobre la marcha" . Archivado del original el 21 de marzo de 2017. Recuperado el 21 de marzo de 2017 .
  • Bürckert, Christian Félix (20 de marzo de 2012). Eine Bibliothek für Selbstmodifikationen zur Laufzeit in Java [ Una biblioteca para automodificaciones en tiempo de ejecución en Java ] (PDF) (Tesis) (en alemán). Universität des Saarlandes , Naturwissenschaftlich-Technische Fakultät I, Fachrichtung Informatik. Archivado (PDF) desde el original el 18 de agosto de 2023 . Consultado el 18 de agosto de 2023 .(80 páginas)
  • Uso de código automodificable en Linux
  • Código C automodificable
  • Código automodificable certificado