Como foram feitos os primeiros compiladores?

70

Eu sempre me pergunto isso, e talvez eu precise de uma boa lição de história sobre linguagens de programação. Mas como a maioria dos compiladores atualmente são feitos em C, como foram os primeiros compiladores (AKA antes de C) ou todas as linguagens foram interpretadas?

Com isso dito, eu ainda não entendo como foi feita a primeira linguagem assembly, entendo o que é a linguagem assembly, mas não vejo como eles conseguiram que a MUITO primeira linguagem assembly funcionasse (como, por exemplo, como eles criaram a primeira linguagem assembly) comandos (como mov R21) ou w / e definido como o equivalente binário?

mosquito
fonte
9
Havia um programador comicamente inepto na minha equipe uma vez, onde tudo o que ele fez foi reclamar de C #. Costumávamos brincar sobre uma linguagem fictícia que ele inventou chamada Crunk. Um fato pouco conhecido sobre o Crunk, é o primeiro idioma em que o compilador também foi escrito em Crunk. :)
maple_shaft
2
Por que alguém reclamaria de c #? Ele nunca usou Smalltalk ou Lisp? lol
2
possível duplicata de compilador C e Dennis Ritchie
vartec
4
@maple_shaft: para ser justo, o compilador GCC é escrito em C . Na verdade, isso não é um problema se você tiver um bom compilador cruzado para compilar a primeira versão. O primeiro compilador C, é claro, teve que ser escrito em outro idioma.
Scott Whitlock
5
possível duplicata de Como foi escrito o primeiro compilador?
Greg Hewgill

Respostas:

89

Ha, eu fiz isso. Muitas CPUs possuem instruções simples e de tamanho fixo, com apenas alguns bytes de comprimento. Para uma CPU simples como um Motorola 6800, por exemplo, você pode caber todas as instruções em uma única folha de papel . Cada instrução teria um código de operação de dois bytes associado a ela e argumentos. Você pode montar um programa manualmente, pesquisando o código de operação de cada instrução. Você escreveria seu programa no papel , anotando cada instrução com seu código de operação correspondente. Depois de escrever seu programa, você poderá gravar cada código de operação em sequência em uma EPROMque armazenaria seu programa. Conecte a EPROM à CPU com apenas as instruções corretas nos endereços certos e você terá um programa de trabalho simples. E para responder sua próxima pergunta, sim. Foi doloroso (fizemos isso no ensino médio). Mas devo dizer que ligar todos os chips de um computador de 8 bits e escrever um programa manualmente me proporcionou uma compreensão profunda da arquitetura do computador que provavelmente não poderia ter conseguido de outra maneira.

Os chips mais avançados (como x86) são muito mais difíceis de codificar manualmente, porque geralmente possuem instruções de tamanho variável. Os processadores VLIW / EPIC como o Itanium são quase impossíveis de codificar com eficiência, porque eles lidam com pacotes de instruções que são otimizadas e montadas por compiladores avançados. Para novas arquiteturas, os programas são quase sempre escritos e montados em outro computador primeiro e depois carregados na nova arquitetura. De fato, para empresas como a Intel que realmente constroem CPUs, elas podem executar programas reais em arquiteturas que ainda não existem, executando-os em simuladores. Mas eu discordo ...

Quanto aos compiladores, na sua forma mais simples, eles podem ser pouco mais do que programas "recortar e colar". Você pode escrever uma "linguagem de alto nível" muito simples, não otimizadora, que agrupe instruções simples em linguagem assembly sem muito esforço.

Se você quer um histórico de compiladores e linguagens de programação, sugiro que você faça um histórico do FORTRAN .

Dave Markle
fonte
27
. . . e shoudn't que ser "... eu sugiro que você JMP a uma história ..."
Binary Worrier
2
Eu sinto muito mesmo. Mas eu tive que. Eu apenas ... tive. para ...
Dave Markle 30/06
9
@ Dave: Você percebe que se condenou à morte pelo Velociraptor ?
Preocupação binária
7
Eles "sabiam" porque estavam literalmente conectados para executar essa operação quando viram um sinal 101010100 para uma determinada instrução. Eles realmente têm uma unidade on-chip responsável por instruções instruções de decodificação: en.wikipedia.org/wiki/Decoder
Dave Markle
7
Vale acrescentar: o compilador de um novo idioma, quando escrito no mesmo idioma, às vezes é compilado com um "proto-compilador" escrito em outro idioma que produz código comprovadamente correto, mas terrivelmente ineficiente. Uma vez compilado, ele é executado automaticamente para produzir um compilador razoavelmente rápido. Compare a máquina de Von Neumann. : D
BMDan 01/07/11
54

É disso que trata a inicialização do compilador (já que ninguém mencionou como é chamado =).

o processo de escrever um compilador (ou assembler) na linguagem de programação de destino que ele pretende compilar. A aplicação desta técnica leva a um compilador auto-hospedado.

Muitos compiladores para muitas linguagens de programação são inicializados, incluindo compiladores para BASIC, ALGOL, C, Pascal, PL / I, Fator, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Scheme, Java, Python, Scala e mais .. .

