stringtranslate.com

Lenguaje ensamblador

En programación informática , el lenguaje ensamblador (alternativamente lenguaje ensamblador [1] o código de máquina simbólico ), [2] [3] [4] a menudo denominado simplemente ensamblaje y comúnmente abreviado como ASM o asm , es cualquier lenguaje de programación de bajo nivel con una correspondencia muy fuerte entre las instrucciones en el lenguaje y las instrucciones del código de máquina de la arquitectura . [5] El lenguaje ensamblador generalmente tiene una declaración por instrucción de máquina (1:1), pero las constantes, los comentarios , las directivas de ensamblador , [6] las etiquetas simbólicas de, por ejemplo, ubicaciones de memoria , registros y macros [7] [1] generalmente también son compatibles.

El primer código ensamblador en el que se utiliza un lenguaje para representar instrucciones de código máquina se encuentra en el trabajo de 1947 de Kathleen y Andrew Donald Booth , Coding for ARC . [8] El código ensamblador se convierte en código máquina ejecutable mediante un programa de utilidad denominado ensamblador . El término "ensamblador" se atribuye generalmente a Wilkes , Wheeler y Gill en su libro de 1951 The Preparation of Programs for an Electronic Digital Computer , [9] quienes, sin embargo, utilizaron el término para significar "un programa que ensambla otro programa que consta de varias secciones en un solo programa". [10] El proceso de conversión se denomina ensamblaje , como ensamblar el código fuente . El paso computacional cuando un ensamblador está procesando un programa se llama tiempo de ensamblaje .

Dado que el ensamblaje depende de las instrucciones del código de máquina, cada lenguaje ensamblador [nb 1] es específico para una arquitectura informática particular . [11] [12] [13]

A veces hay más de un ensamblador para la misma arquitectura, y a veces un ensamblador es específico para un sistema operativo o para sistemas operativos particulares. La mayoría de los lenguajes ensambladores no proporcionan una sintaxis específica para las llamadas al sistema operativo, y la mayoría de los lenguajes ensambladores se pueden usar universalmente con cualquier sistema operativo, [nb 2] ya que el lenguaje proporciona acceso a todas las capacidades reales del procesador , sobre las que descansan en última instancia todos los mecanismos de llamada al sistema . A diferencia de los lenguajes ensambladores, la mayoría de los lenguajes de programación de alto nivel son generalmente portables a través de múltiples arquitecturas pero requieren interpretación o compilación , tareas mucho más complicadas que el ensamblaje.

En las primeras décadas de la informática, era habitual que tanto la programación de sistemas como la programación de aplicaciones se realizaran íntegramente en lenguaje ensamblador. Si bien sigue siendo irremplazable para algunos propósitos, la mayor parte de la programación ahora se realiza en lenguajes compilados e interpretados de alto nivel. En " No Silver Bullet ", Fred Brooks resumió los efectos del abandono de la programación en lenguaje ensamblador: "Seguramente el golpe más poderoso para la productividad, la confiabilidad y la simplicidad del software ha sido el uso progresivo de lenguajes de alto nivel para la programación. La mayoría de los observadores atribuyen a ese desarrollo al menos un factor de cinco en la productividad y las ganancias concomitantes en confiabilidad, simplicidad y comprensibilidad". [14]

En la actualidad, es habitual utilizar pequeñas cantidades de código en lenguaje ensamblador en sistemas más grandes implementados en un lenguaje de alto nivel, por razones de rendimiento o para interactuar directamente con el hardware de formas que no son compatibles con el lenguaje de alto nivel. Por ejemplo, poco menos del 2% del código fuente de la versión 4.9 del núcleo de Linux está escrito en lenguaje ensamblador ; más del 97% está escrito en C. [15]

Sintaxis del lenguaje ensamblador

El lenguaje ensamblador utiliza un mnemónico para representar, por ejemplo, cada instrucción de máquina de bajo nivel o código de operación , cada directiva , típicamente también cada registro arquitectónico , bandera , etc. Algunos de los mnemónicos pueden estar integrados y otros definidos por el usuario. Muchas operaciones requieren uno o más operandos para formar una instrucción completa. La mayoría de los ensambladores permiten constantes con nombre, registros y etiquetas para ubicaciones de programa y memoria, y pueden calcular expresiones para operandos. De este modo, los programadores se liberan de cálculos repetitivos tediosos y los programas ensambladores son mucho más legibles que el código máquina. Dependiendo de la arquitectura, estos elementos también pueden combinarse para instrucciones específicas o modos de direccionamiento utilizando desplazamientos u otros datos, así como direcciones fijas. Muchos ensambladores ofrecen mecanismos adicionales para facilitar el desarrollo del programa, controlar el proceso de ensamblaje y ayudar a la depuración .

Algunos están orientados a columnas, con campos específicos en columnas específicas; esto era muy común en las máquinas que usaban tarjetas perforadas en los años 1950 y principios de los 1960. Algunos ensambladores tienen una sintaxis de formato libre, con campos separados por delimitadores, p. ej., puntuación, espacio en blanco . Algunos ensambladores son híbridos, con, p. ej., etiquetas, en una columna específica y otros campos separados por delimitadores; esto se volvió más común que la sintaxis orientada a columnas en los años 1960.

Terminología

Conceptos clave

Ensamblador

Un programa ensamblador crea código objeto traduciendo combinaciones de mnemotecnia y sintaxis para operaciones y modos de direccionamiento en sus equivalentes numéricos. Esta representación normalmente incluye un código de operación (" opcode ") así como otros bits de control y datos. El ensamblador también calcula expresiones constantes y resuelve nombres simbólicos para ubicaciones de memoria y otras entidades. [20] El uso de referencias simbólicas es una característica clave de los ensambladores, que ahorra cálculos tediosos y actualizaciones manuales de direcciones después de modificaciones del programa. La mayoría de los ensambladores también incluyen funciones de macro para realizar sustituciones textuales, por ejemplo, para generar secuencias cortas comunes de instrucciones como inline , en lugar de las llamadas subrutinas .

Algunos ensambladores también pueden ser capaces de realizar algunos tipos simples de optimizaciones específicas del conjunto de instrucciones . Un ejemplo concreto de esto pueden ser los ubicuos ensambladores x86 de varios proveedores. Llamados jump-sizing [ 20], la mayoría de ellos son capaces de realizar reemplazos de instrucciones de salto (saltos largos reemplazados por saltos cortos o relativos) en cualquier número de pases, a pedido. Otros pueden incluso hacer una simple reorganización o inserción de instrucciones, como algunos ensambladores para arquitecturas RISC que pueden ayudar a optimizar una programación de instrucciones sensata para explotar el pipeline de la CPU de la manera más eficiente posible. [21]

Los ensambladores han estado disponibles desde la década de 1950, como el primer paso por encima del lenguaje de máquina y antes de los lenguajes de programación de alto nivel como Fortran , Algol , COBOL y Lisp . También han existido varias clases de traductores y generadores de código semiautomáticos con propiedades similares tanto al ensamblador como a los lenguajes de alto nivel, siendo Speedcode quizás uno de los ejemplos más conocidos.

Puede haber varios ensambladores con sintaxis diferente para una CPU o arquitectura de conjunto de instrucciones en particular . Por ejemplo, una instrucción para agregar datos de memoria a un registro en un procesador de la familia x86 podría estar add eax,[ebx]en la sintaxis original de Intel , mientras que esta estaría escrita addl (%ebx),%eaxen la sintaxis de AT&T utilizada por el ensamblador GNU . A pesar de las diferentes apariencias, las diferentes formas sintácticas generalmente generan el mismo código de máquina numérico . Un solo ensamblador también puede tener diferentes modos para admitir variaciones en las formas sintácticas, así como sus interpretaciones semánticas exactas (como la sintaxis FASM , la sintaxis TASM , el modo ideal, etc., en el caso especial de la programación en ensamblador x86 ).

