Articulo de referencia

lenguaje ensamblador

.asm , .s , .S , .inc , .wla , .SRC as well as several others depending on the assembler"},"file format":{"wt":""},"website":{"wt":""},"implementations":{"wt":""},"dialects":{"w...

En informática, el lenguaje ensamblador (alternativamente lenguaje ensamblador [ 1 ] o código máquina simbólico ), [ 2 ] [ 3 ] [ 4 ] a menudo denominado simplemente ensamblador 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 del lenguaje y las instrucciones del código máquina de la arquitectura . [ 5 ] El lenguaje ensamblador suele tener una instrucción por cada instrucción del código máquina (1:1), pero también se admiten generalmente constantes, comentarios , directivas del ensamblador , [ 6 ] etiquetas simbólicas de, por ejemplo, ubicaciones de memoria , registros y macros [ 7 ] [ 1 ] .

El primer código ensamblador en el que se utiliza un lenguaje para representar instrucciones de código máquina se encuentra en la obra de Kathleen y Andrew Donald Booth de 1947, 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 referirse a "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 en el ensamblaje del código fuente . El paso computacional en el que un ensamblador procesa un programa se denomina tiempo de ensamblaje .

Debido a que el lenguaje ensamblador depende de las instrucciones del código máquina, cada lenguaje ensamblador [ nb 1 ] es específico de una arquitectura de computadora particular , como x86 o ARM . [ 11 ] [ 12 ] [ 13 ]

A veces existe más de un ensamblador para la misma arquitectura, y a veces un ensamblador es específico de un sistema operativo o de sistemas operativos particulares. La mayoría de los lenguajes ensamblador no proporcionan una sintaxis específica para las llamadas al sistema operativo, y la mayoría de los lenguajes ensamblador 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 cuales se basan en última instancia todos los mecanismos de llamadas al sistema . A diferencia de los lenguajes ensamblador, 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 común que tanto la programación de sistemas como la de aplicaciones se realizaran íntegramente en lenguaje ensamblador. Si bien sigue siendo insustituible para algunos fines, la mayor parte de la programación se lleva a cabo actualmente en lenguajes interpretados y compilados de alto nivel. En « No Silver Bullet », Fred Brooks resumió los efectos del abandono de la programación en lenguaje ensamblador: «Sin duda, el golpe más poderoso para la productividad, la fiabilidad 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 este desarrollo al menos un aumento de cinco veces en la productividad, con las consiguientes mejoras en la fiabilidad, la simplicidad y la comprensibilidad». [ 14 ]

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

sintaxis del lenguaje ensamblador

El lenguaje ensamblador utiliza símbolos mnemotécnicos para representar instrucciones de máquina de bajo nivel ( códigos de operación ), directivas y, generalmente, registros y banderas de arquitectura . [ 16 ] Algunos de los mnemotécnicos 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 esta manera, los programadores se liberan de cálculos repetitivos tediosos y los programas en ensamblador 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 de programas, controlar el proceso de ensamblaje y ayudar en la depuración .

Algunos ensambladores tienen sintaxis orientada a columnas, con campos específicos en columnas específicas; esto era muy común en las máquinas que usaban tarjetas perforadas en las décadas de 1950 y principios de 1960. Algunos ensambladores tienen sintaxis de formato libre, con campos separados por delimitadores, por ejemplo, signos de puntuación o espacios en blanco . Algunos ensambladores son híbridos, con, por ejemplo, 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 la década de 1960.

Terminología

  • Un ensamblador de macros es un ensamblador que incluye una función de macroinstrucciones para que el texto en lenguaje ensamblador (parametrizado) pueda representarse mediante un nombre, y ese nombre pueda utilizarse para insertar el texto expandido en otro código.
    • El código abierto se refiere a cualquier entrada de ensamblador que no esté definida dentro de una macro.
  • Un ensamblador cruzado (véase también compilador cruzado ) es un ensamblador que se ejecuta en un ordenador o sistema operativo (el sistema anfitrión ) de un tipo diferente al del sistema en el que se ejecutará el código resultante (el sistema de destino ). El ensamblaje cruzado facilita el desarrollo de programas para sistemas que no disponen de los recursos necesarios para el desarrollo de software, como un sistema embebido o un microcontrolador . En tal caso, el código objeto resultante debe transferirse al sistema de destino mediante memoria de solo lectura (ROM, EPROM , etc.), un programador (cuando la memoria de solo lectura está integrada en el dispositivo, como en los microcontroladores) o un enlace de datos, utilizando una copia exacta bit a bit del código objeto o una representación textual de dicho código (como Intel hex o Motorola S-record ).
  • Un ensamblador de alto nivel es un programa que proporciona abstracciones de lenguaje más comúnmente asociadas con lenguajes de alto nivel, como estructuras de control avanzadas ( IF/THEN/ELSE , DO CASE, etc.) y tipos de datos abstractos de alto nivel, incluyendo estructuras/registros, uniones, clases y conjuntos.
  • Un microensamblador es un programa que ayuda a preparar un microprograma para controlar el funcionamiento de bajo nivel de un ordenador.
  • Un metaensamblador es "un programa que acepta la descripción sintáctica y semántica de un lenguaje ensamblador y genera un ensamblador para ese lenguaje" [ 17 ] o que acepta un archivo fuente de ensamblador junto con dicha descripción y ensambla el archivo fuente de acuerdo con esa descripción. Los ensambladores "Meta-Symbol" para las series de computadoras SDS 9 y SDS Sigma son metaensambladores. [ 18 ] Sperry Univac también proporcionó un metaensamblador para la serie UNIVAC 1100/2200 . [ 19 ]
  • El ensamblador en línea (o ensamblador embebido ) es código ensamblador contenido dentro de un programa en lenguaje de alto nivel. [ 20 ] Esto se usa con mayor frecuencia en programas de sistema que necesitan acceso directo al hardware.

Conceptos clave

Ensamblador

Un programa ensamblador crea código objeto traduciendo combinaciones de mnemónicos y sintaxis para operaciones y modos de direccionamiento a 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. [ 21 ] 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 sustitución textual, por ejemplo, para generar secuencias cortas comunes de instrucciones como inline , en lugar de subrutinas llamadas .

Algunos ensambladores también pueden realizar optimizaciones sencillas específicas del conjunto de instrucciones . Un ejemplo concreto son los omnipresentes ensambladores x86 de diversos proveedores. Mediante el dimensionamiento de saltos , [ 21 ] la mayoría de ellos pueden realizar reemplazos de instrucciones de salto (saltos largos reemplazados por saltos cortos o relativos) en cualquier número de pasadas, según se solicite. Otros incluso pueden realizar una simple reorganización o inserción de instrucciones, como algunos ensambladores para arquitecturas RISC que ayudan a optimizar una planificación de instrucciones adecuada para aprovechar la tubería de la CPU de la forma más eficiente posible. [ 22 ]

