Comment ont été réalisés les premiers compilateurs?

70

Je me le demande toujours et il me faut peut-être une bonne leçon d’histoire sur les langages de programmation. Mais puisque la plupart des compilateurs actuels sont en C, comment ont été construits les tout premiers compilateurs (AKA avant C) ou tous les langages ont-ils été interprétés?

Cela dit, je ne comprends toujours pas comment même le premier langage d'assemblage a été fait, je comprends ce qu'est le langage d'assemblage, mais je ne vois pas comment ils ont obtenu le fonctionnement du TRÈS premier langage d'assemblage (comme, comment ont-ils créé le premier commandes (comme mov R21) ou w / e réglé sur l’équivalent binaire?

moucheron
la source
9
Il y avait une fois un programmeur comiquement inepte dans mon équipe, où il ne faisait que se plaindre de C #. Nous avions l'habitude de plaisanter au sujet d'un langage fictif qu'il a inventé appelé Crunk. Un fait peu connu sur Crunk, c’est le premier langage où le compilateur a ÉGALEMENT été écrit en Crunk. :)
maple_shaft
2
Pourquoi quelqu'un se plaindrait-il de C #? At-il jamais utilisé Smalltalk ou Lisp? lol
2
duplication possible du compilateur C et de Dennis Ritchie
vartec le
4
@maple_shaft: pour être juste, le compilateur gcc est écrit en C . Ce n'est pas un problème si vous avez un bon compilateur croisé pour compiler la première version. Bien entendu, le premier compilateur C devait être écrit dans une autre langue.
Scott Whitlock
5
doublon possible de Comment a été écrit le premier compilateur?
Greg Hewgill

Réponses:

89

Ha, j'ai fait ça. De nombreux processeurs ont des instructions simples, de taille fixe, ne comptant que quelques octets. Pour un processeur simple comme un Motorola 6800 par exemple, vous pouvez adapter toutes ses instructions sur une seule feuille de papier . Un code d'opération à deux octets est associé à chaque instruction, ainsi que des arguments. Vous pouvez assembler à la main un programme en consultant l'opcode de chaque instruction. Vous écririez ensuite votre programme sur papier en annotant chaque instruction avec son code d'opération correspondant. Une fois que vous avez écrit votre programme, vous pouvez graver chaque code opération en séquence sur une EPROM.qui stockerait alors votre programme. Raccordez l’EPROM au processeur avec juste les bonnes instructions aux bonnes adresses et vous disposez d’un programme de travail simple. Et pour répondre à votre prochaine question, oui. C'était douloureux (nous l'avons fait au lycée). Mais je dois dire que le fait de connecter chaque puce à un ordinateur 8 bits et d’écrire un programme manuellement me permettait de mieux comprendre l’architecture de l’ordinateur, ce que je n’aurais probablement pas pu réaliser autrement.

Les puces plus avancées (comme x86) sont beaucoup plus difficiles à coder à la main, car elles ont souvent des instructions de longueur variable. Les processeurs VLIW / EPIC tels que l’ Itanium sont quasiment impossibles à coder manuellement à la main, car ils gèrent des paquets d’instructions optimisées et assemblées par des compilateurs avancés. Pour les nouvelles architectures, les programmes sont presque toujours écrits et assemblés sur un autre ordinateur, puis chargés dans la nouvelle architecture. En fait, les entreprises comme Intel, qui construisent des processeurs, peuvent exécuter de véritables programmes sur des architectures inexistantes en les exécutant sur des simulateurs. Mais je m'égare ...

Quant aux compilateurs, dans leur forme la plus simple, ils ne peuvent être que des programmes "copier / coller". Vous pourriez écrire un "langage de haut niveau" très simple, non optimisant, qui regroupe simplement des instructions de langage d'assemblage simples sans beaucoup d'effort.

Si vous voulez une histoire des compilateurs et des langages de programmation, je vous suggère d'obtenir une histoire de Fortran .