Número de pases

Hay dos tipos de ensambladores según la cantidad de pasadas a través de la fuente que se necesitan (cuántas veces el ensamblador lee la fuente) para producir el archivo objeto.

En ambos casos, el ensamblador debe ser capaz de determinar el tamaño de cada instrucción en los pases iniciales para calcular las direcciones de los símbolos subsiguientes. Esto significa que si el tamaño de una operación que hace referencia a un operando definido posteriormente depende del tipo o la distancia del operando, el ensamblador realizará una estimación pesimista cuando se encuentre por primera vez con la operación y, si es necesario, la rellenará con una o más instrucciones de " no operación " en un pase posterior o con la errata. En un ensamblador con optimización de mirilla , las direcciones se pueden recalcular entre pases para permitir reemplazar el código pesimista con un código adaptado a la distancia exacta desde el objetivo.

La razón original para el uso de ensambladores de una sola pasada era el tamaño de la memoria y la velocidad de ensamblaje; a menudo, una segunda pasada requeriría almacenar la tabla de símbolos en la memoria (para manejar referencias hacia adelante ), rebobinar y releer el código fuente del programa en cinta , o releer una baraja de cartas o una cinta de papel perforada . Las computadoras posteriores con memorias mucho más grandes (especialmente almacenamiento en disco), tenían el espacio para realizar todo el procesamiento necesario sin tal relectura. La ventaja del ensamblador de múltiples pasadas es que la ausencia de erratas hace que el proceso de enlace (o la carga del programa si el ensamblador produce directamente código ejecutable) sea más rápido. [22]

Ejemplo: en el siguiente fragmento de código, un ensamblador de una sola pasada podría determinar la dirección de la referencia hacia atrás BKWD al ensamblar la instrucción S2 , pero no podría determinar la dirección de la referencia hacia adelante FWD al ensamblar la instrucción de bifurcación S1 ; de hecho, FWD puede no estar definida. Un ensamblador de dos pasadas determinaría ambas direcciones en la pasada 1, por lo que se conocerían al generar el código en la pasada 2.

S1 B tracción delantera ...EQUIPO DE TRACCIÓN DELANTERA * ...Equilibrio BKWD * ...S2 B tracción trasera

Ensambladores de alto nivel

Los ensambladores de alto nivel más sofisticados proporcionan abstracciones del lenguaje como:

Consulte el diseño del lenguaje a continuación para obtener más detalles.

Lenguaje ensamblador

Un programa escrito en lenguaje ensamblador consta de una serie de instrucciones mnemotécnicas de procesador y metadeclaraciones (conocidas de diversas formas como operaciones declarativas, directivas, pseudoinstrucciones, pseudooperaciones y pseudoops), comentarios y datos. Las instrucciones en lenguaje ensamblador suelen constar de una mnemotécnica de código de operación seguida de un operando , que puede ser una lista de datos, argumentos o parámetros. [24] Algunas instrucciones pueden estar "implícitas", lo que significa que los datos sobre los que opera la instrucción están definidos implícitamente por la propia instrucción; dicha instrucción no toma un operando. La declaración resultante es traducida por un ensamblador a instrucciones en lenguaje de máquina que pueden cargarse en la memoria y ejecutarse.

Por ejemplo, la siguiente instrucción le indica a un procesador x86 / IA-32 que mueva un valor inmediato de 8 bits a un registro . El código binario para esta instrucción es 10110 seguido de un identificador de 3 bits para el registro que se utilizará. El identificador para el registro AL es 000, por lo que el siguiente código de máquina carga el registro AL con los datos 01100001. [24]

10110000 01100001

Este código de computadora binario se puede hacer más legible para los humanos expresándolo en hexadecimal de la siguiente manera.

B0 61

Aquí, B0significa "Mover una copia del siguiente valor a AL ", y 61es una representación hexadecimal del valor 01100001, que es 97 en decimal . El lenguaje ensamblador para la familia 8086 proporciona el mnemónico MOV (una abreviatura de mover ) para instrucciones como esta, por lo que el código de máquina anterior se puede escribir de la siguiente manera en lenguaje ensamblador, completo con un comentario explicativo si es necesario, después del punto y coma. Esto es mucho más fácil de leer y recordar.

MOV AL , 61h ; Cargar AL con 97 decimales (61 hexadecimales)   

En algunos lenguajes ensambladores (incluido este), se puede utilizar el mismo mnemónico, como MOV, para una familia de instrucciones relacionadas para cargar, copiar y mover datos, ya sean valores inmediatos, valores en registros o ubicaciones de memoria a las que apuntan los valores en los registros o direcciones inmediatas (también conocidas como directas). Otros ensambladores pueden utilizar mnemónicos de código de operación independientes, como L para "mover la memoria al registro", ST para "mover el registro a la memoria", LR para "mover el registro al registro", MVI para "mover el operando inmediato a la memoria", etc.

Si se utiliza el mismo mnemónico para distintas instrucciones, significa que el mnemónico corresponde a varios códigos de instrucciones binarias diferentes, excluyendo los datos (por ejemplo, 61hen este ejemplo), dependiendo de los operandos que siguen al mnemónico. Por ejemplo, para las CPU x86/IA-32, la sintaxis del lenguaje ensamblador de Intel MOV AL, AHrepresenta una instrucción que mueve el contenido del registro AH al registro AL . La forma hexadecimal [nb 3] de esta instrucción es:

88E0

El primer byte, 88h, identifica un movimiento entre un registro del tamaño de un byte y otro registro o memoria, y el segundo byte, E0h, está codificado (con tres campos de bits) para especificar que ambos operandos son registros, la fuente es AH y el destino es AL .

En un caso como este, en el que el mismo mnemónico puede representar más de una instrucción binaria, el ensamblador determina qué instrucción generar examinando los operandos. En el primer ejemplo, el operando 61hes una constante numérica hexadecimal válida y no es un nombre de registro válido, por lo que solo la B0instrucción puede ser aplicable. En el segundo ejemplo, el operando AHes un nombre de registro válido y no una constante numérica válida (hexadecimal, decimal, octal o binaria), por lo que solo la 88instrucción puede ser aplicable.

Los lenguajes ensambladores siempre están diseñados para que esta clase de falta de ambigüedad sea universalmente impuesta por su sintaxis. Por ejemplo, en el lenguaje ensamblador Intel x86, una constante hexadecimal debe comenzar con un dígito numérico, de modo que el número hexadecimal 'A' (igual al decimal diez) se escribiría como 0Aho 0AH, no AH, específicamente para que no parezca ser el nombre del registro AH . (La misma regla también evita la ambigüedad con los nombres de los registros BH , CH y DH , así como con cualquier símbolo definido por el usuario que termine con la letra H y que de otro modo contenga solo caracteres que sean dígitos hexadecimales, como la palabra "BEACH").

Volviendo al ejemplo original, mientras que el código de operación x86 10110000 ( B0) copia un valor de 8 bits en el registro ALB1 , 10110001 ( ) lo mueve al registro CL y 10110010 ( B2) lo hace en el registro DL . A continuación se ofrecen ejemplos en lenguaje ensamblador para estos casos. [24]

MOV AL , 1h ; Carga AL con valor inmediato 1 MOV CL , 2h ; Carga CL con valor inmediato 2 MOV DL , 3h ; Carga DL con valor inmediato 3         

La sintaxis de MOV también puede ser más compleja como lo muestran los siguientes ejemplos. [25]

MOV EAX , [ EBX ] ; Mueve los 4 bytes en la memoria en la dirección contenida en EBX a EAX MOV [ ESI + EAX ], CL ; Mueve el contenido de CL al byte en la dirección ESI+EAX MOV DS , DX ; Mueve el contenido de DX al registro de segmento DS         

