¿Hay alguna diferencia real entre un compilador y un ensamblador?

15

¿Hay alguna diferencia entre los dos? Según el libro de Ullman , los compiladores convierten un idioma a otro (generalmente de bajo nivel), y también lo hace un ensamblador. ¿Cómo son los dos diferentes?

gpuguy
fuente
1
Un ensamblador es un compilador que realiza un conjunto específico de tareas. Los términos han divergido en la práctica, pero se aplica la definición básica de "compilador" (traducir entre idiomas).
Raphael
Todos los ensambladores son compiladores (simples), ya que transforman un idioma a otro. No todos los compiladores son ensambladores.
user253751

Respuestas:

16

Un ensamblador traduce el código de ensamblaje al código de máquina. La traducción es mecánica y solo se puede hacer de una manera. En contraste, un compilador tiene más libertad cuando compila el lenguaje de programación relevante; puede optimizar, por ejemplo, e incluso los compiladores no optimizadores producen código diferente. Además, los compiladores se pueden escribir de una manera que separe el "front-end" (correspondiente al lenguaje de programación) y el "back-end" (correspondiente a la arquitectura de la computadora), mientras que con los ensambladores los dos son siempre iguales.

Yuval Filmus
fuente
2
¿Por qué la traducción se puede hacer de una sola manera? ¿Eso significa que el código asm de origen no se puede generar para un código de máquina dado (y la arquitectura de destino)? Eso suena contra intuitivo para mí. Porque si una instrucción de código de máquina dada puede correlacionarse con múltiples instrucciones asm, entonces, ¿cómo decide la máquina qué instrucción ejecutar? ¿Me estoy perdiendo de algo?
Utku
3
UNT(UN)UN
Gracias, también veo que en el libro de Ullman, un compilador tiene un front-end y un back-end. Si estoy en lo cierto, el backend realiza la optimización en un lenguaje intermedio, la generación de código de máquina y la optimización del código de máquina, y cada una de las tres tareas se puede realizar de más de una manera. ¿Es la parte "backend" un ensamblador? ¿Es el lenguaje intermedio un lenguaje ensamblador? Supongo que sí, pero su respuesta menciona que un ensamblador hace su trabajo de una sola manera.
Tim
Lo publiqué
Tim
El lenguaje intermedio generalmente se refiere a un lenguaje que es independiente de la máquina.
Yuval Filmus
11

La conclusión es que es más divertido escribir un compilador que un ensamblador. Los lenguajes de ensamblaje generalmente están diseñados para ser casi triviales para analizar y escribir cheques y tienden a involucrar una gran cantidad de generadores accionados por tablas ("el código de operación para agregar es 01110", "para las instrucciones de carga, el registro de operando de destino se especifica en los bits 17 a 21 "). Por lo general, la parte más interesante de un ensamblador es la parte que resuelve etiquetas simbólicas en números.

Sin embargo , la mayoría de los ensambladores pueden hacer una pequeña cantidad de aritmética (agregando etiquetas simbólicas con pequeñas constantes, por ejemplo) y la mayoría de los ensambladores tienen o están integrados con una función de procesamiento de macro. (En la mayoría de los sistemas Unix, la función de macro se proporciona ejecutando el preprocesador C sobre el ensamblaje antes de pasarlo al ensamblador propiamente dicho).

El ensamblador MIPS tuvo que ir un paso más allá y tomó algunas decisiones interesantes de generación de código e hizo una pequeña cantidad de optimización. El lenguaje de máquina MIPS requiere diferentes secuencias de código para cargar diferentes constantes, por ejemplo, por lo que el ensamblador tuvo que elegir la secuencia de código después de construir la constante . Además, el código de máquina MIPS tenía la noción de ranuras de retraso , pero era responsabilidad del ensamblador abstraerlas y presentar un lenguaje ensamblador abstracto más "normal" al compilador. Por lo tanto, el ensamblador de MIPS necesita hacer una programación local de instrucciones.

La distinción se ve aún más borrosa por parte del trabajo de Norman Ramsey , en particular su lenguaje ensamblador C- portable. (El artículo relevante es Ramsey y Peyton Jones, "Un lenguaje intermedio único que admite múltiples implementaciones de excepciones", Prog. Lang. Impl. Y Dsgn. , (PLDI-21): 285–298, 2000 ). Y finalmente, allí también es un lenguaje de ensamblaje mecanografiado de David Walker y Greg Morrisett con un ensamblador que puede garantizar la seguridad de la memoria.

Lógica Errante
fuente
0

Un poco de respuesta simplificada aquí, la realidad es más complicada. Esperaría que la diferencia entre un ensamblador (A) y un compilador (C) sea, entre otras cosas:

  1. Una línea de código fuente se relaciona directamente con un código de operación de CPU (A) o no (C)
  2. Depende mucho de la CPU real (A) o de la máquina independiente (C)

Tendemos a llamar al lenguaje ensamblador "nivel bajo" y el lenguaje fuente que un compilador entiende "nivel alto" (esto es una simplificación general, pero aún así).

En lenguaje ensamblador, por ejemplo, podría hacer una operación de agregar diciendo:

  • agregue a, b (para una CPU específica)
  • agregue R5, R6 (para una CPU diferente)
  • add (A5), D2 (para una CPU diferente)

En un lenguaje de alto nivel podrías escribir:

  • x = y + z;

Y esto podría dar como resultado una instrucción o cientos de instrucciones dependiendo de una serie de circunstancias, una es para qué CPU crea las instrucciones el compilador.

Como puede ver, el lenguaje fuente de ensamblaje es más frecuente: (A) una línea de código fuente proporciona una línea de códigos de operación de la CPU y depende mucho de la CPU a la que se dirija. Un compilador de lenguaje de alto nivel (C) maneja todos estos detalles por usted: una línea de código fuente podría convertirse en cero, uno o varios códigos de operación de la CPU y el compilador maneja los detalles de lo que la CPU puede hacer.

Un compilador hoy a menudo consta de varias etapas diferentes. Podrían llamarse frontend / backend o ser llamado otras cosas. Normalmente los veo como cuatro etapas:

  1. La primera etapa lee el código fuente real y crea una representación interna. Esta etapa conoce el idioma fuente real.
  2. La segunda etapa analiza la representación interna y realiza una serie de optimizaciones. Hoy en día, el compilador normalmente buscaría hacer que el programa sea más rápido y no le importe si se hace más grande. La optimización se realiza en la representación interna. Curiosamente, partes de esto podrían ser genéricas para varios idiomas diferentes.
  3. La tercera etapa toma la representación interna y crea código real para la CPU seleccionada. Puede haber varias versiones diferentes de esta etapa, dirigidas a diferentes CPU-s. En efecto, podría escribir el código fuente una vez y luego compilarlo para diferentes CPUS-s.
  4. Preparativos finales para "empaquetar" el programa (esta etapa podría ser un enlazador).

Escribir buenos compiladores es una profesión altamente calificada: un aficionado puede hacer un compilador de lenguaje de juguete en una tarde (o bueno, un poco más).

ghellquist
fuente