Los ensambladores existen desde la década de 1950, como primer paso previo al lenguaje máquina y a los lenguajes de programación de alto nivel como Fortran , Algol , COBOL y Lisp . También han existido diversas clases de traductores y generadores de código semiautomáticos con propiedades similares tanto al lenguaje 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 ser , en la sintaxisadd eax,[ebx] original de Intel , mientras que esta se escribiría en la sintaxis AT&T utilizada por el ensamblador GNU . A pesar de las diferentes apariencias, las diferentes formas sintácticas generalmente generan el mismo código 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 ).addl (%ebx),%eax

Número de pases

Existen dos tipos de ensambladores, según la cantidad de pasadas que se necesiten a través del código fuente (cuántas veces el ensamblador lee el código fuente) para producir el archivo objeto.

  • Los ensambladores de una sola pasada procesan el código fuente una sola vez. Para los símbolos utilizados antes de ser definidos, el ensamblador emitirá "erratas" después de la definición final, indicando al enlazador o al cargador que corrijan las ubicaciones donde se habían utilizado los símbolos aún no definidos.
  • Los ensambladores de múltiples pasadas crean una tabla con todos los símbolos y sus valores en las primeras pasadas, y luego utilizan esa tabla en pasadas posteriores para generar código.

En ambos casos, el ensamblador debe poder determinar el tamaño de cada instrucción en las pasadas 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 al encontrar la operación por primera vez y, si es necesario, la rellenará con una o más instrucciones de " no operación " en una pasada posterior o en la errata. En un ensamblador con optimización de "peephole" , las direcciones pueden recalcularse entre pasadas para permitir reemplazar el código pesimista con código adaptado a la distancia exacta del 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 requerí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 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 dicha 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. [ 23 ]

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 podría no estar definida. Un ensamblador de dos pasadas determinaría ambas direcciones en la primera pasada, por lo que se conocerían al generar el código en la segunda pasada.

S1 B DELANTERO ... EQUIPO DE ADELANTE * ... BKWD EQU * ... S2 B BKWD

Ensambladores de alto nivel

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

Consulte la sección "Diseño del idioma" a continuación para obtener más detalles.

lenguaje ensamblador

Un programa escrito en lenguaje ensamblador consta de una serie de instrucciones de procesador mnemotécnicas y meta-instrucciones (conocidas como operaciones declarativas, directivas, pseudo-instrucciones, pseudo-operaciones y pseudo-ops), comentarios y datos. Las instrucciones en lenguaje ensamblador suelen constar de un código de operación mnemotécnico seguido de un operando , que puede ser una lista de datos, argumentos o parámetros. [ 25 ] Algunas instrucciones pueden ser "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 requiere un operando. La instrucción resultante es traducida por un ensamblador a instrucciones en lenguaje máquina que pueden cargarse en 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 de esta instrucción es 10110 seguido de un identificador de 3 bits que indica qué registro usar. El identificador del registro AL es 000, por lo que el siguiente código máquina carga el registro AL con los datos 01100001. [ 25 ]

10110000 01100001

Este código informático 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 (abreviatura de move ) para instrucciones como esta, por lo que el código máquina anterior se puede escribir de la siguiente manera en lenguaje ensamblador, 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 decimal (61 hexadecimal)

En algunos lenguajes ensamblador (incluido este), el mismo mnemónico, como MOV, puede usarse 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 valores en registros o direcciones directas incrustadas en la instrucción. Otros ensambladores pueden usar mnemónicos de código de operación separados, como L para "mover memoria a registro", ST para "mover registro a memoria", LR para "mover registro a registro", MVI para "mover operando inmediato a memoria", etc.

Si se utiliza el mismo mnemónico para diferentes instrucciones, significa que el mnemónico corresponde a varios códigos de instrucción binarios 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:

88 E0

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, donde 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 un nombre de registro válido, por lo que solo la B0instrucción es 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 es aplicable.

Los lenguajes ensamblador siempre se diseñan de manera que esta falta de ambigüedad se imponga universalmente mediante 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' (equivalente a diez en decimal) se escribiría como 0Aho 0AH, no AH, específicamente para que no pueda parecer 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 contenga únicamente 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 AL , 10110001 ( B1) lo mueve a CL y 10110010 ( B2) lo hace a DL . A continuación se muestran ejemplos en lenguaje ensamblador. [ 25 ]

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

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

MOV EAX , [ EBX ] ; Mueve los 4 bytes de 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 ni recordar cuál. [ 25 ]

Un ensamblador transforma el lenguaje ensamblador en código máquina, y un desensamblador puede realizar la transformación inversa, al menos parcialmente . A diferencia de los lenguajes de alto nivel , existe una correspondencia uno a uno entre muchas instrucciones simples de ensamblador y las instrucciones del lenguaje máquina. Sin embargo, en algunos casos, un ensamblador puede proporcionar pseudoinstrucciones (esencialmente macros) que se expanden en varias instrucciones del lenguaje máquina para proporcionar funcionalidades de uso común. Por ejemplo, para una máquina que carece de la instrucción "saltar si es mayor o igual", un ensamblador puede proporcionar una pseudoinstrucción que se expanda a las instrucciones de la máquina "establecer si es menor que" y "saltar si es cero (en el resultado de la instrucción establecer)". La mayoría de los ensambladores completos también proporcionan un lenguaje de macros avanzado (que se describe más adelante) que utilizan los proveedores y programadores para generar secuencias de código y datos más complejas. Dado que la información sobre pseudoinstrucciones y macros definidas en el entorno del 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 del lenguaje ensamblador. Del mismo modo, dado que el ensamblador ignora los comentarios en el archivo fuente del lenguaje ensamblador y estos no tienen ningún efecto en el código objeto que genera, un desensamblador siempre es completamente incapaz de recuperar los comentarios del código fuente.

Cada arquitectura informática tiene su propio lenguaje máquina. Las computadoras difieren en la cantidad y el tipo de operaciones que admiten, en el tamaño y la cantidad de registros, y en la representación de los datos almacenados. Si bien la mayoría de las computadoras de propósito general pueden realizar esencialmente la misma funcionalidad, la forma en que lo hacen difiere; los lenguajes ensamblador correspondientes reflejan estas diferencias.

Para un mismo conjunto de instrucciones, pueden existir varios conjuntos de mnemónicos o sintaxis de lenguaje ensamblador, que normalmente se implementan en diferentes programas ensambladores. En estos casos, el más común suele ser el proporcionado por el fabricante de la CPU y utilizado en su documentación.