En cada caso, el mnemónico MOV se traduce directamente a uno de los códigos de operación 88-8C, 8E, A0-A3, B0-BF, C6 o C7 mediante un ensamblador, y el programador normalmente no tiene que saber o recordar cuál. [24]

La transformación del lenguaje ensamblador en código de máquina es tarea de un ensamblador, y lo inverso puede lograrse, al menos parcialmente, con un desensamblador . A diferencia de los lenguajes de alto nivel , existe una correspondencia uno a uno entre muchas instrucciones de ensamblador simples e instrucciones de lenguaje de máquina. Sin embargo, en algunos casos, un ensamblador puede proporcionar pseudoinstrucciones (esencialmente macros) que se expanden en varias instrucciones de lenguaje de máquina para proporcionar una funcionalidad comúnmente necesaria. Por ejemplo, para una máquina que carece de una instrucción "ramificar si es mayor o igual a", un ensamblador puede proporcionar una pseudoinstrucciones que se expandan a las instrucciones "establecer si es menor que" y "ramificar si es cero (en el resultado de la instrucción de establecimiento)" de la máquina. La mayoría de los ensambladores con todas las funciones también proporcionan un rico lenguaje de macros (que se analiza a continuación) que utilizan los proveedores y programadores para generar secuencias de datos y códigos más complejos. Dado que la información sobre pseudoinstrucciones y macros definidas en el entorno de ensamblador no está presente en el programa objeto, un desensamblador no puede reconstruir las invocaciones de macros y pseudoinstrucciones, sino que solo puede desensamblar las instrucciones de máquina reales que el ensamblador generó a partir de esas entidades abstractas de lenguaje ensamblador. Del mismo modo, dado que el ensamblador ignora los comentarios en el archivo fuente de lenguaje ensamblador y no tienen efecto en el código objeto que genera, un desensamblador siempre es completamente incapaz de recuperar los comentarios fuente.

Cada arquitectura informática tiene su propio lenguaje de máquina. Los ordenadores difieren en la cantidad y el tipo de operaciones que admiten, en los distintos tamaños y cantidades de registros y en las representaciones de los datos almacenados. Si bien la mayoría de los ordenadores de uso general pueden llevar a cabo esencialmente la misma funcionalidad, las formas en que lo hacen difieren; los lenguajes ensambladores correspondientes reflejan estas diferencias.

Pueden existir varios conjuntos de mnemónicos o sintaxis de lenguaje ensamblador para un único conjunto de instrucciones, que normalmente se instancian en distintos programas ensambladores. En estos casos, el más popular suele ser el que proporciona el fabricante de la CPU y que se utiliza en su documentación.

Dos ejemplos de CPU que tienen dos conjuntos diferentes de mnemónicos son la familia Intel 8080 y los Intel 8086/8088. Debido a que Intel reclamó los derechos de autor sobre sus mnemónicos en lenguaje ensamblador (en cada página de su documentación publicada en la década de 1970 y principios de la de 1980, al menos), algunas compañías que produjeron de forma independiente CPU compatibles con los conjuntos de instrucciones de Intel inventaron sus propios mnemónicos. La CPU Zilog Z80 , una mejora del Intel 8080A , admite todas las instrucciones del 8080A y muchas más; Zilog inventó un lenguaje ensamblador completamente nuevo, no solo para las nuevas instrucciones sino también para todas las instrucciones del 8080A. Por ejemplo, donde Intel usa los mnemónicos MOV , MVI , LDA , STA , LXI , LDAX , STAX , LHLD y SHLD para varias instrucciones de transferencia de datos, el lenguaje ensamblador Z80 usa el mnemónico LD para todas ellas. Un caso similar es el de las CPU NEC V20 y V30 , copias mejoradas de las Intel 8086 y 8088, respectivamente. Al igual que Zilog con el Z80, NEC inventó nuevos mnemónicos para todas las instrucciones 8086 y 8088, para evitar acusaciones de infracción de los derechos de autor de Intel. (Es cuestionable si dichos derechos de autor pueden ser válidos, y las empresas de CPU posteriores como AMD [nb 4] y Cyrix republicaron los mnemónicos de instrucciones x86/IA-32 de Intel exactamente sin permiso ni penalización legal). Es dudoso que en la práctica muchas personas que programaron las V20 y V30 realmente escribieron en el lenguaje ensamblador de NEC en lugar del de Intel; dado que dos lenguajes ensambladores cualesquiera para la misma arquitectura de conjunto de instrucciones son isomorfos (algo así como el inglés y el latín pig ), no existe ningún requisito para utilizar el lenguaje ensamblador publicado por el propio fabricante con los productos de ese fabricante.

Diseño del lenguaje

Elementos básicos

Existe un alto grado de diversidad en la forma en que los autores de ensambladores categorizan las instrucciones y en la nomenclatura que utilizan. En particular, algunos describen cualquier cosa que no sea una mnemotecnia de máquina o una mnemotecnia extendida como una pseudooperación (pseudo-op). Un lenguaje ensamblador típico consta de 3 tipos de instrucciones que se utilizan para definir operaciones de programa:

Mnemotécnicos de código de operación y mnemotécnicos extendidos

Las instrucciones (sentencias) en lenguaje ensamblador son generalmente muy simples, a diferencia de las de los lenguajes de alto nivel . Generalmente, un mnemónico es un nombre simbólico para una única instrucción ejecutable en lenguaje de máquina (un opcode ), y hay al menos un mnemónico de opcode definido para cada instrucción en lenguaje de máquina. Cada instrucción normalmente consta de una operación o un opcode más cero o más operandos . La mayoría de las instrucciones se refieren a un único valor o a un par de valores. Los operandos pueden ser inmediatos (valor codificado en la propia instrucción), registros especificados en la instrucción o implícitos, o las direcciones de datos ubicados en otra parte del almacenamiento. Esto está determinado por la arquitectura del procesador subyacente: el ensamblador simplemente refleja cómo funciona esta arquitectura. Los mnemónicos extendidos se utilizan a menudo para especificar una combinación de un opcode con un operando específico, por ejemplo, los ensambladores System/360 utilizan Bcomo mnemónico extendido para BCcon una máscara de 15 y NOP("NO OPeration" – no hacer nada para un paso) para BCcon una máscara de 0.

Los mnemónicos extendidos se utilizan a menudo para admitir usos especializados de instrucciones, a menudo para fines que no son obvios a partir del nombre de la instrucción. Por ejemplo, muchas CPU no tienen una instrucción NOP explícita, pero sí tienen instrucciones que se pueden usar para ese propósito. En las CPU 8086, la instrucción se utiliza para , siendo un pseudocódigo de operación para codificar la instrucción . Algunos desensambladores reconocen esto y decodificarán la instrucción como . De manera similar, los ensambladores IBM para System/360 y System/370 utilizan los mnemónicos extendidos y para y con máscaras cero. Para la arquitectura SPARC, se conocen como instrucciones sintéticas . [26]xchg ax,axnopnopxchg ax,axxchg ax,axnopNOPNOPRBCBCR

Algunos ensambladores también admiten macroinstrucciones integradas simples que generan dos o más instrucciones de máquina. Por ejemplo, con algunos ensambladores Z80, ld hl,bcse reconoce la instrucción como generate ld l,cseguida de ld h,b. [27] A veces, se las conoce como pseudocódigos de operación .

Los mnemónicos son símbolos arbitrarios; en 1985, el IEEE publicó el estándar 694 para un conjunto uniforme de mnemónicos que utilizarían todos los ensambladores. El estándar ha sido retirado desde entonces.

Directivas de datos

Existen instrucciones que se utilizan para definir elementos de datos que contienen datos y variables. Definen el tipo de datos, la longitud y la alineación de los datos. Estas instrucciones también pueden definir si los datos están disponibles para programas externos (programas ensamblados por separado) o solo para el programa en el que se define la sección de datos. Algunos ensambladores las clasifican como pseudooperaciones.