O problema do frango e do ovo

Se é necessário um compilador para a linguagem X para obter um compilador para a linguagem X (que está escrito na linguagem X), como o primeiro compilador foi escrito? Os métodos possíveis para resolver esse problema de galinha ou ovo incluem:

  • Implementando um intérprete ou compilador para a linguagem X na linguagem Y. Niklaus Wirth relatou que ele escreveu o primeiro compilador Pascal no Fortran.
  • Outro intérprete ou compilador para X já foi escrito em outro idioma Y; é assim que o esquema geralmente é inicializado.
  • As versões anteriores do compilador foram gravadas em um subconjunto do X para o qual existia outro compilador; é assim que alguns superconjuntos de Java, Haskell e o compilador Free Pascal inicial são inicializados.
  • O compilador para X é compilado em cruz a partir de outra arquitetura, onde existe um compilador para X; é assim que os compiladores para C geralmente são portados para outras plataformas. Além disso, este é o método usado para o Free Pascal após a inicialização.
  • Escrevendo o compilador em X; depois, compilando-o manualmente a partir da fonte (provavelmente de maneira não otimizada) e executando-o no código para obter um compilador otimizado. Donald Knuth usou isso em seu sistema de programação alfabetizado WEB ...
videiras
fonte
Bom link que também leva você a en.wikipedia.org/wiki/History_of_compiler_writing . Em geral, acho que os compiladores originais foram escritos em Assembly Language ( en.wikipedia.org/wiki/Assembly_language ). Somente mais tarde surgiu a idéia de inicialização ou auto-hospedagem.
Michael Levy
11
+1 FINALMENTE! É estranho que essa seja apenas a terceira resposta mais bem classificada. Sim, inicialização. Essa é a resposta
Adam Rackis
15

Por fim, todos os computadores operam com códigos binários, que são alimentados na CPU. Esses códigos binários são perfeitamente naturais para uma CPU, mas também perfeitamente inúteis para os seres humanos. Uma das primeiras maneiras de escrever um programa foi perfurando os cartões. A posição dos furos representava uma posição de bit específica em uma palavra, e a presença ou ausência do furo era interpretada como zero ou uma. Esses cartões foram colocados na sequência correta em uma caixa e, em seguida, alimentados em um leitor de cartão, que os converteu efetivamente em código binário para a CPU (e sua vida foi efetivamente perdida se você soltasse a caixa).

Obviamente, os primeiros programadores elaboraram os códigos binários um por um e tinham uma máquina para perfurar os cartões. Isso é essencialmente programação em linguagem assembly em suas mãos e joelhos. Depois disso, você poderá criar todas as outras coisas: um editor de texto simples, um compilador de linguagem assembly (para converter as instruções de montagem de texto em códigos binários), um vinculador e um carregador. E o resto, como eles falam, é história.

wolfgangsz
fonte
4
Antes dos cartões, você tinha um conjunto de comutadores para o endereço, um conjunto para a palavra de dados e um comutador para carregar os dados. Você programou cada endereço de memória individualmente configurando as chaves de endereço e de dados com a representação binária e ligou e desligou a chave de carregamento. Demorou séculos, mas o programa tinha apenas algumas palavras: bytes não haviam sido inventados na época.
uɐɪ
4
... E antes disso, você tinha que religá-lo . Diversão diversão diversão!
Michael K
Sim, mas quando você tinha que fazer isso, não era realmente o que pensávamos como um computador moderno, pois a arquitetura Von Neumann ainda não havia sido inventada.
precisa
7

Um pouco de pesquisa mostra as Ordens Iniciais da EDSAC do final dos anos 40. Como foi o primeiro montador, provavelmente foi codificado em linguagem de máquina.

Posteriormente vieram montadores para outras máquinas, como SOAP I e II para o IBM 650. SOAP I também provavelmente foi codificado em linguagem de máquina, embora não tenha encontrado a declaração definitiva.

Um pouco mais tarde veio Fortran (tradutor de fórmulas), para o IBM 704. Presumivelmente, foi escrito em assembler para o 704. Um dos primeiros montadores para o 701 é creditado a Nathan Rochester .

Se você quiser ter uma idéia de como programar um computador em linguagem de máquina, confira um dos meus sites favoritos, o computador de retransmissão de Harry Porter .

Mike Dunlavey
fonte
Caramba, o computador doméstico de Harry Porter (quase dito harry potter lol) é INCRÍVEL. Eu gostaria de entender como algo assim foi construído :(.
11
@Sauron: Harry Porter não gostaria de nada melhor do que contar para você. Nessa página, ele tem um powerpoint lindamente trabalhado, explicando tudo. Ele pressupõe algum conhecimento básico de circuitos, mas isso não é muito difícil de obter.
Mike Dunlavey
Eu sei que estou apenas bagunçando ^ _ ^, independentemente de ser uma máquina muito impressionante e tenho certeza de que muitas horas de assistente foram colocadas nela :).
6