Dos ejemplos de CPU con conjuntos de mnemónicos diferentes son la familia Intel 8080 y la Intel 8086/8088. Dado que Intel reclamó los derechos de autor de sus mnemónicos en lenguaje ensamblador (al menos en cada página de su documentación publicada en las décadas de 1970 y principios de 1980), algunas empresas que producían de forma independiente CPU compatibles con los conjuntos de instrucciones de Intel inventaron sus propios mnemónicos. La CPU Zilog Z80 , una mejora de la Intel 8080A , admite todas las instrucciones de la 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 de la 8080A. Por ejemplo, mientras que Intel utiliza los mnemónicos MOV , MVI , LDA , STA , LXI , LDAX , STAX , LHLD y SHLD para diversas instrucciones de transferencia de datos, el lenguaje ensamblador Z80 utiliza el mnemónico LD para todas ellas. Un caso similar son las CPU NEC V20 y V30 , copias mejoradas de las Intel 8086 y 8088, respectivamente. Al igual que Zilog con la Z80, NEC inventó nuevos mnemónicos para todas las instrucciones de las 8086 y 8088, para evitar acusaciones de infracción de los derechos de autor de Intel. (Es cuestionable si tales derechos de autor pueden ser válidos, y compañías de CPU posteriores como AMD [ nb 4 ] y Cyrix republicaron los mnemónicos de instrucciones x86/IA-32 de Intel exactamente sin permiso ni sanció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 ensamblador para la misma arquitectura de conjunto de instrucciones son isomorfos (algo así como el inglés y el Pig Latin ), no hay obligación de usar el lenguaje ensamblador publicado por un fabricante con los productos de ese fabricante.

Ejemplos

"¡Hola, mundo!" en hardware x86 de 32 bits sin protección

"¡Hola, mundo!" se puede imprimir usando lenguaje ensamblador de 32 bits para un procesador x86 con poca ayuda del sistema operativo. "Call outchr" llama a un mecanismo que imprime un carácter en AL en la consola. Una cadena de caracteres distinta de cero debe terminar con un byte cero.

Hola: mov esi , msg ; dirección de la cadena en ESI cld ; Establecer la dirección para incrementar ESI lodsb ; Cargar el primer carácter en AL, inc ESI chrlp: call outchr ; Imprimir el carácter en AL lodsb ; Cargar el siguiente carácter en AL, inc ESI or al , al ; ¿Es un terminador cero? bne chrlp ; Si no, continuar ret ; Regresar a la función que la llamómsg: db '¡Hola, mundo!' , 0xa , 0x0 ; cadena que se imprimirá

"¡Hola, mundo!" en Linux x86 de 32 bits

En lenguaje ensamblador de 32 bits para Linux en un procesador x86 , "¡Hola, mundo!" se imprimiría mediante una sola llamada al sistema operativo:

sección .texto ; inicio del segmento de código global _start ; declarar _start para que sea visible en el archivo objeto generado _start: mov edx , len ; longitud de la cadena, tercer argumento de write() mov ecx , msg ; dirección de la cadena, segundo argumento de write() mov ebx , 1 ; descriptor de archivo (salida estándar), primer argumento de write() mov eax , 4 ; número de llamada al sistema para write() int 0x80 ; trampa de llamada al sistema mov ebx , 0 ; código de salida, primer argumento de exit() mov eax , 1 ; número de llamada al sistema para exit() int 0x80 ; trampa de llamada al sistemasección .data ; inicio del segmento de datos msg db '¡Hola, mundo!' , 0xa ; cadena a imprimir len equ $ - msg ; longitud de esa cadena como una constante calculada en tiempo de ensamblaje

Diseño de lenguaje

Elementos básicos

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

Mnemotecnia de códigos de operación y mnemotecnia extendida

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 sola instrucción ejecutable en lenguaje máquina (un opcode ), y hay al menos un mnemónico de opcode definido para cada instrucción en lenguaje máquina. Cada instrucción normalmente consta de una operación o opcode más cero o más operandos . La mayoría de las instrucciones se refieren a un solo 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 otro lugar de la memoria. Esto viene 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 de System/360 usan Bcomo mnemónico extendido para BCcon una máscara de 15 y NOP("NO OPeration" – no hacer nada durante un paso) para BCcon una máscara de 0.

Los mnemónicos extendidos se utilizan a menudo para admitir usos especializados de las instrucciones, a menudo para propósitos 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 pueden usarse para ese propósito. En las CPU 8086, la instrucción se usa 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 de IBM para System/360 y System/370 usan los mnemónicos extendidos y para y con máscaras de cero. Para la arquitectura SPARC, estas se conocen como instrucciones sintéticas . [ 27 ]xchgax,axnopnopxchgax,axxchgax,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 para generar ld l,cseguida de ld h,b. [ 28 ] A veces se les 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 debían usar todos los ensambladores. [ 29 ] El estándar fue retirado posteriormente.

Directivas de datos

Existen instrucciones que se utilizan para definir elementos de datos que almacenan información y variables. Estas instrucciones definen el tipo de datos, su longitud y su alineación . También pueden definir si los datos están disponibles para programas externos (programas compilados 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 pseudocódigos de operación, pseudooperaciones o pseudo-ops, son comandos que se le dan a un ensamblador para que realice operaciones distintas a las instrucciones de ensamblaje. [ 21 ] Las directivas afectan el funcionamiento del 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 pseudocódigo de operación se reserva para directivas que generan código objeto, como las que generan datos. [ 30 ]

Los nombres de las pseudooperaciones suelen comenzar con un punto para distinguirlas de las instrucciones de máquina. Las pseudooperaciones pueden hacer que el ensamblaje del programa dependa de los parámetros introducidos por el programador, de modo que un mismo programa pueda ensamblarse de diferentes maneras, quizás para distintas aplicaciones. También pueden utilizarse para manipular la presentación de un programa y facilitar su lectura y mantenimiento. Otro uso común de las pseudooperaciones es reservar áreas de almacenamiento para datos en tiempo de ejecución e inicializar opcionalmente 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 diversas constantes. Generalmente, a cada constante y variable se le asigna un nombre para que las instrucciones puedan referenciar esas ubicaciones por su nombre, lo que fomenta la autodocumentación del código . En el código ejecutable, el nombre de cada subrutina se asocia con su punto de entrada, de modo que cualquier llamada a una subrutina puede usar su nombre. Dentro de las subrutinas, a los destinos GOTO se les asignan 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 , ofrecen una gestión flexible de símbolos, lo que permite a los programadores administrar diferentes espacios de nombres , calcular automáticamente desplazamientos dentro de las estructuras de datos y asignar etiquetas que hacen referencia a valores literales o al resultado de cálculos sencillos realizados por el ensamblador. Las etiquetas también se pueden usar para inicializar constantes y variables con direcciones reubicables.

Los lenguajes ensamblador, al igual que la mayoría de los lenguajes de programación, permiten añadir comentarios al código fuente del programa , los cuales se ignoran durante el ensamblaje. Un buen uso de los comentarios es fundamental en los programas en lenguaje ensamblador, ya que el significado y la finalidad de una secuencia de instrucciones binarias de máquina pueden ser difíciles de determinar. El código ensamblador "en bruto" (sin comentarios) generado por compiladores o desensambladores resulta bastante difícil de leer cuando es necesario realizar modificaciones.

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 insertan variables y constantes. La definición de la macro suele ser [ nb 5 ] una combinación de instrucciones de ensamblador, por ejemplo, directivas, instrucciones de máquina simbólicas y plantillas para instrucciones de ensamblador. Esta secuencia de líneas de texto puede incluir códigos de operación o directivas. Una vez definida una macro, su nombre puede utilizarse en lugar de un mnemónico. Cuando el ensamblador procesa dicha instrucción, la reemplaza con las líneas de texto asociadas a esa macro y, a continuación, las procesa como si existieran en el archivo de código fuente (incluida, en algunos ensambladores, la expansión de cualquier macro existente en el texto de reemplazo). Las macros en este sentido se remontan a los autocodificadores de IBM de la década de 1950. [ 31 ]

Los ensambladores de macros suelen tener directivas para, por ejemplo, definir macros, definir variables, asignar a las variables el resultado de una expresión aritmética, lógica o de cadena, iterar y generar código condicionalmente. Algunas de estas directivas pueden estar restringidas al uso dentro de una definición de macro, por ejemplo, MEXIT en HLASM , mientras que otras pueden estar permitidas en 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 usa normalmente para crear macros cortas de una sola línea. Las instrucciones macro del ensamblador, al igual que las macros en PL/I y otros lenguajes, pueden ser "programas" extensos por sí mismos, ejecutados por interpretación del ensamblador durante el ensamblaje.

Dado que las macros pueden tener nombres cortos pero expandirse a varias líneas de código, se pueden usar para que los programas en lenguaje ensamblador parezcan mucho más cortos, requiriendo menos líneas de código fuente, al igual que con los lenguajes de alto nivel. También se pueden usar para añadir niveles superiores de estructura a los programas en ensamblador, e incluso introducir código de depuración integrado mediante parámetros y otras funciones similares.

Los ensambladores de macros suelen permitir que las macros acepten parámetros . Algunos incluyen lenguajes de macros bastante sofisticados, que incorporan elementos de lenguajes 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 determinada, y que permiten a las macros guardar el contexto o intercambiar información. De este modo, una macro puede generar numerosas instrucciones en lenguaje ensamblador o definiciones de datos, basándose en sus argumentos. Esto podría utilizarse para generar estructuras de datos tipo registro o bucles desenrollados , por ejemplo, o incluso algoritmos completos basados ​​en parámetros complejos. Por ejemplo, una macro de ordenación podría aceptar la especificación de una clave de ordenación compleja y generar código diseñado específicamente para esa clave, sin necesidad de las pruebas en tiempo de ejecución que requeriría un procedimiento general que interprete la especificación. Una organización que utiliza lenguaje ensamblador y que ha sido ampliamente ampliada mediante un conjunto de macros de este tipo puede considerarse que trabaja en un lenguaje de alto nivel, ya que dichos programadores no trabajan con los elementos conceptuales de nivel más bajo de un ordenador. Para ilustrar este punto, se utilizaron macros para implementar una máquina virtual temprana en SNOBOL4 (1967), que estaba escrita en el lenguaje de implementación de SNOBOL (SIL), un lenguaje ensamblador para máquinas virtuales. La máquina de destino traducía esto a su código nativo mediante un ensamblador de macros . [ 32 ] Esto permitía un alto grado de portabilidad para la época.

En la era de los mainframes, las macros se utilizaban para personalizar sistemas de software a gran escala para clientes específicos, y también eran empleadas por el personal de los clientes para satisfacer las necesidades de sus empleadores mediante la creación de versiones específicas de los sistemas operativos del fabricante. Esto se hacía, por ejemplo, por programadores de sistemas que trabajaban con el Conversational Monitor System / Virtual Machine ( VM/CMS ) de IBM y con los complementos de IBM para el procesamiento de transacciones en tiempo real, el Customer Information Control System (CICS ) y el ACP / TPF , el sistema para aerolíneas y finanzas que comenzó en la década de 1970 y que aún hoy gestiona muchos sistemas de reservas informáticas (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 mediante 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 generar código arbitrario. IBM OS/360 utiliza macros para la generación del sistema . El usuario especifica las opciones mediante la codificación de una serie de macros de ensamblador. El ensamblaje de estas macros genera un flujo de trabajo para construir el sistema, incluyendo instrucciones de control de trabajo y de utilidades .

Esto se debe a que, como se comprendió en la década de 1960, el concepto de "macroprocesamiento" es independiente del concepto de "ensamblador", ya que, en términos modernos, el primero se asemeja más al procesamiento de texto que a la generación de código objeto. El concepto de macroprocesamiento surgió, y sigue surgiendo, en el lenguaje de programación C, que admite "instrucciones de preprocesador" para definir variables y realizar pruebas condicionales sobre sus valores. A diferencia de ciertos procesadores de macros anteriores dentro de los ensambladores, el preprocesador de C no es Turing-completo porque carece de la capacidad de iterar o de "ir a", lo que permite que los programas se ejecuten en bucle.

A pesar del poder del procesamiento de macros, cayó en desuso en muchos lenguajes de alto nivel (con la importante excepción de C , C++ y PL/I), mientras que siguió siendo una herramienta fundamental para los ensambladores.

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

foo: macro a cargar a*b

La intención era que quien llamara 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, se produce la expansión de macro de load a-c*b. 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 quienes llaman pueden poner entre paréntesis los parámetros de entrada. [ 33 ]

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, [ 34 ] 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 el 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 High Level Assembler Toolkit de IBM [ 35 ] incluye un paquete de macros de este tipo.

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

Desde el declive del desarrollo a gran escala del lenguaje ensamblador, ha habido poca demanda aparente de ensambladores más sofisticados. [ 37 ] A pesar de ello, todavía se desarrollan y aplican en casos donde las limitaciones de recursos o las peculiaridades de la arquitectura del sistema de destino impiden el uso efectivo de lenguajes de alto nivel. [ 38 ]

Los ensambladores con un potente motor de macros permiten la programación estructurada mediante macros, como la macro switch que se incluye en el paquete Masm32 (este código es un programa completo):

include \ masm32 \ include \ masm32rt.inc ; usar 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 demás 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 "cases 1 a 3: other" .endif case 4 , 6 , 8 print "cases 4, 6 u 8" default mov ebx , 19 ; print 20 stars .Repeat print "*" dec ebx .Until Sign? ; bucle hasta que se establezca el indicador de signo endsw print chr$ ( 13 , 10 ) ENDM salir fin demomain

Uso del lenguaje ensamblador

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

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

Los lenguajes ensamblador eliminaron gran parte de la programación de primera generación, propensa a errores, tediosa y lenta, necesaria con las primeras computadoras, liberando a los programadores de tareas tediosas como recordar códigos numéricos y calcular direcciones. En su momento, se utilizaron ampliamente para todo tipo de programación. A finales de la década de 1950, su uso había sido en gran medida reemplazado por lenguajes de alto nivel en la búsqueda de una mayor productividad en la programación . [ 46 ] Hoy en día, el lenguaje ensamblador todavía se utiliza para la manipulación directa del hardware, el acceso a instrucciones especializadas del procesador o para abordar problemas críticos de rendimiento. [ 47 ] Los usos típicos son controladores de dispositivos , sistemas embebidos de bajo nivel y sistemas en tiempo real (véase §  Uso actual ).

Numerosos programas se escribieron íntegramente en lenguaje ensamblador. El Burroughs MCP (1961) fue el primer ordenador cuyo sistema operativo no se desarrolló completamente en lenguaje ensamblador; se escribió en ESPOL ( Executive Systems Problem Oriented Language ), un dialecto de Algol. Muchas aplicaciones comerciales también se escribieron en lenguaje ensamblador, incluyendo gran parte del software para mainframes de IBM desarrollado por grandes corporaciones. COBOL , FORTRAN y algunos lenguajes 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 principal lenguaje de desarrollo para computadoras domésticas de 8 bits como la Apple II , las computadoras Atari de 8 bits , la ZX Spectrum y la 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 la Atari 2600 y la Nintendo Entertainment System . [ 48 ]

El software clave para los compatibles con IBM PC, 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 renderizació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 la Sega Saturn , [ 49 ] y como lenguaje principal para el hardware arcade que utilizaba la CPU/GPU integrada TMS34010 , como Mortal Kombat y NBA Jam .

Uso actual

Se ha debatido sobre la utilidad y el rendimiento del lenguaje ensamblador en relación con los lenguajes de alto nivel. [ 50 ]

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

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. [ 52 ] El ensamblador se puede utilizar para optimizar la velocidad o el tamaño. En el caso de la optimización de velocidad, se afirma que los compiladores optimizadores modernos [ 53 ] convierten lenguajes de alto nivel en código que puede ejecutarse tan rápido como el ensamblador escrito a mano, a pesar de algunos contraejemplos. [ 54 ] [ 55 ] [ 56 ] 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 ensamblador. [ 57 ] [ 58 ] El aumento del rendimiento del procesador ha significado que la mayoría de las CPU permanecen inactivas la mayor parte del tiempo, [ 59 ] con retrasos causados ​​por cuellos de botella predecibles como fallos de caché, operaciones de E/S y paginación , lo que hace que la velocidad de ejecución del código bruto no sea un problema para muchos programadores.

Todavía existen ciertos ámbitos de la programación informática en los que el uso de la programación en lenguaje ensamblador es más común:

  • Escribir código para sistemas con procesadores antiguos que tienen opciones limitadas de lenguaje de alto nivel como Atari 2600 , Commodore 64 y calculadoras gráficas . [ 60 ] Los programas para estas computadoras de las décadas de 1970 y 1980 a menudo se escriben en el contexto de las subculturas demoscene o retrogaming .
  • Código que debe interactuar directamente con el hardware, por ejemplo, en controladores de dispositivos y manejadores de interrupciones .
  • En un procesador integrado o DSP , las interrupciones de alta frecuencia requieren el menor número de ciclos por interrupción, como por ejemplo una interrupción que se produce 1000 o 10000 veces por segundo.
  • Programas que necesitan usar instrucciones específicas del procesador no implementadas en un compilador. Un ejemplo común es la instrucción de rotación de bits , que es fundamental en muchos algoritmos de cifrado, así como la consulta de la paridad de un byte o el acarreo de 4 bits de una suma.
  • Archivos ejecutables independientes que deben ejecutarse sin recurrir a los componentes o bibliotecas de tiempo de ejecución asociados con un lenguaje de alto nivel, como el firmware para teléfonos, sistemas de combustible y encendido de automóviles, sistemas de control de aire acondicionado y sistemas de seguridad.
  • Programas con bucles internos sensibles al rendimiento, donde el lenguaje ensamblador ofrece oportunidades de optimización difíciles de lograr en un lenguaje de alto nivel. Por ejemplo, álgebra lineal con BLAS [ 54 ] [ 61 ] o transformación discreta del coseno (por ejemplo, versión de ensamblador SIMD de x264 [ 62 ] ).
  • Programas que crean funciones vectorizadas para programas en lenguajes de alto nivel como C. En el lenguaje de alto nivel, esto a veces se facilita mediante funciones intrínsecas del compilador que se asignan directamente a los mnemónicos SIMD, pero que, no obstante, dan como resultado una conversión de ensamblador uno a uno específica para el procesador vectorial dado.
  • Programas en tiempo real como simulaciones, sistemas de navegación aérea y equipos médicos. Por ejemplo, en un sistema fly-by-wire , la telemetría debe interpretarse y procesarse dentro de estrictos límites de tiempo. Estos sistemas deben eliminar las fuentes de retrasos impredecibles, que pueden ser causadas por lenguajes interpretados, recolección automática de basura , paginación o multitarea preventiva . Elegir lenguaje ensamblador o de bajo nivel para estos sistemas brinda a los programadores mayor visibilidad y control sobre los detalles del procesamiento.
  • Algoritmos criptográficos que deben tardar siempre exactamente el mismo tiempo en ejecutarse, lo que impide los ataques de temporización .
  • Los codificadores y decodificadores de vídeo como rav1e (un codificador para AV1 ) [ 63 ] y dav1d (el decodificador de referencia para AV1) [ 64 ] contienen código ensamblador para aprovechar las instrucciones AVX2 y ARM Neon cuando estén disponibles.
  • Modificar y extender el código heredado escrito para las computadoras centrales de IBM . [ 65 ] [ 66 ]
  • Situaciones en las que se requiere un control total del entorno, en situaciones de seguridad extremadamente alta en las que nada se puede dar por sentado .
  • Virus informáticos , gestores de arranque , determinados controladores de dispositivos u otros elementos muy cercanos al hardware o al sistema operativo de bajo nivel.
  • Simuladores de conjuntos de instrucciones para monitorización, seguimiento y depuración, donde la sobrecarga adicional se reduce al mínimo.
  • Situaciones en las que no existe un lenguaje de alto nivel, en un procesador nuevo o especializado para el que no hay disponible un compilador cruzado .
  • Ingeniería inversa y modificación de archivos de programas tales como:
    • binarios existentes que pueden o no haber sido escritos originalmente en un lenguaje de alto nivel, por ejemplo, al intentar recrear programas para los que no se dispone del código fuente o se ha perdido, o al descifrar la protección anticopia de software propietario.
    • Los videojuegos (también llamados ROM hacking ) se pueden modificar mediante varios métodos. El método más utilizado consiste en alterar el código del programa a nivel de 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 pocos programadores hoy en día trabajan regularmente con el lenguaje ensamblador como herramienta, los conceptos subyacentes siguen siendo importantes. Temas fundamentales como la aritmética binaria , la asignación de memoria , el procesamiento de la pila , la codificación de conjuntos de caracteres , el procesamiento de interrupciones y el diseño de compiladores serían difíciles de estudiar en detalle sin comprender cómo funciona una computadora a nivel de hardware. Dado que el comportamiento de una computadora 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 las computadoras modernas 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 su uso podría ser apropiado y ver cómo se puede crear código ejecutable eficiente a partir de lenguajes de alto nivel. [ 24 ]

Aplicaciones típicas

  • El lenguaje ensamblador se utiliza normalmente en el código de arranque del sistema , el código de bajo nivel que inicializa y prueba el hardware antes de iniciar el sistema operativo y que suele almacenarse en la ROM . ( La BIOS en los sistemas PC compatibles con IBM y CP/M son un ejemplo).
  • El lenguaje ensamblador se utiliza a menudo para código de bajo nivel, por ejemplo, para los núcleos de los sistemas operativos , que no pueden depender de la disponibilidad de llamadas al sistema preexistentes y deben implementarlas para la arquitectura de procesador particular en la que se ejecutará el sistema.
  • Algunos compiladores traducen primero los lenguajes de alto nivel a lenguaje ensamblador antes de compilar completamente, lo que permite visualizar el código ensamblador con fines de depuración y optimización.
  • Algunos compiladores para lenguajes de bajo nivel, como Pascal o C , permiten al programador integrar lenguaje ensamblador directamente en el código fuente (lo que se conoce como ensamblador en línea ). Los programas que utilizan estas funcionalidades pueden construir abstracciones con diferentes lenguajes ensamblador en cada plataforma de hardware. El código portable del sistema puede entonces utilizar estos componentes específicos del procesador a través de una interfaz uniforme.
  • El lenguaje ensamblador es útil en la ingeniería inversa . Muchos programas se distribuyen únicamente en código máquina, que es fácil de traducir a lenguaje ensamblador mediante un desensamblador , pero más difícil de traducir a un lenguaje de alto nivel mediante un descompilador . Herramientas como el Desensamblador Interactivo hacen un uso extensivo del desensamblaje para este propósito. Esta técnica la utilizan los hackers para vulnerar software comercial y la competencia para producir software con resultados similares de otras empresas.
  • El lenguaje ensamblador se utiliza para mejorar la velocidad de ejecución, especialmente en los primeros ordenadores personales con potencia de procesamiento y memoria RAM limitadas.
  • Los ensambladores pueden utilizarse para generar bloques de datos, sin la sobrecarga de un lenguaje de alto nivel, a partir de código fuente formateado y comentado, para ser utilizados por otro código. [ 67 ] [ 68 ]

Véase también

Notas

  1. Excepto 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 forma idéntica. El 8086 y varias otras CPU de finales de la década de 1970 y principios de la de 1980 tienen redundancias en sus conjuntos de instrucciones, porque era más sencillo para los ingenieros diseñar estas CPU (para que cupieran en chips de silicio de tamaño limitado) con los códigos redundantes que eliminarlos (ver términos indiferentes ). Cada ensamblador normalmente generará solo una de dos o más codificaciones de instrucciones redundantes, pero un desensamblador generalmente reconocerá cualquiera de ellas.
  4. AMD fabricó procesadores Intel 8086, 8088 y 80286 de segunda mano, y quizás también procesadores 8080A y 8085A, bajo licencia de Intel, pero a partir del 80386, Intel se negó a compartir sus diseños de procesadores x86 con nadie —AMD demandó por incumplimiento de contrato— y AMD diseñó, fabricó y vendió procesadores de la familia x86 de 32 y 64 bits sin la ayuda ni 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 las utilicen los generadores de macros.

Referencias

  1. 1 2 "Lenguaje ensamblador" . Ensamblador de alto nivel para z/OS, z/VM y z/VSE. Referencia del lenguaje. Versión 1. Edición 6. IBM . 2014 [1990] . SC26-4940-06.
  2. "Ensamblaje: Revisión" (PDF) . Ciencias de la Computación e Ingeniería. Facultad de Ingeniería, Universidad Estatal de Ohio . 2016. Archivado (PDF) del original el 24 de marzo de 2020. Recuperado el 24 de marzo de 2020 .
  3. Archer, Benjamin (noviembre de 2016). Assembly Language For Students . 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-5ISSN 1863-7310 . S2CID 195930813. Programar en lenguaje ensamblador tiene las mismas ventajas que programar en lenguaje máquina, excepto que es más fácil.  
  5. Saxon, James A.; Plette, William S. (1962). Programming the IBM 1401, a self-instructional programmed manual . Englewood Cliffs, Nueva Jersey, EE. UU.: Prentice-Hall . LCCN 62-20615 . (Nota: Se utiliza el término programa de ensamblaje ).
  6. Kornelis, AF (2010) [2003]. "Ensamblador de alto nivel: descripción general de los códigos de operación, directivas del ensamblador" . Archivado del original el 24 de marzo de 2020. Recuperado el 24 de marzo de 2020 .
  7. "Instrucciones macro" . High Level Assembler for z/OS & z/VM & z/VSE Language Reference Version 1 Release 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 . Recuperado 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 de 1982 ). Tomash Publishers . ISBN  978-0-93822803-5OCLC 313593586 {{cite book}}: Incompatibilidad de ISBN/Fecha ( ayuda )
  10. Fairhead, Harry (16 de noviembre de 2017). "Historia de los lenguajes de programación: la década clásica de 1950" . I Programmer . Archivado del original el 2 de enero de 2020. Consultado el 6 de marzo de 2020 .
  11. "¿Cómo dependen los lenguajes ensamblador de los sistemas operativos?" . Stack Exchange . Stack Exchange Inc. 28/07/2011. Archivado del original el 24/03/2020 . Consultado el 24/03/2020 .(Nota: Las llamadas al sistema suelen variar, por ejemplo, entre MVS , VSE y VM/CMS; los formatos binarios/ejecutables para los 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. págs. 326–360 . doi : 10.1016/b978-012068377-2/50013-9 . ISBN  9780120683772El lenguaje ensamblador (o Assembler) 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 las instrucciones que entiende una CPU específica, de forma uno a uno. Estos mnemónicos del ensamblador constituyen el conjunto de instrucciones de ese procesador.
  13. Carnes, Beau (27 de abril de 2022). "Aprende programación en lenguaje ensamblador con ARM" . freeCodeCamp.org . Consultado el 21 de junio de 2022. El lenguaje ensamblador suele ser específico de una arquitectura de computadora particular, por lo que existen varios tipos de lenguajes ensamblador. ARM es un lenguaje ensamblador cada vez más popular.
  14. Brooks, Frederick P. (1986). "No hay una solución mágica: esencia y casualidad 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. "linux kernel mainline 4.9 sloccount.txt" . Gist . Consultado el 4 de mayo de 2022 .
  16. "¿Qué es el lenguaje ensamblador?" . GeeksforGeeks . 19-10-2023 . Consultado el 24-04-2026 .
  17. Daintith, John, ed. (2019). "meta-assembler" . A Dictionary of Computing . Archivado del original el 24 de marzo de 2020. Recuperado el 24 de marzo de 2020 .
  18. Xerox Data Systems (octubre de 1975). Manual de referencia de lenguaje y operaciones de computadoras Xerox Meta-Symbol Sigma 5-9 (PDF) . pág. vi. Archivado (PDF) del original el 9 de octubre de 2022. Consultado el 7 de junio de 2020. Utilizado como un metaensamblador, permite al usuario diseñar sus propios lenguajes de programación y generar procesadores para dichos lenguajes con un mínimo esfuerzo. 
  19. Sperry Univac Computer Systems (1977). Referencia del programador del metaensamblador (MASM) de Sperry Univac Computer Systems (PDF) . Archivado (PDF) del original el 09/10/2022 . Consultado el 07/06/2020 .
  20. "Cómo usar lenguaje ensamblador en línea en código C" . gnu.org . Consultado el 5 de noviembre de 2020 .
  21. 1 2 3 4 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.). Chichester, West Sussex, Reino Unido: Ellis Horwood Limited / Simon & Schuster International Group . págs. 7, 237–238 . ISBN   0-13-052564-2. Archivado (PDF) del original el 23-03-2020 . Consultado el 01-10-2008 .(xiv+294+4 páginas)
  22. 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 segmentación estática de instrucciones» . Actas de la 14.ª conferencia ACM SIGPLAN/SIGBED sobre lenguajes, compiladores y herramientas para sistemas embebidos . págs. 33–44 . doi : 10.1145/2465554.2465559 . ISBN  9781450320856. S2CID 8015812 . 
  23. Beck, Leland L. (1996). "2". Software de sistema: Una introducción a la programación de sistemas . Addison Wesley .
  24. 1 2 Hyde, Randall (septiembre de 2003) [1996-09-30]. "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 del original el 6 de mayo de 2010. Consultado el 22 de junio de 2020 .Erratas:(928 páginas)
  25. 1 2 3 4 Manual del desarrollador de software de la arquitectura Intel, Volumen 2: Referencia del conjunto de instrucciones (PDF) . Vol. 2. Intel Corporation . 1999. Archivado del original (PDF) el 11 de junio de 2009. Recuperado el 18 de noviembre de 2010 . 
  26. Ferrari, Adam; Batson, Alan; Lack, Mike; Jones, Anita (19 de noviembre de 2018) [Primavera de 2006]. Evans, David (ed.). "Guía de ensamblador x86" . Ciencias de la Computación CS216: Representación de programas y datos. Universidad de Virginia . Archivado del original el 24 de marzo de 2020. Recuperado el 18 de noviembre de 2010 .
  27. "Manual de arquitectura SPARC, versión 8" (PDF) . SPARC International . 1992. Archivado del original (PDF) el 10 de diciembre de 2011. Consultado el 10 de diciembre de 2011 .
  28. Moxham, James (1996). "Intérprete ZINT Z80" . Códigos de operación Z80 para ZINT . Archivado del original el 24 de marzo de 2020. Recuperado el 21 de julio de 2013 .
  29. IEEE Std 694-1985: Norma IEEE para el lenguaje ensamblador de microprocesadores . IEEE Computer Society. 1985. ISBN 0-7381-2752-3OCLC 1415906564 
  30. Hyde, Randall . "Capítulo 8. MASM: Directivas y pseudocódigos de operación" (PDF) . El arte de la programación informática . Archivado (PDF) del original el 24 de marzo de 2020. Recuperado el 19 de marzo de 2011 .
  31. Sistema Autocoder 1401, Programa n.° 1401-AU-037, Versión 3, Nivel de modificación 11 (PDF) . 7 de diciembre de 1965. Consultado el 21 de enero de 2024. La siguiente restricción o limitación menor está vigente con respecto al uso del Autocoder 1401 al codificar instrucciones macro...
  32. 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.
  33. "Macros (C/C++), Biblioteca MSDN para Visual Studio 2008" . Microsoft Corp. 16 de noviembre de 2012. Archivado del original el 24 de marzo de 2020. Consultado el 22 de junio de 2010 .
  34. 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: Concepto 14 Macros . Gaithersburg, Maryland, EE. UU.: International Business Machines Corporation . Archivado del original el 24 de marzo de 2020. Consultado el 25 de mayo de 2009 .
  35. "Una 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 del original el 7 de marzo de 2023.
  36. Whitesmiths Ltd (15-07-1980). Manual de referencia del lenguaje natural A.
  37. "Lenguaje ensamblador: Definición y mucho más de Answers.com" . answers.com . Archivado del original el 8 de junio de 2009. Consultado el 19 de junio de 2008 .
  38. Provinciano, Brian (17 de abril de 2005). "NESHLA: El ensamblador 6502 de alto nivel y código abierto para Nintendo Entertainment System" . Archivado del original el 24 de marzo de 2020. Consultado el 24 de marzo de 2020 .
  39. Dufresne, Steven (21 de agosto de 2018). "Kathleen Booth: Ensamblando las primeras computadoras mientras inventaba el lenguaje ensamblador" . Archivado del original el 24 de marzo de 2020. Recuperado el 10 de febrero de 2019 .
  40. 1 2 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 de propósito general (PDF) (2.ª ed.). The Institute for Advanced Study, Princeton, Nueva Jersey, EE. UU.: Birkbeck College, Londres . Archivado (PDF) del original el 24 de marzo de 2020. Recuperado 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 reconocer la contribución del Prof. John von Neumann y del Dr. Herman Goldstein por las numerosas y fructíferas discusiones... 
  41. 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 . 
  42. Campbell-Kelly, Martin (1980). "Programando el 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 .
  43. "Premio Pionero de la Informática de 1985 'Por programación en lenguaje ensamblador' David Wheeler" . 27 de marzo de 2018.
  44. Wilkes, Maurice Vincent (1949). "El EDSAC: una máquina de cálculo electrónica". Journal of Scientific Instruments . 26 (12): 385– 391. Bibcode : 1949JScI...26..385W . doi : 10.1088/0950-7671/26/12/301 .
  45. 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 del original el 15 de febrero de 2020. Consultado el 17 de enero de 2012 .
  46. Abell, John C. "15 de octubre de 1956: Fortran cambia para siempre el destino de la informática" . Wired . ISSN 1059-1028 . Consultado el 2 de marzo de 2024 . 
  47. Collen, Morris F. (marzo-abril de 1994). " Los orígenes de la informática" . Journal of the American Medical Informatics Association . 1 (2): 96– 97. doi : 10.1136/jamia.1994.95236152 . PMC 116189. PMID 7719803 .  
  48. "Historia simplificada de las consolas de juegos retro para programadores" . pikuma.com . Consultado el 16 de abril de 2026 .
  49. Pettus, Sam (10 de enero de 2008). "SegaBase Volumen 6 - Saturno" . Archivado del original el 13 de julio de 2008. Recuperado el 25 de julio de 2008 .
  50. Kauler, Barry (1997-01-09). Windows Assembly Language and Systems Programming: 16- and 32-Bit Low-Level Programming for the PC and Windows . CRC Press . ISBN 978-1-48227572-8. Consultado el 24 de marzo de 2020 . El debate sobre la aplicabilidad del lenguaje ensamblador en nuestro mundo de programación moderno sigue vigente.
  51. Hsieh, Paul (24-03-2020) [2016, 1996]. "Optimización de la programación" . Archivado del original el 24-03-2020 . Recuperado el 24-03-2020 . ... los cambios de diseño tienden a afectar el rendimiento más que... uno no debería pasar directamente al lenguaje ensamblador hasta...
  52. "Índice TIOBE" . Software TIOBE . Archivado del original el 24 de marzo de 2020. Consultado el 24 de marzo de 2020 .
  53. Rusling, David A. (1999) [1996]. "Capítulo 2 Fundamentos del software" . El núcleo de Linux . Archivado del original el 24 de marzo de 2020. Recuperado el 11 de marzo de 2012 .
  54. 1 2 Markoff, John Gregory (28 de noviembre de 2005). "Escribiendo 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 del original el 23 de marzo de 2020. Recuperado el 4 de marzo de 2010 .
  55. "Bit-field-badness" . hardwarebug.org . 30/01/2010. Archivado del original el 05/02/2010 . Consultado el 04/03/2010 .
  56. "GCC hace un desastre" . hardwarebug.org . 13 de mayo de 2009. Archivado del original el 16 de marzo de 2010. Consultado el 4 de marzo de 2010 .
  57. Hyde, Randall . "El gran debate" . Archivado del original el 16 de junio de 2008. Consultado el 3 de julio de 2008 .
  58. "El código fuente vuelve a fallar" . hardwarebug.org . 30/01/2010. Archivado del original el 02/04/2010 . Consultado el 04/03/2010 .
  59. Click, Cliff ; Goetz, Brian. "Un curso intensivo sobre hardware moderno" . Archivado del original el 24 de marzo de 2020. Consultado el 1 de mayo de 2014 .
  60. "Programación de 68K en Fargo II" . Archivado del original el 2 de julio de 2008. Consultado el 3 de julio de 2008 .
  61. "BLAS Benchmark-August2008" . eigen.tuxfamily.org. 1 de agosto de 2008. Archivado del original el 24 de marzo de 2020. Consultado el 4 de marzo de 2010 .
  62. "x264.git/common/x86/dct-32.asm" . git.videolan.org. 29/09/2010. Archivado del original el 04/03/2012 . Consultado el 29/09/2010 .
  63. "rav1e/README.md en v0.6.3" . GitHub . Archivado del original el 22 de febrero de 2023. Consultado el 21 de febrero de 2023 .
  64. "README.md · 1.1.0 · VideoLAN / dav1d" . 13 de febrero de 2023. Archivado del original el 22 de febrero de 2023. Consultado el 21 de febrero de 2023 .
  65. Bosworth, Edward (2016). "Capítulo 1: ¿Por qué estudiar el lenguaje ensamblador?" . www.edwardbosworth.com . Archivado del original el 24 de marzo de 2020. Consultado el 1 de junio de 2016 .
  66. "Instrucciones de macros DFSMS de z/OS versión 2 Release 3 para conjuntos de datos" (PDF) . IBM. 15 de febrero de 2019. Archivado (PDF) del original el 25 de junio de 2021. Consultado el 14 de septiembre de 2021 .
  67. Paul, Matthias R. (2001) [1996], "Especificación y documentación de referencia para NECPINW" , NECPINW.CPI - Controlador de cambio de página de códigos DOS para máquinas de escribir NEC ( ed. 2.08), FILESPEC.TXT, NECPINW.ASM, EUROFONT.INC de NECPI208.ZIP, archivado del original el 10-09-2017 , recuperado el 22-04-2013 
  68. Paul, Matthias R. (2002-05-13). " [ fd-dev ] mkeyb" . freedos-dev . Recuperado el 2018-09-10 .{{cite web}}: CS1 maint: servicio de archivado obsoleto ( enlace )

Lecturas adicionales

  • Bartlett, Jonathan (2004). Programación desde cero: una introducción a la programación con lenguaje ensamblador Linux . Bartlett Publishing . ISBN 0-9752838-4-7Archivado del original el 24-03-2020 . Consultado el 24-03-2020 .
  • Britton, Robert (2003). Programación en lenguaje ensamblador MIPS . Prentice Hall . ISBN 0-13-142044-5.
  • Calingaert, Peter (1979) [5 de noviembre de 1978]. Escrito en la Universidad de Carolina del Norte en Chapel Hill . Horowitz, Ellis (ed.). Ensambladores, compiladores y traducción de programas . Serie de ingeniería de software (1.ª impresión, 1.ª  ed.). Potomac, Maryland, EE. UU.: Computer Science Press, Inc. ISBN 0-914894-23-4ISSN 0888-2088 . LCCN 78-21905 . Consultado el 20 de marzo de 2020 .  (2+xiv+270+6 páginas)
  • Duntemann, Jeff (2000). Lenguaje ensamblador paso a paso . Wiley . ISBN 0-471-37523-3.
  • Hyde, Randall (2010). El arte del lenguaje ensamblador (2.ª  ed.). No Starch Press. ISBN 978-1593272074.
  • Jorgensen, Ed. "Programación en lenguaje ensamblador x86-64 con Ubuntu" (PDF) .
  • Kann, Charles W. (2015). "Introducción a la programación en lenguaje ensamblador MIPS" . Archivado del original el 24 de marzo de 2020. Recuperado el 24 de marzo de 2020 .
  • Kann, Charles W. (2021). "Introducción a la programación en lenguaje ensamblador: de principio a fin: edición ARM" . Recursos educativos abiertos .
  • Norton, Peter ; Socha, John (1986). El libro de Peter Norton sobre lenguaje ensamblador para IBM PC . Nueva York, EE. UU.: Brady Books.
  • Singer, Michael (1980). PDP-11. Programación en lenguaje ensamblador y organización de la máquina . Nueva York, EE. UU.: John Wiley & Sons .
  • Sweetman, Dominic (1999). Véase MIPS Run . Morgan Kaufmann Publishers . ISBN 1-55860-410-3.
  • Waldron, John (1998). Introducción a la programación en lenguaje ensamblador RISC . Addison Wesley . ISBN 0-201-39828-1.
  • "Libro de la comunidad ASM" . 2009. Archivado del original el 30 de mayo de 2013. Consultado el 30 de mayo de 2013 .("Un libro en línea lleno de información útil sobre ASM, tutoriales y ejemplos de código" de la comunidad ASM, archivado en el archivo de Internet).
  • Páginas sobre lenguaje ensamblador y aprendizaje del lenguaje ensamblador en WikiWikiWeb
  • Ejemplos de programación en lenguaje ensamblador
  • Introducción al lenguaje ensamblador de Windows x64
Obtenido de " https://en.wikipedia.org/w/index.php?title=Assembly_language&oldid=1362914719#Cross_assembler "