Directivas de la Asamblea

Las directivas de ensamblaje, también llamadas pseudo-opcodes, pseudo-operaciones o pseudo-ops, son comandos que se dan a un ensamblador "para que realice operaciones distintas a las instrucciones de ensamblaje". [20] Las directivas afectan la forma en que opera el ensamblador y "pueden afectar el código objeto, la tabla de símbolos, el archivo de listado y los valores de los parámetros internos del ensamblador". A veces, el término pseudo-opcode se reserva para directivas que generan código objeto, como las que generan datos. [28]

Los nombres de las pseudooperaciones suelen comenzar con un punto para distinguirlas de las instrucciones de la máquina. Las pseudooperaciones pueden hacer que el ensamblaje del programa dependa de los parámetros ingresados ​​por un programador, de modo que un programa se pueda ensamblar de diferentes maneras, tal vez para diferentes aplicaciones. O bien, una pseudooperación se puede utilizar para manipular la presentación de un programa para que sea más fácil de leer y mantener. Otro uso común de las pseudooperaciones es reservar áreas de almacenamiento para datos de tiempo de ejecución y, opcionalmente, inicializar su contenido con valores conocidos.

Los ensambladores simbólicos permiten a los programadores asociar nombres arbitrarios ( etiquetas o símbolos ) con ubicaciones de memoria y varias constantes. Por lo general, a cada constante y variable se le asigna un nombre para que las instrucciones puedan hacer referencia a esas ubicaciones por nombre, promoviendo así el código autodocumentado . En el código ejecutable, el nombre de cada subrutina está asociado con su punto de entrada, por lo que cualquier llamada a una subrutina puede usar su nombre. Dentro de las subrutinas, los destinos GOTO reciben etiquetas. Algunos ensambladores admiten símbolos locales que a menudo son léxicamente distintos de los símbolos normales (por ejemplo, el uso de "10$" como destino GOTO).

Algunos ensambladores, como NASM , proporcionan una gestión flexible de símbolos, lo que permite a los programadores gestionar diferentes espacios de nombres , calcular automáticamente los desplazamientos dentro de las estructuras de datos y asignar etiquetas que hacen referencia a valores literales o al resultado de cálculos simples realizados por el ensamblador. Las etiquetas también se pueden utilizar para inicializar constantes y variables con direcciones reubicables.

Los lenguajes ensambladores, como la mayoría de los demás lenguajes informáticos, permiten añadir comentarios al código fuente del programa que se ignorarán durante el ensamblaje. Los comentarios sensatos son esenciales en los programas en lenguaje ensamblador, ya que el significado y el propósito de una secuencia de instrucciones binarias de máquina pueden ser difíciles de determinar. El lenguaje ensamblador "en bruto" (sin comentarios) generado por compiladores o desensambladores es bastante difícil de leer cuando se deben realizar cambios.

Macros

Muchos ensambladores admiten macros predefinidas , y otros admiten macros definidas por el programador (y redefinibles repetidamente) que implican secuencias de líneas de texto en las que se incrustan variables y constantes. La definición de macro es más comúnmente [nb 5] una mezcla de declaraciones de ensamblador, por ejemplo, directivas, instrucciones de máquina simbólicas y plantillas para declaraciones de ensamblador. Esta secuencia de líneas de texto puede incluir códigos de operación o directivas. Una vez que se ha definido una macro, su nombre puede usarse en lugar de un mnemónico. Cuando el ensamblador procesa una declaración de este tipo, reemplaza la declaración con las líneas de texto asociadas con esa macro, luego las procesa como si existieran en el archivo de código fuente (incluyendo, en algunos ensambladores, la expansión de cualquier macro existente en el texto de reemplazo). Las macros en este sentido datan de los autocodificadores de IBM de la década de 1950. [29]

Los ensambladores de macros suelen tener directivas para, por ejemplo, definir macros, definir variables, establecer variables como resultado de una expresión aritmética, lógica o de cadena, iterar y generar código condicionalmente. Algunas de esas directivas pueden estar restringidas para usarse dentro de una definición de macro, por ejemplo, MEXIT en HLASM , mientras que otras pueden estar permitidas dentro del código abierto (fuera de las definiciones de macros), por ejemplo, AIF y COPY en HLASM.

En lenguaje ensamblador, el término "macro" representa un concepto más amplio que en otros contextos, como el preprocesador en el lenguaje de programación C , donde su directiva #define se utiliza normalmente para crear macros breves de una sola línea. Las macroinstrucciones de ensamblador, como las macros en PL/I y algunos otros lenguajes, pueden ser "programas" extensos en sí mismos, ejecutados por interpretación del ensamblador durante el ensamblaje.

Dado que las macros pueden tener nombres "cortos" pero expandirse a varias o incluso muchas líneas de código, se pueden utilizar para hacer que los programas en lenguaje ensamblador parezcan mucho más cortos y requieran menos líneas de código fuente, como sucede con los lenguajes de nivel superior. También se pueden utilizar para agregar niveles superiores de estructura a los programas ensambladores, introducir opcionalmente código de depuración integrado mediante parámetros y otras funciones similares.

Los ensambladores de macros suelen permitir que las macros tomen parámetros . Algunos ensambladores incluyen lenguajes de macros bastante sofisticados, que incorporan elementos de lenguaje de alto nivel como parámetros opcionales, variables simbólicas, condicionales, manipulación de cadenas y operaciones aritméticas, todos utilizables durante la ejecución de una macro dada, y que permiten a las macros guardar el contexto o intercambiar información. Por lo tanto, una macro puede generar numerosas instrucciones en lenguaje ensamblador o definiciones de datos, basadas en los argumentos de la macro. Esto se puede utilizar para generar estructuras de datos de estilo de registro o bucles " desenrollados ", por ejemplo, o puede generar algoritmos completos basados ​​en parámetros complejos. Por ejemplo, una macro "sort" podría aceptar la especificación de una clave de ordenación compleja y generar código diseñado para esa clave específica, sin necesidad de las pruebas de tiempo de ejecución que se requerirían para un procedimiento general que interprete la especificación. Se puede considerar que una organización que utiliza lenguaje ensamblador que se ha extendido en gran medida utilizando un conjunto de macros de este tipo está trabajando en un lenguaje de nivel superior, ya que dichos programadores no están trabajando con los elementos conceptuales de nivel más bajo de una computadora. Para subrayar este punto, se utilizaron macros para implementar una máquina virtual temprana en SNOBOL4 (1967), que se escribió en el lenguaje de implementación SNOBOL (SIL), un lenguaje ensamblador para una máquina virtual. La máquina de destino traduciría esto a su código nativo utilizando un ensamblador de macros . [30] Esto permitió un alto grado de portabilidad para la época.

Las macros se utilizaban para personalizar sistemas de software a gran escala para clientes específicos en la era de los mainframes y también las utilizaba el personal de los clientes para satisfacer las necesidades de sus empleadores creando versiones específicas de los sistemas operativos de los fabricantes. Esto lo hacían, por ejemplo, los programadores de sistemas que trabajaban con el sistema de monitorización conversacional/máquina virtual ( VM/CMS ) de IBM y con los complementos de "procesamiento de transacciones en tiempo real" de IBM, el sistema de control de información del cliente (CICS ) y ACP / TPF , el sistema financiero/de aerolíneas que comenzó en la década de 1970 y que todavía hoy ejecuta muchos sistemas de reserva por ordenador (CRS) y sistemas de tarjetas de crédito de gran tamaño.