Dave Markle
la source
27
. . . et ça ne devrait pas être "... je vous suggère JMP à une histoire ..."
Binary Worrier
2
Je suis vraiment très désolé. Mais je devais. Je viens tout juste d'avoir. à ...
Dave Markle
9
@ Dave: Vous réalisez que vous êtes condamné à mort par Velociraptor ?
Binary Worrier
7
Ils "savaient" parce qu'ils étaient littéralement câblés pour effectuer cette opération lorsqu'ils ont vu un signal 101010100 pour une instruction donnée. Ils ont en fait une unité sur puce chargée des instructions de décodage des instructions: en.wikipedia.org/wiki/Decoder
Dave Markle
7
À noter: le compilateur d'un nouveau langage, lorsqu'il est écrit dans ce même nouveau langage, est parfois compilé avec un "proto-compilateur" écrit dans un autre langage qui produit un code manifestement correct, mais terriblement inefficace. Une fois ainsi compilé, il est ensuite exécuté sur lui-même pour produire un compilateur raisonnablement rapide. Comparez Von Neumann Machine. : D
BMDan
54

C’est l’objet du démarrage du compilateur (puisque personne n’a mentionné comment il s’appelle =).

le processus d'écriture d'un compilateur (ou assembleur) dans le langage de programmation cible qu'il est destiné à compiler. L'application de cette technique conduit à un compilateur auto-hébergé.

De nombreux compilateurs pour de nombreux langages de programmation sont amorcés, y compris les compilateurs pour BASIC, ALGOL, C, Pascal, PL / I, Factor, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Scheme, Java, Python, Scala et plus encore. .

Le problème de la poule et de l'œuf