É possível (se entediante) escrever código de máquina direto. Talvez você escreva o programa no assembler em um pedaço de papel e depois o traduza manualmente nas instruções numéricas do código da máquina que você digita na memória da máquina. Você pode até pular a etapa do montador em papel se tiver memorizado os valores numéricos de todas as instruções de código de máquina - não é incomum naqueles dias, acredite ou não!

Os primeiros computadores foram diretamente programados em binário, alternando os comutadores físicos. Foi uma grande melhoria de produtividade quando o hardware evoluiu para permitir que o programador (ou o assistente de entrada de dados) insira o código em números hexadecimais via teclado!

Um assembler de software só se tornou relevante quando mais memória se tornou disponível (já que o código do assembler ocupa mais espaço do que o código bruto da máquina) e o hardware evoluiu para permitir entrada alfanumérica. Portanto, os primeiros montadores foram escritos diretamente por pessoas fluentes em código de máquina.

Quando você tem um assembler, você pode escrever um compilador para uma linguagem de nível superior no assembler.

A história para C tem várias etapas. O primeiro compilador C foi escrito em B (um predecessor de C), que por sua vez foi escrito em BCPL. BCPL é uma linguagem bastante simples (por exemplo, não possui tipos), mas ainda é um passo em frente ao assembler bruto. Então você vê como linguagens gradualmente mais complexas são construídas em linguagens mais simples, desde o assembler. E o próprio C é uma linguagem bem pequena e simples para os padrões atuais.

Hoje, o primeiro compilador para um novo idioma geralmente é escrito em C, mas quando o idioma atinge uma certa maturidade, é frequentemente reescrito "em si". O primeiro compilador Java foi escrito em C, mas posteriormente reescrito em Java. O primeiro compilador C # foi escrito em C ++, mas recentemente foi reescrito em C #. O compilador / intérprete Python é escrito em C, mas o projeto PyPy é uma tentativa de reescrevê-lo no Python.

Nem sempre é possível escrever um compilador / intérprete para um idioma no próprio idioma. Existe um intérprete JavaScript escrito em JavaScript, mas os compiladores / intérpretes nos navegadores atuais ainda são gravados em C ou C ++ por motivos de desempenho. JavaScript escrito em JavaScript é simplesmente muito lento.

Mas você não precisa usar C como o "idioma inicial" para um compilador. O primeiro compilador de F # foi escrito em OCaml, que é o outro idioma que está mais relacionado ao F #. Quando o compilador foi concluído, ele foi reescrito em F #. O primeiro compilador para Perl 6 foi escrito em Haskell (uma linguagem funcional pura muito diferente do Perl), mas agora possui um compilador escrito em C.

Um caso interessante é o Rust, onde o primeiro compilador foi escrito no OCaml (agora é reescrito no Rust). Isso é notável porque o OCaml geralmente é considerado um nível mais alto que o Rust, que é uma linguagem de sistemas mais próxima do metal. Portanto, nem sempre os idiomas de nível superior são implementados nos idiomas de nível inferior; também pode ser o contrário.

JacquesB
fonte
3

Supondo que você esteja começando com um conjunto de instruções simples e nada mais, você começaria criando um montador ou compilador mínimo e pouco funcional que possa carregar um arquivo, analisar um subconjunto mínimo do idioma de destino e gerar um executável arquivo como saída, escrevendo o código bruto da máquina usando um editor hexadecimal ou similar.

Você usaria esse compilador ou montador apenas quase funcional para implementar um compilador ou montador um pouco mais capaz que possa reconhecer um subconjunto maior do idioma de destino. Espuma, enxágüe, repita, até obter o produto final.

John Bode
fonte
2

Não é tão difícil, como parece. Na infância;) fiz algumas desmontagens do x86 em mente.

Você nem precisa aprender especialmente. Acontece que quando você é capaz de programar no ASM e depois tentar consertar um binário de terceiros usando desmontadores interativos. Ou ao escrever sua própria proteção com criptografia de código.

Ou seja, às vezes você está migrando mesmo do idioma para os códigos sem surpresa.

Pavel Koryagin
fonte
1

Os primeiros compiladores foram implementados usando linguagem assembly. E os primeiros montadores foram implementados por programas de codificação em binários ...


Não faz muito tempo que a programação em binário ainda era uma habilidade que as pessoas usavam.

Quando eu estava na graduação, lembro-me de fazer um exercício de programação que envolvia escrever um pequeno programa em código de máquina PDP-8 (eu acho), inseri-lo através dos comutadores do painel frontal e executá-lo. Alguns anos depois, comprei um kit de desenvolvimento de sistema 6502 que possuía um teclado hexadecimal para a entrada de programas ... e 4k bytes de RAM.

Stephen C
fonte
-3

UMA RESPOSTA MUITO SIMPLES Suponha que escrevamos um programa conectado e o armazenemos na ROM. Pode ser considerado como compilador. Então, eu simplesmente quero dizer é que o primeiro compilador foi conectado. À medida que a tecnologia melhorava, esses compiladores simples eram então usados ​​para escrever compiladores de alto nível.

DINOTOPO
fonte