También es posible utilizar únicamente las capacidades de procesamiento de macros de un ensamblador para generar código escrito en lenguajes completamente diferentes, por ejemplo, para generar una versión de un programa en COBOL utilizando un programa ensamblador de macros puro que contenga líneas de código COBOL dentro de operadores de tiempo de ensamblaje que instruyan al ensamblador para que genere código arbitrario. IBM OS/360 utiliza macros para realizar la generación del sistema . El usuario especifica opciones codificando una serie de macros de ensamblador. El ensamblaje de estas macros genera un flujo de trabajo para construir el sistema, que incluye el lenguaje de control de trabajos y las instrucciones de control de utilidades .

Esto se debe a que, como se entendió en la década de 1960, el concepto de "procesamiento de macros" es independiente del concepto de "ensamblador", siendo el primero, en términos modernos, más procesamiento de textos que generación de código objeto. El concepto de procesamiento de macros apareció, y aparece, en el lenguaje de programación C, que admite "instrucciones de preprocesador" para establecer variables y realizar pruebas condicionales sobre sus valores. A diferencia de ciertos procesadores de macros anteriores dentro de ensambladores, el preprocesador de C no es Turing-completo porque carece de la capacidad de hacer bucles o de "ir a", lo último que permite que los programas hagan bucles.

A pesar del poder del procesamiento de macros, cayó en desuso en muchos lenguajes de alto nivel (las principales excepciones son C , C++ y PL/I), mientras que siguió siendo un recurso perenne para los ensambladores.

La sustitución de parámetros de macros se realiza estrictamente por nombre: en el momento del procesamiento de la macro, el valor de un parámetro se sustituye textualmente por su nombre. El tipo de error más famoso que se produjo fue el uso de un parámetro que era en sí mismo una expresión y no un simple nombre cuando el autor de la macro esperaba un nombre. En la macro:

foo: macro acarga a*b

La intención era que el llamador proporcionara el nombre de una variable, y la variable o constante "global" b se usaría para multiplicar "a". Si se llama a foo con el parámetro a-c, load a-c*bse produce la expansión de la macro de . Para evitar cualquier posible ambigüedad, los usuarios de procesadores de macros pueden poner entre paréntesis los parámetros formales dentro de las definiciones de macros, o los llamadores pueden poner entre paréntesis los parámetros de entrada. [31]

Soporte para programación estructurada

Se han escrito paquetes de macros que proporcionan elementos de programación estructurada para codificar el flujo de ejecución. El primer ejemplo de este enfoque fue el conjunto de macros Concept-14, [32] propuesto originalmente por Harlan Mills (marzo de 1970) e implementado por Marvin Kessler en la División de Sistemas Federales de IBM, que proporcionaba bloques de flujo de control IF/ELSE/ENDIF y similares para programas ensambladores de OS/360. Esta era una forma de reducir o eliminar el uso de operaciones GOTO en código ensamblador, uno de los principales factores que causaban el código espagueti en lenguaje ensamblador. Este enfoque fue ampliamente aceptado a principios de la década de 1980 (los últimos días del uso a gran escala del lenguaje ensamblador). El kit de herramientas de ensamblador de alto nivel de IBM [33] incluye un paquete de macros de este tipo.

Otro diseño fue A-Natural, [34] un ensamblador "orientado a flujo" para procesadores 8080/ Z80 de Whitesmiths Ltd. (desarrolladores del sistema operativo similar a Unix Idris , y lo que se informó que fue el primer compilador de C comercial ). El lenguaje fue clasificado como un ensamblador porque trabajaba con elementos de máquina en bruto como códigos de operación , registros y referencias de memoria; pero incorporaba una sintaxis de expresión para indicar el orden de ejecución. Los paréntesis y otros símbolos especiales, junto con construcciones de programación estructurada orientada a bloques, controlaban la secuencia de las instrucciones generadas. A-natural fue construido como el lenguaje objeto de un compilador de C, en lugar de para codificación manual, pero su sintaxis lógica ganó algunos fanáticos.

Ha habido poca demanda aparente de ensambladores más sofisticados desde el declive del desarrollo del lenguaje ensamblador a gran escala. [35] A pesar de eso, todavía se están desarrollando y aplicando en casos donde las limitaciones de recursos o peculiaridades en la arquitectura del sistema de destino impiden el uso efectivo de lenguajes de nivel superior. [36]

Los ensambladores con un motor de macros potente permiten una programación estructurada a través de macros, como la macro switch proporcionada con el paquete Masm32 (este código es un programa completo):

include \ masm32 \ include \ masm32rt.inc ; utiliza la biblioteca Masm32 .code demomain: REPEAT 20 switch rv ( nrandom , 9 ) ; genera un número entre 0 y 8 mov ecx , 7 case 0 print "case 0" case ecx ; a diferencia de la mayoría de los otros lenguajes de programación, print "case 7" ; el switch Masm32 permite "casos variables" case 1 ... 3 .if eax == 1 print "case 1" .elseif eax == 2 print "case 2" .else print "casos 1 a 3: otros" .endif case 4 , 6 , 8 print "casos 4, 6 u 8" default mov ebx , 19 ; print 20 stars .Repeat print "*" dec ebx .Until Sign ?; repetir hasta que se establezca la bandera de signo endsw print chr$ ( 13 , 10 ) ENDM exit end demomain                                  

Uso del lenguaje ensamblador

Cuando se introdujo la computadora con programa almacenado , los programas se escribían en código de máquina y se cargaban en la computadora desde una cinta de papel perforada o se activaban directamente en la memoria desde los interruptores de la consola. [ cita requerida ] A Kathleen Booth "se le atribuye la invención del lenguaje ensamblador" [37] [38] basándose en el trabajo teórico que comenzó en 1947, mientras trabajaba en el ARC2 en Birkbeck, Universidad de Londres, tras la consulta de Andrew Booth (más tarde su marido) con el matemático John von Neumann y el físico Herman Goldstine en el Instituto de Estudios Avanzados . [38] [39]

A finales de 1948, la Calculadora Automática de Almacenamiento de Retardo Electrónico (EDSAC) tenía un ensamblador (llamado "órdenes iniciales") integrado en su programa de arranque . Utilizaba mnemotécnicos de una letra desarrollados por David Wheeler , a quien la IEEE Computer Society atribuye el mérito de ser el creador del primer "ensamblador". [20] [40] [41] Los informes sobre la EDSAC introdujeron el término "ensamblador" para el proceso de combinar campos en una palabra de instrucción. [42] SOAP ( Programa de Ensamblaje Óptimo Simbólico ) fue un lenguaje ensamblador para la computadora IBM 650 escrito por Stan Poley en 1955. [43]

Los lenguajes ensambladores eliminaron gran parte de la programación de primera generación propensa a errores, tediosa y que consumía mucho tiempo que se necesitaba con las primeras computadoras, liberando a los programadores de tareas tediosas como recordar códigos numéricos y calcular direcciones. Alguna vez fueron ampliamente utilizados para todo tipo de programación. A fines de la década de 1950, su uso había sido reemplazado en gran medida por lenguajes de alto nivel en la búsqueda de una mejor productividad de programación . [44] Hoy en día, el lenguaje ensamblador todavía se usa para la manipulación directa de hardware, el acceso a instrucciones especializadas del procesador o para abordar problemas críticos de rendimiento. [45] Los usos típicos son los controladores de dispositivos , los sistemas integrados de bajo nivel y los sistemas en tiempo real (consulte § Uso actual).

Numerosos programas fueron escritos completamente en lenguaje ensamblador. El Burroughs MCP (1961) fue el primer ordenador para el que no se desarrolló un sistema operativo completamente en lenguaje ensamblador; se escribió en lenguaje orientado a problemas de sistemas ejecutivos (ESPOL), un dialecto de Algol. Muchas aplicaciones comerciales también se escribieron en lenguaje ensamblador, incluida una gran cantidad de software para mainframes de IBM desarrollado por grandes corporaciones. COBOL , FORTRAN y algunos PL/I acabaron desplazando al lenguaje ensamblador, aunque varias grandes organizaciones mantuvieron infraestructuras de aplicaciones en lenguaje ensamblador hasta bien entrada la década de 1990.