Si on a besoin d'un compilateur pour le langage X pour obtenir un compilateur pour le langage X (qui est écrit en langage X), comment le premier compilateur a-t-il été écrit? Les méthodes possibles pour résoudre ce problème de la poule ou de l'œuf sont les suivantes:

  • Implémentation d'un interpréteur ou compilateur pour le langage X dans le langage Y. Niklaus Wirth a indiqué qu'il avait écrit le premier compilateur Pascal en Fortran.
  • Un autre interprète ou compilateur pour X a déjà été écrit dans une autre langue, Y; c'est ainsi que Scheme est souvent amorcé.
  • Les versions précédentes du compilateur étaient écrites dans un sous-ensemble de X pour lequel il existait un autre compilateur; C'est ainsi que certains sur-ensembles de Java, Haskell et le compilateur Free Pascal initial sont initialisés.
  • Le compilateur pour X est compilé de manière croisée à partir d’une autre architecture où il existe un compilateur pour X; C'est ainsi que les compilateurs pour C sont généralement portés sur d'autres plates-formes. C'est aussi la méthode utilisée pour Free Pascal après le démarrage initial.
  • Ecrire le compilateur en X; puis compilez-le manuellement à partir de la source (le plus souvent d'une manière non optimisée) et exécutez-le sur le code pour obtenir un compilateur optimisé. Donald Knuth l'a utilisé pour son système de programmation alphabète WEB ...
vignes
la source
Bon lien qui vous mène également à en.wikipedia.org/wiki/History_of_compiler_writing . En général, je pense que les compilateurs originaux ont été écrits en langage d'assemblage ( en.wikipedia.org/wiki/Assembly_language ). Ce n'est que plus tard que l'idée d'amorçage ou d'auto-hébergement est apparue.
Michael Levy
1
+1 ENFIN! Bizarre que ce ne soit que la troisième réponse la plus cotée. Oui, amorcer. C'est la réponse
Adam Rackis
15

En fin de compte, tous les ordinateurs fonctionnent sur des codes binaires, qui sont introduits dans la CPU. Ces codes binaires sont parfaitement naturels pour un processeur, mais également parfaitement inutiles pour les êtres humains. L'une des premières façons d'écrire un programme consistait à percer des trous dans les cartes. La position des trous représentait une position de bit particulière dans un mot, et la présence ou l'absence du trou était interprétée comme un zéro ou un un. Ces cartes ont été placées dans le bon ordre dans une boîte, puis introduites dans un lecteur de carte, ce qui les a converties efficacement en code binaire pour le processeur (votre vie a été perdue si vous avez laissé tomber la boîte).

Il est évident que les tout premiers programmeurs ont élaboré les codes binaires un par un et avaient une machine pour perforer les cartes. Il s’agit essentiellement de programmation en langage assembleur à quatre pattes. Une fois que vous avez cela, vous pouvez créer tout le reste: un éditeur de texte simple, un compilateur en langage assembleur (pour convertir les instructions d'assemblage de texte en codes binaires), un éditeur de liens et un chargeur. Et le reste, comme on dit, c'est de l'histoire.

Wolfgangsz
la source
4
Avant les cartes, vous disposiez d'un ensemble de commutateurs pour l'adresse, d'un ensemble pour le mot de données et d'un commutateur pour charger les données. Vous avez programmé chaque adresse de mémoire individuellement en configurant l'adresse et les commutateurs de données avec la représentation binaire et activez puis désactivez le commutateur de charge. Cela a pris des siècles, mais le programme ne comportait que quelques mots: des octets n’avaient pas encore été inventés.
Uu
4
... Et avant cela, vous deviez le recâbler . Funfunfun!
Michael K
Oui, mais lorsque vous deviez le faire, ce n'était pas vraiment ce que nous pensions être un ordinateur moderne, l'architecture Von Neumann n'ayant pas encore été inventée.
Dave Markle
7

Une petite recherche sur Google révèle les commandes initiales d'EDSAC datant de la fin des années 40. Comme il s'agissait du premier assembleur, il était probablement codé en langage machine.

Vint ensuite des assembleurs pour d'autres machines, comme SOAP I et II pour IBM 650. SOAP J'étais probablement aussi codé en langage machine, bien que je n'ai pas trouvé la déclaration définitive.

Un peu plus tard, Fortran (traducteur de formules), pour IBM 704, a probablement été écrit en assembleur pour le 704. Un des premiers assembleurs pour le 701 est attribué à Nathan Rochester .

Si vous souhaitez avoir une idée de la programmation d'un ordinateur en langage machine, consultez l'un de mes sites préférés, l'ordinateur relais de Harry Porter .

Mike Dunlavey
la source
Bon sang, l'ordinateur d'Harry Porter (presque dit Harry Potter lol) construit à la maison est génial. Je voudrais comprendre comment quelque chose comme ça a été construit :(.
1
@Sauron: Harry Porter n'aimerait rien de mieux que de vous le dire. Sur cette page, il a un powerpoint magnifiquement conçu qui explique tout. Cela suppose des connaissances de base en circuits, mais ce n'est pas trop difficile à obtenir.
Mike Dunlavey
Je sais que je viens de salir ^ _ ^, même s’il s’agit d’une machine très impressionnante et que de nombreuses heures de magicien y ont été consacrées :).
6

Il est possible (si fastidieux) d’écrire du code machine direct. Peut-être écrivez-vous le programme en assembleur sur un morceau de papier, puis traduisez-le à la main en instructions numériques de code machine que vous avez entrées dans la mémoire de la machine. Vous pouvez même ignorer l'étape d'assemblage sur papier si vous avez mémorisé les valeurs numériques de toutes les instructions de code machine. Ce n'est pas inhabituel à cette époque, croyez-le ou non!

Les tout premiers ordinateurs ont été directement programmés en binaire en basculant des commutateurs physiques. Ce fut une grande amélioration de la productivité lorsque le matériel informatique a évolué pour permettre au programmeur (ou à l’assistant de saisie) de saisir le code en nombres hexadécimaux via un clavier!

Un assembleur de logiciels n'est devenu pertinent que lorsque davantage de mémoire est devenue disponible (le code de l'assembleur prenant plus de place que le code machine brut) et le matériel a évolué pour permettre une entrée alphanumérique. Les premiers assembleurs ont donc été écrits directement par des personnes parlant couramment le code machine.

Lorsque vous avez un assembleur, vous pouvez écrire un compilateur pour un langage de niveau supérieur dans l'assembleur.

L'histoire de C comporte plusieurs étapes. Le premier compilateur C a été écrit en B (un prédécesseur de C) qui à son tour a été écrit en BCPL. BCPL est un langage assez simple (par exemple, il n’a pas du tout de types), mais reste un pas en avant de l’assembleur brut. Vous voyez donc comment des langages de plus en plus complexes sont construits dans des langages plus simples jusqu’à assembleur. Et lui-même C est un langage assez petit et simple par rapport aux normes actuelles.

Aujourd'hui, le premier compilateur pour un nouveau langage est souvent écrit en C, mais lorsque le langage atteint une certaine maturité, il est souvent réécrit "en soi". Le premier compilateur Java a été écrit en C, mais réécrit plus tard en Java. Le premier compilateur C # a été écrit en C ++, mais il a récemment été réécrit en C #. Le compilateur / interprète Python est écrit en C, mais le projet PyPy tente de le réécrire en Python.

Cependant, il n'est pas toujours possible d'écrire un compilateur / interprète pour une langue dans la langue elle-même. Un interpréteur JavaScript écrit en JavaScript existe, mais les compilateurs / interprètes des navigateurs actuels sont toujours écrits en C ou C ++ pour des raisons de performances. JavaScript écrit en JavaScript est tout simplement trop lent.

Mais vous n'avez pas à utiliser C comme "langage de départ" pour un compilateur. Le premier compilateur F # a été écrit en OCaml, l’autre langage le plus proche de F #. Une fois le compilateur terminé, il a été réécrit en F #. Le premier compilateur pour Perl 6 a été écrit en Haskell (un langage fonctionnel pur très différent de Perl), mais a maintenant un compilateur écrit en C.

Rust, où le premier compilateur a été écrit en OCaml (il est maintenant réécrit en Rust) est un cas intéressant. Ceci est notable car OCaml est généralement considéré comme étant de niveau supérieur à Rust, langage de systèmes plus proche du métal. Ce ne sont donc pas toujours des langages de niveau supérieur implémentés dans des langages de niveau inférieur, ce pourrait également être l'inverse.

JacquesB
la source
3

En supposant que vous commenciez avec un jeu d'instructions nues et rien d'autre, vous commenceriez par créer un assembleur ou un compilateur minimal , à peine fonctionnel, capable de charger un fichier, d'analyser un sous-ensemble minimal du langage cible et de générer un exécutable. fichier en sortie, en écrivant le code machine brut en utilisant un éditeur hexadécimal ou similaire.

Vous utiliseriez ensuite ce compilateur ou assembleur à peine fonctionnel pour implémenter un compilateur ou un assembleur légèrement plus capable capable de reconnaître un sous-ensemble plus important du langage cible. Faire mousser, rincer, répéter, jusqu'à l'obtention du produit final.

John Bode
la source
2

Ce n'est pas si difficile, semble-t-il. Dans l’enfance;) j’ai fait du désassemblage x86 à l’esprit.

Vous n'avez même pas besoin de l'apprendre spécialement. C'est ce qui se produit lorsque vous pouvez programmer dans ASM, puis essayer de réparer un fichier binaire tiers à l'aide de désassembleurs interactifs. Ou lorsque vous écrivez votre propre protection avec le cryptage de code.

C'est-à-dire que parfois, vous migrez même de la langue vers des codes sans surprise.

Pavel Koryagin
la source
1

Les premiers compilateurs ont été mis en œuvre en langage assembleur. Et les premiers assembleurs ont été implémentés en codant des programmes en binaire ...


Il n'y a pas si longtemps, la programmation en binaire était encore une compétence que les gens utilisaient.

Quand j'étais étudiant, je me souviens avoir fait un exercice de programmation qui impliquait d'écrire un petit programme en code machine PDP-8 (je pense), de le saisir via les commutateurs du panneau avant et de l'exécuter. Quelques années plus tard, je me suis acheté un kit de développement de système 6502 doté d'un clavier hexadécimal pour entrer dans les programmes ... et de 4 000 octets de mémoire vive.

Stephen C
la source
-3

UNE RÉPONSE TRÈS SIMPLE Supposons que nous écrivions un programme câblé et que nous le stockions dans une ROM. Cela peut être considéré comme un compilateur. Donc, je veux simplement dire que le tout premier compilateur était câblé. Au fur et à mesure de l'amélioration de la technologie, ces compilateurs simples ont ensuite été utilisés pour écrire des compilateurs de haut niveau.

DINOTOPO
la source