Existe alguma diferença real entre um compilador e um montador?

14

Existe alguma diferença entre os dois? De acordo com o livro de Ullman , os compiladores convertem um idioma para outro (geralmente de baixo nível), assim como um assembler. Como os dois são diferentes?

gpuguy
fonte
1
Um assembler é um compilador que executa um conjunto específico de tarefas. Os termos divergiram um pouco na prática, mas a definição básica de "compilador" (traduzir entre idiomas) se aplica.
Raphael
Todos os assemblers são compiladores (simples), pois transformam um idioma em outro. Nem todos os compiladores são montadores.
user253751

Respostas:

16

Um montador converte o código de montagem em código de máquina. A tradução é mecânica e pode ser feita de apenas uma maneira. Por outro lado, um compilador tem mais liberdade ao compilar a linguagem de programação relevante - ele pode otimizar, por exemplo, e até compiladores que não otimizam produzem código diferente. Além disso, os compiladores podem ser escritos de maneira a separar o "front-end" (correspondente à linguagem de programação) e o "back-end" (correspondente à arquitetura do computador), enquanto que os montadores são sempre os mesmos.

Yuval Filmus
fonte
2
Por que a tradução pode ser feita de apenas uma maneira? Isso significa que o código asm de origem não pode ser gerado para um determinado código de máquina (e arquitetura de destino)? Isso parece contra-intuitivo para mim. Como se uma determinada instrução de código de máquina pode mapear para várias instruções ASM, como a máquina decide qual instrução executar? Estou esquecendo de algo?
Utku
2
Receio que você tenha entendido mal o significado de "caminho único" aqui. Isso significa que, dado um código de montagem , existe uma única tradução de em código de máquina. t ( A ) AUMAT(UMA)UMA
Yuval Filmus
Obrigado, também vejo que no livro de Ullman, um compilador tem um front end e um back-end. Se estiver correto, o back-end realiza otimização em um idioma intermediário, geração de código de máquina e otimização do código de máquina, e cada uma das três tarefas pode ser executada de mais de uma maneira. a parte "back-end" é uma montadora? A linguagem intermediária é uma linguagem assembly? Acho que sim, mas sua resposta menciona que um montador faz seu trabalho de apenas uma maneira.
Tim
Eu o publiquei
Tim
Linguagem intermediária geralmente se refere a uma linguagem independente da máquina.
Yuval Filmus
11

A conclusão é que é mais divertido escrever um compilador do que um montador. As linguagens assembly geralmente são projetadas para serem quase triviais para analisar e verificar o tipo e tendem a envolver muitos geradores acionados por tabela ("o opcode para add é 01110", "para instruções de carregamento, o registro do operando de destino é especificado pelos bits 17 a 21. "). Normalmente, a parte mais interessante de um montador é a parte que resolve etiquetas simbólicas em números.

No entanto , a maioria dos montadores pode fazer uma pequena quantidade de aritmética (adicionando rótulos simbólicos com pequenas constantes, por exemplo) e a maioria dos montadores possui ou está integrada a um recurso de processamento de macro. (Na maioria dos sistemas Unix, o recurso de macro é realmente fornecido executando o pré-processador C sobre o conjunto antes de passá-lo ao montador apropriado.)

O montador do MIPS teve que ir um passo além disso, tomou algumas decisões interessantes sobre geração de código e fez uma pequena otimização. A linguagem de máquina do MIPS requer sequências de código diferentes para carregar constantes diferentes, por exemplo, e assim o montador teve que escolher a sequência de código após construir a constante . Além disso, o código de máquina MIPS tinha a noção de slots de atraso , mas era responsabilidade do montador abstraí-los e apresentar uma linguagem de montagem abstrata mais "normal" ao compilador. Portanto, o assembler do MIPS precisa fazer algum agendamento de instruções local.

A distinção é ainda mais obscurecida por parte do trabalho de Norman Ramsey , em particular sua linguagem assembly C - portátil. (O artigo relevante é Ramsey e Peyton Jones, "Uma única linguagem intermediária que suporta múltiplas implementações de exceções", Prog. Lang. Impl. E Dsgn. , (PLDI-21): 285–298, 2000. ) E finalmente, há também é uma linguagem de montagem digitada de David Walker e Greg Morrisett com um assembler que pode garantir a segurança da memória.

Lógica Errante
fonte
0

Um pouco de resposta simplificada aqui, a realidade é mais complicada. Eu esperaria que a diferença entre um Assembler (A) e um Compiler (C) estivesse entre outras coisas:

  1. Uma linha de código-fonte está diretamente relacionada a um código de operação da CPU (A) ou não (C)
  2. Altamente dependente da CPU real (A) ou da máquina independente (C)

Nós tendemos a chamar a linguagem assembly de "baixo nível" e o idioma de origem que um compilador entende como "alto nível" (isso é simplificação grosseira, mas ainda assim).

Na linguagem assembly, você poderia, por exemplo, fazer uma operação add dizendo:

  • adicione a, b (para uma CPU específica)
  • adicione R5, R6 (para uma CPU diferente)
  • adicionar (A5), D2 (para uma CPU diferente)

Em um idioma de alto nível, você pode escrever:

  • x = y + z;

E isso pode resultar em uma instrução ou centenas de instruções, dependendo de várias circunstâncias, uma é para qual CPU o compilador cria instruções.

Como você pode ver, a linguagem de origem do assembly costuma ser: (A) uma linha de código-fonte fornece uma linha de códigos de operação da CPU e depende muito de qual CPU você está direcionando. Um compilador de linguagem de alto nível (C) lida com todos esses detalhes para você - uma linha de código-fonte pode se tornar zero, um ou mais códigos de operação da CPU e o compilador lida com os detalhes do que a CPU pode fazer.

Hoje, um compilador geralmente consiste em vários estágios diferentes. Eles poderiam ser chamados de frontend / backend ou ser chamados de outras coisas. Eu normalmente os vejo como quatro estágios:

  1. O primeiro estágio lê o código fonte real e cria uma representação interna. Este estágio conhece o idioma de origem real.
  2. O segundo estágio examina a representação interna e faz várias otimizações. Atualmente, o compilador normalmente procura tornar o programa mais rápido e não se importa se ele ficar maior. A otimização é feita na representação interna. Curiosamente, partes disso podem ser genéricas para vários idiomas diferentes.
  3. O terceiro estágio pega a representação interna e cria o código real para a CPU selecionada. Pode haver várias versões diferentes desse estágio, visando diferentes CPU-s. Na verdade, você pode escrever o código-fonte uma vez e compilá-lo para diferentes CPUS-s.
  4. Preparativos finais para "empacotar" o programa (esta etapa pode ser um linker).

Escrever bons compiladores é uma profissão altamente qualificada - fazer um compilador de linguagem de brinquedo pode ser feito à tarde por um amador (ou bem, um pouco mais).

ghellquist
fonte