El lenguaje ensamblador fue el lenguaje de desarrollo principal para los ordenadores domésticos de 8 bits, como el Apple II , los ordenadores Atari de 8 bits , el ZX Spectrum y el Commodore 64. El BASIC interpretado en estos sistemas no ofrecía la máxima velocidad de ejecución ni el uso completo de las funciones para aprovechar al máximo el hardware disponible. El lenguaje ensamblador fue la opción predeterminada para programar consolas de 8 bits, como el Atari 2600 y el Nintendo Entertainment System .

El software clave para los sistemas IBM PC compatibles, como MS-DOS , Turbo Pascal y la hoja de cálculo Lotus 1-2-3 , se escribió en lenguaje ensamblador. A medida que la velocidad de las computadoras creció exponencialmente, el lenguaje ensamblador se convirtió en una herramienta para acelerar partes de los programas, como la representación de Doom , en lugar de un lenguaje de desarrollo dominante. En la década de 1990, el lenguaje ensamblador se utilizó para maximizar el rendimiento de sistemas como Sega Saturn , [46] y como el lenguaje principal para el hardware de arcade que utilizaba la CPU/GPU integrada TMS34010, como Mortal Kombat y NBA Jam .

Uso actual

Ha habido un debate sobre la utilidad y el rendimiento del lenguaje ensamblador en relación con los lenguajes de alto nivel. [47]

Aunque el lenguaje ensamblador tiene usos específicos donde es importante (ver más abajo), existen otras herramientas para la optimización. [48]

A partir de julio de 2017 , el índice TIOBE de popularidad de lenguajes de programación clasifica al lenguaje ensamblador en el puesto 11, por delante de Visual Basic , por ejemplo. [49] El ensamblador se puede utilizar para optimizar la velocidad o para optimizar el tamaño. En el caso de la optimización de la velocidad, se afirma que los compiladores de optimización modernos [50] convierten los lenguajes de alto nivel en código que puede ejecutarse tan rápido como el ensamblador escrito a mano, a pesar de algunos contraejemplos. [51] [52] [53] La complejidad de los procesadores modernos y los subsistemas de memoria hace que la optimización efectiva sea cada vez más difícil tanto para los compiladores como para los programadores de ensamblaje. [54] [55] El aumento del rendimiento del procesador ha significado que la mayoría de las CPU permanecen inactivas la mayor parte del tiempo, [56] con retrasos causados ​​por cuellos de botella predecibles como fallas de caché, operaciones de E/S y paginación , lo que hace que la velocidad de ejecución del código sin procesar no sea un problema para muchos programadores.

Todavía existen situaciones en las que los desarrolladores podrían optar por utilizar el lenguaje ensamblador:

El lenguaje ensamblador todavía se enseña en la mayoría de los programas de informática e ingeniería electrónica . Aunque hoy en día pocos programadores trabajan regularmente con el lenguaje ensamblador como herramienta, los conceptos subyacentes siguen siendo importantes. Temas tan fundamentales como la aritmética binaria , la asignación de memoria , el procesamiento de pila , la codificación del conjunto de caracteres , el procesamiento de interrupciones y el diseño de compiladores serían difíciles de estudiar en detalle sin una comprensión de cómo funciona un ordenador a nivel de hardware. Dado que el comportamiento de un ordenador está definido fundamentalmente por su conjunto de instrucciones, la forma lógica de aprender estos conceptos es estudiar un lenguaje ensamblador. La mayoría de los ordenadores modernos tienen conjuntos de instrucciones similares. Por lo tanto, estudiar un solo lenguaje ensamblador es suficiente para aprender los conceptos básicos, reconocer situaciones en las que el uso del lenguaje ensamblador podría ser apropiado y ver cómo se puede crear código ejecutable eficiente a partir de lenguajes de alto nivel. [23]

Aplicaciones típicas

Véase también

Notas

  1. ^ Aparte de los metaensambladores
  2. ^ Sin embargo, eso no significa que los programas ensambladores que implementan esos lenguajes sean universales.
  3. ^ Esta es una de las dos formas redundantes de esta instrucción que funcionan de manera idéntica. El 8086 y varias otras CPU de finales de los años 1970 y principios de los años 1980 tienen redundancias en sus conjuntos de instrucciones, porque era más sencillo para los ingenieros diseñar estas CPU (para que encajaran en chips de silicio de tamaños limitados) con los códigos redundantes que eliminarlos (consulte los términos indiferentes ). Cada ensamblador normalmente generará solo una de dos o más codificaciones de instrucciones redundantes, pero un desensamblador normalmente reconocerá cualquiera de ellas.
  4. ^ AMD fabricó CPU Intel 8086, 8088 y 80286 de segunda fuente, y quizás CPU 8080A y 8085A, bajo licencia de Intel, pero a partir del 80386, Intel se negó a compartir sus diseños de CPU x86 con nadie (AMD presentó una demanda por incumplimiento de contrato) y AMD diseñó, fabricó y vendió CPU de la familia x86 de 32 y 64 bits sin la ayuda o el respaldo de Intel.
  5. ^ En 7070 Autocoder, una definición de macro es un programa generador de macros 7070 que el ensamblador llama; Autocoder proporciona macros especiales para que los utilicen los generadores de macros.

Referencias

  1. ^ ab "Lenguaje ensamblador". Ensamblador de alto nivel para z/OS, z/VM y z/VSE Referencia del lenguaje Versión 1, versión 6. IBM . 2014 [1990]. SC26-4940-06.
  2. ^ "Asamblea: revisión" (PDF) . Ciencias de la Computación e Ingeniería. Facultad de Ingeniería, Universidad Estatal de Ohio . 2016. Archivado (PDF) desde el original el 24 de marzo de 2020 . Consultado el 24 de marzo de 2020 .
  3. ^ Archer, Benjamin (noviembre de 2016). Lenguaje ensamblador para estudiantes. North Charleston, Carolina del Sur, EE. UU.: CreateSpace Independent Publishing . ISBN 978-1-5403-7071-6El lenguaje ensamblador también puede denominarse código máquina simbólico.
  4. ^ Streib, James T. (2020). "Guía del lenguaje ensamblador". Temas de pregrado en informática . Cham: Springer International Publishing. doi :10.1007/978-3-030-35639-2. ISBN 978-3-030-35638-5. ISSN  1863-7310. S2CID  195930813. La programación en lenguaje ensamblador tiene los mismos beneficios que la programación en lenguaje máquina, excepto que es más fácil.
  5. ^ Saxon, James A.; Plette, William S. (1962). Programación del IBM 1401, un manual programado autodidacta. Englewood Cliffs, Nueva Jersey, EE. UU.: Prentice-Hall . LCCN  62-20615.(NB. Uso del término programa ensamblador .)
  6. ^ Kornelis, AF (2010) [2003]. "Ensamblador de alto nivel: descripción general de los códigos de operación, directivas del ensamblador". Archivado desde el original el 24 de marzo de 2020. Consultado el 24 de marzo de 2020 .
  7. ^ "Instrucciones de macro". Ensamblador de alto nivel para z/OS, z/VM y z/VSE Referencia del lenguaje Versión 1, versión 6. IBM . 2014 [1990]. SC26-4940-06.
  8. ^ Booth, Andrew D; Britten, Kathleen HV (1947). Codificación para ARC (PDF) . Instituto de Estudios Avanzados, Princeton . Consultado el 4 de noviembre de 2022 .
  9. ^ Wilkes, Maurice Vincent ; Wheeler, David John ; Gill, Stanley J. (1951). La preparación de programas para una computadora digital electrónica (Reimpresión 1982 ed.). Tomash Publishers . ISBN 978-0-93822803-5.OCLC 313593586  .
  10. ^ Fairhead, Harry (16 de noviembre de 2017). «Historia de los lenguajes informáticos: la década clásica, 1950». I Programmer . Archivado desde el original el 2 de enero de 2020. Consultado el 6 de marzo de 2020 .
  11. ^ "¿Cómo dependen los lenguajes ensambladores de los sistemas operativos?". Stack Exchange . Stack Exchange Inc. 2011-07-28. Archivado desde el original el 2020-03-24 . Consultado el 2020-03-24 .(NB. Las llamadas al sistema a menudo varían, por ejemplo, para MVS vs. VSE vs. VM/CMS; los formatos binarios/ejecutables para diferentes sistemas operativos también pueden variar).
  12. ^ Austerlitz, Howard (2003). "Lenguajes de programación informática". Técnicas de adquisición de datos mediante PC . Elsevier. pp. 326–360. doi :10.1016/b978-012068377-2/50013-9. ISBN 9780120683772El lenguaje ensamblador es un lenguaje de programación compilado de bajo nivel. Depende del procesador, ya que básicamente traduce los mnemónicos del ensamblador directamente a los comandos que entiende una CPU en particular, de forma uno a uno. Estos mnemónicos del ensamblador son el conjunto de instrucciones para ese procesador.
  13. ^ Carnes, Beau (27 de abril de 2022). "Aprenda a programar en lenguaje ensamblador con ARM". freeCodeCamp.org . Consultado el 21 de junio de 2022 . El lenguaje ensamblador suele ser específico de una arquitectura informática en particular, por lo que existen varios tipos de lenguajes ensambladores. ARM es un lenguaje ensamblador cada vez más popular.
  14. ^ Brooks, Frederick P. (1986). "No hay bala de plata: esencia y accidente en la ingeniería de software". Actas de la Décima Conferencia Mundial de Computación de la IFIP , págs. 1069–1076.
  15. ^ Anguiano, Ricardo. «Línea principal del kernel de Linux 4.9 sloccount.txt». Gist . Consultado el 4 de mayo de 2022 .
  16. ^ Daintith, John, ed. (2019). «metaensamblador». A Dictionary of Computing . Archivado desde el original el 24 de marzo de 2020. Consultado el 24 de marzo de 2020 .
  17. ^ Xerox Data Systems (octubre de 1975). Manual de referencia de lenguaje y operaciones de Xerox Meta-Symbol Sigma 5-9 Computers (PDF) . pág. vi. Archivado (PDF) del original el 2022-10-09 . Consultado el 2020-06-07 . Utilizado como metaensamblador, permite al usuario diseñar sus propios lenguajes de programación y generar procesadores para dichos lenguajes con un mínimo esfuerzo.
  18. ^ Sperry Univac Computer Systems (1977). Referencia del programador de metaensamblador (MASM) de Sperry Univac Computer Systems (PDF) . Archivado (PDF) desde el original el 2022-10-09 . Consultado el 2020-06-07 .
  19. ^ "Cómo usar lenguaje ensamblador en línea en código C". gnu.org . Consultado el 5 de noviembre de 2020 .
  20. ^ abcd Salomon, David (febrero de 1993) [1992]. Escrito en la Universidad Estatal de California, Northridge, California, EE. UU. Chivers, Ian D. (ed.). Ensambladores y cargadores (PDF) . Serie Ellis Horwood en Computadoras y sus aplicaciones (1.ª ed.). Chicester, West Sussex, Reino Unido: Ellis Horwood Limited / Simon & Schuster International Group . págs. 7, 237–238. ISBN 0-13-052564-2Archivado (PDF) del original el 23 de marzo de 2020. Consultado el 1 de octubre de 2008 .(xiv+294+4 páginas)
  21. ^ Finlayson, Ian; Davis, Brandon; Gavin, Peter; Uh, Gang-Ryung; Whalley, David; Själander, Magnus; Tyson, Gary (2013). "Mejora de la eficiencia del procesador mediante la canalización estática de instrucciones". Actas de la 14.ª conferencia ACM SIGPLAN/SIGBED sobre lenguajes, compiladores y herramientas para sistemas integrados . págs. 33–44. doi :10.1145/2465554.2465559. ISBN . 9781450320856.S2CID8015812  .​
  22. ^ Beck, Leland L. (1996). "2". Software de sistemas: Introducción a la programación de sistemas . Addison Wesley .
  23. ^ ab Hyde, Randall (septiembre de 2003) [30 de septiembre de 1996]. "Prólogo ("¿Por qué alguien aprendería esto?") / Capítulo 12: Clases y objetos". El arte del lenguaje ensamblador (2.ª ed.). No Starch Press . ISBN 1-886411-97-2Archivado desde el original el 6 de mayo de 2010. Consultado el 22 de junio de 2020 .Erratas: [1] (928 páginas) [2][3]
  24. ^ abcd Manual del desarrollador de software de arquitectura Intel, volumen 2: Referencia del conjunto de instrucciones (PDF) . Vol. 2. Intel Corporation . 1999. Archivado desde el original (PDF) el 2009-06-11 . Consultado el 2010-11-18 .
  25. ^ Ferrari, Adam; Batson, Alan; Lack, Mike; Jones, Anita (19 de noviembre de 2018) [primavera de 2006]. Evans, David (ed.). "Guía de ensamblaje x86". Ciencias de la computación CS216: Representación de programas y datos. Universidad de Virginia . Archivado desde el original el 24 de marzo de 2020. Consultado el 18 de noviembre de 2010 .
  26. ^ "Manual de arquitectura SPARC, versión 8" (PDF) . SPARC International . 1992. Archivado desde el original (PDF) el 2011-12-10 . Consultado el 2011-12-10 .
  27. ^ Moxham, James (1996). "ZINT Z80 Interpreter". Códigos operativos Z80 para ZINT . Archivado desde el original el 24 de marzo de 2020. Consultado el 21 de julio de 2013 .
  28. ^ Hyde, Randall . «Capítulo 8. MASM: Directivas y pseudocódigos de operación» (PDF) . El arte de la programación informática . Archivado (PDF) desde el original el 24 de marzo de 2020. Consultado el 19 de marzo de 2011 .
  29. ^ 1401 Autocoder System, Program #1401-AU-037, Version 3, Modification Level 11 (PDF) . 1965-12-07 . Consultado el 21 de enero de 2024 . La siguiente restricción o limitación menor está vigente con respecto al uso de 1401 Autocoder al codificar instrucciones macro ...
  30. ^ Griswold, Ralph E. (1972). "Capítulo 1". La implementación macro de SNOBOL4 . San Francisco, California, EE. UU.: WH Freeman and Company . ISBN 0-7167-0447-1.
  31. ^ "Macros (C/C++), MSDN Library para Visual Studio 2008". Microsoft Corp. 16 de noviembre de 2012. Archivado desde el original el 24 de marzo de 2020. Consultado el 22 de junio de 2010 .
  32. ^ Kessler, Marvin M. (18 de diciembre de 1970). "Informe *Conceptual* 14: Implementación de macros para permitir la programación estructurada en OS/360". MVS Software: Macros conceptuales 14 . Gaithersburg, Maryland, EE. UU.: International Business Machines Corporation . Archivado desde el original el 24 de marzo de 2020 . Consultado el 25 de mayo de 2009 .
  33. ^ "La función del kit de herramientas de ensamblador de alto nivel aumenta la productividad del programador". Cartas de anuncio . IBM . 12 de diciembre de 1995. A95-1432. Archivado desde el original el 7 de marzo de 2023.
  34. ^ Whitesmiths Ltd (15 de julio de 1980). Manual de referencia del lenguaje natural.
  35. ^ "lenguaje ensamblador: definición y mucho más de Answers.com". answers.com . Archivado desde el original el 2009-06-08 . Consultado el 2008-06-19 .
  36. ^ Provinciano, Brian (17 de abril de 2005). «NESHLA: el ensamblador 6502 de código abierto y alto nivel para el Nintendo Entertainment System». Archivado desde el original el 24 de marzo de 2020. Consultado el 24 de marzo de 2020 .
  37. ^ Dufresne, Steven (21 de agosto de 2018). «Kathleen Booth: ensamblando las primeras computadoras mientras inventaba el ensamblaje». Archivado desde el original el 24 de marzo de 2020. Consultado el 10 de febrero de 2019 .
  38. ^ ab Booth, Andrew Donald ; Britten, Kathleen Hylda Valerie (septiembre de 1947) [agosto de 1947]. Consideraciones generales en el diseño de una computadora digital electrónica multipropósito (PDF) (2.ª ed.). The Institute for Advanced Study, Princeton, Nueva Jersey, EE. UU.: Birkbeck College, Londres . Archivado (PDF) desde el original el 24 de marzo de 2020. Consultado el 10 de febrero de 2019. Las ideas no originales contenidas en el siguiente texto se han derivado de varias fuentes... Sin embargo, se considera que se debe agradecer al profesor John von Neumann y al doctor Herman Goldstein por las muchas discusiones fructíferas...
  39. ^ Campbell-Kelly, Martin (abril de 1982). "El desarrollo de la programación informática en Gran Bretaña (1945 a 1955)". IEEE Annals of the History of Computing . 4 (2): 121–139. doi :10.1109/MAHC.1982.10016. S2CID  14861159.
  40. ^ Campbell-Kelly, Martin (1980). "Programación del EDSAC: actividad de programación temprana en la Universidad de Cambridge". IEEE Annals of the History of Computing . 2 (1): 7–36. doi :10.1109/MAHC.1980.10009.
  41. ^ "Premio Pionero en Computación 1985 'Por programación en lenguaje ensamblador' David Wheeler". 27 de marzo de 2018.
  42. ^ Wilkes, Maurice Vincent (1949). "EDSAC: una máquina calculadora electrónica". Revista de instrumentos científicos . 26 (12): 385–391. Bibcode :1949JScI...26..385W. doi :10.1088/0950-7671/26/12/301.
  43. ^ da Cruz, Frank (17 de mayo de 2019). "La calculadora de tambor magnético IBM 650". Historia de la informática: una cronología de la informática. Universidad de Columbia . Archivado desde el original el 15 de febrero de 2020. Consultado el 17 de enero de 2012 .
  44. ^ Abell, John C. "15 de octubre de 1956: Fortran cambia para siempre la suerte de la informática". Wired . ISSN  1059-1028 . Consultado el 2 de marzo de 2024 .
  45. ^ Collen, Morris F. (marzo-abril de 1994). "Los orígenes de la informática". Revista de la Asociación Estadounidense de Informática Médica . 1 (2): 96–97. doi :10.1136/jamia.1994.95236152. PMC 116189 . PMID  7719803. 
  46. ^ Pettus, Sam (10 de enero de 2008). «SegaBase Volume 6 - Saturn». Archivado desde el original el 13 de julio de 2008. Consultado el 25 de julio de 2008 .{{cite web}}: CS1 maint: URL no apta ( enlace )
  47. ^ Kauler, Barry (9 de enero de 1997). Lenguaje ensamblador de Windows y programación de sistemas: programación de bajo nivel de 16 y 32 bits para PC y Windows. CRC Press . ISBN 978-1-48227572-8. Recuperado el 24 de marzo de 2020. Siempre hay un debate sobre la aplicabilidad del lenguaje ensamblador en nuestro mundo de programación moderno.
  48. ^ Hsieh, Paul (2020-03-24) [2016, 1996]. "Optimización de la programación". Archivado desde el original el 2020-03-24 . Consultado el 2020-03-24 . ... los cambios de diseño tienden a afectar el rendimiento más que ... no se debe pasar directamente al lenguaje ensamblador hasta que ...
  49. ^ "Índice TIOBE". Software TIOBE . Archivado desde el original el 2020-03-24 . Consultado el 2020-03-24 .
  50. ^ Rusling, David A. (1999) [1996]. "Capítulo 2 Fundamentos del software". El núcleo de Linux . Archivado desde el original el 24 de marzo de 2020. Consultado el 11 de marzo de 2012 .
  51. ^ ab Markoff, John Gregory (28 de noviembre de 2005). "Writing the Fastest Code, by Hand, for Fun: A Human Computer Keeps Speeding Up Chips" (Escribir el código más rápido, a mano, por diversión: una computadora humana sigue acelerando los chips). The New York Times . Seattle, Washington, EE. UU. Archivado desde el original el 23 de marzo de 2020. Consultado el 4 de marzo de 2010 .
  52. ^ "Bit-field-badness". hardwarebug.org . 2010-01-30. Archivado desde el original el 2010-02-05 . Consultado el 2010-03-04 .
  53. ^ "GCC hace un desastre". hardwarebug.org . 2009-05-13. Archivado desde el original el 2010-03-16 . Consultado el 2010-03-04 .
  54. ^ Hyde, Randall . "El gran debate". Archivado desde el original el 16 de junio de 2008. Consultado el 3 de julio de 2008 .
  55. ^ "El código fuente vuelve a fallar". hardwarebug.org . 2010-01-30. Archivado desde el original el 2010-04-02 . Consultado el 2010-03-04 .
  56. ^ Click, Cliff; Goetz, Brian. "Un curso intensivo sobre hardware moderno". Archivado desde el original el 24 de marzo de 2020. Consultado el 1 de mayo de 2014 .
  57. ^ "Programación 68K en Fargo II". Archivado desde el original el 2008-07-02 . Consultado el 2008-07-03 .
  58. ^ "BLAS Benchmark-Agosto 2008". eigen.tuxfamily.org. 2008-08-01. Archivado desde el original el 2020-03-24 . Consultado el 2010-03-04 .
  59. ^ "x264.git/common/x86/dct-32.asm". git.videolan.org. 29 de septiembre de 2010. Archivado desde el original el 4 de marzo de 2012. Consultado el 29 de septiembre de 2010 .
  60. ^ "rav1e/README.md en v0.6.3". GitHub . Archivado desde el original el 2023-02-22 . Consultado el 2023-02-21 .
  61. ^ "README.md · 1.1.0 · VideoLAN / dav1d". 13 de febrero de 2023. Archivado desde el original el 22 de febrero de 2023. Consultado el 21 de febrero de 2023 .
  62. ^ Bosworth, Edward (2016). «Capítulo 1: ¿Por qué estudiar lenguaje ensamblador?». www.edwardbosworth.com . Archivado desde el original el 24 de marzo de 2020. Consultado el 1 de junio de 2016 .
  63. ^ "Instrucciones de macro DFSMS para conjuntos de datos de z/OS versión 2, versión 3" (PDF) . IBM. 15 de febrero de 2019. Archivado (PDF) desde el original el 25 de junio de 2021. Consultado el 14 de septiembre de 2021 .
  64. ^ Paul, Matthias R. (2001) [1996], "Especificación y documentación de referencia para NECPINW", NECPINW.CPI - Controlador de cambio de página de código DOS para NEC Pinwriters (2.08 ed.), FILESPEC.TXT, NECPINW.ASM, EUROFONT.INC de NECPI208.ZIP, archivado desde el original el 2017-09-10 , recuperado el 2013-04-22
  65. ^ Paul, Matthias R. (13 de mayo de 2002). «[fd-dev] mkeyb». freedos-dev . Archivado desde el original el 10 de septiembre de 2018 . Consultado el 10 de septiembre de 2018 .

Lectura adicional

Enlaces externos