最初のコンパイラはどのように作成されましたか?


70

私はいつもこれを疑問に思っており、おそらくプログラミング言語に関する良い歴史のレッスンが必要です。しかし、最近のほとんどのコンパイラはCで作成されているため、最初のコンパイラ(C以前の別名)はどのように作成されましたか?

とはいえ、最初のアセンブリ言語がどのように行われたかはまだわかりません、アセンブリ言語とは何ですか?コマンド(などmov R21)または同等のバイナリに設定されたw / e?


9
私のチームには、かつてC#について文句を言うだけの、コミカルに無能なプログラマーがいました。私たちは、彼が発明したCrunkと呼ばれる架空の言語について冗談を言っていました。Crunkについてはほとんど知られていない事実ですが、これはコンパイラーがCrunkで書かれた最初の言語でもあります。:)
maple_shaft

2
誰かがC#について文句を言うのはなぜですか?彼はsmalltalkやLispを一度も使用したことがありませんか?lol


4
@maple_shaft:公平にするために、gccコンパイラはCで記述されています。最初のバージョンをコンパイルするための優れたクロスコンパイラがあれば、実際には問題になりません。もちろん、最初のCコンパイラは別の言語で作成する必要がありました。
スコットホイットロック

回答:


89

ハ、私はこれをやった。多くのCPUには、長さがわずか数バイトの単純な固定サイズの命令があります。たとえば、Motorola 6800などの単純なCPUの場合、そのすべての指示を1 枚の用紙に収めることができます。各命令には、それに関連付けられた2バイトのオペコードと引数があります。各命令のオペコードを調べることで、プログラムを手作業で組み立てることができます。次に、プログラムを紙に書き、各命令に対応するオペコードを注釈します。プログラムを作成したら、各オペコードを順番にEPROMに書き込むことができます。その後、プログラムが保存されます。EPROMをCPUに配線し、適切な命令を適切なアドレスに置くだけで、簡単な作業プログラムができます。そして、次の質問に答えるために、はい。苦しかったです(高校でこれを行いました)。しかし、8ビットコンピューターのすべてのチップを配線し、プログラムを手動で記述することで、他の方法では達成できなかったコンピューターアーキテクチャの深い理解が得られたと言わざるを得ません。

より高度なチップ(x86など)は、多くの場合可変長命令を持っているため、ハンドコーディングがはるかに困難です。ItaniumなどのVLIW / EPICプロセッサは、高度なコンパイラによって最適化およびアセンブルされた命令のパケットを処理するため、効率的にハンドコーディングすることはほぼ不可能です。新しいアーキテクチャの場合、プログラムはほとんどの場合最初に別のコンピューターで作成およびアセンブルされ、次に新しいアーキテクチャにロードされます。実際、実際にCPUを構築するIntelのような企業では、シミュレータで実行することにより、まだ存在しないアーキテクチャで実際のプログラムを実行できます。しかし、私は脱線します...

コンパイラに関しては、非常に単純な場合、「カットアンドペースト」プログラムにすぎません。非常に単純で最適化されていない「高レベル言語」を記述できます。これは、多くの労力をかけずに単純なアセンブリ言語命令をまとめてクラスター化するだけです。

コンパイラとプログラミング言語の履歴が必要な場合は、FORTRANの履歴に移動することをお勧めします。


27
。。。そして、それは「...私はあなたに歴史へのJMPをお勧めします...」
バイナリウォリアー

2
とてもすみません しかし、私はしなければなりませんでした。ただ…持っていた。...
デイブ・マークル

9
@デイブ:あなたはヴェロキラプトルによってあなた自身が死ぬ運命にあることを知っていますか?
バイナリの心配

7
特定の命令に対して101010100シグナルを受け取ったときに、その操作を実行するために文字通りハードワイヤードされていたため、彼らは「知っていました」。実際には、命令デコード命令を担当するオンチップユニットがあります。en.wikipedia.org
Dave Markle

7
追加する価値がある:新しい言語のコンパイラーは、同じ新しい言語で作成された場合、明らかに正しいが恐ろしく非効率的なコードを生成する別の言語で作成された「プロトコンパイラー」でコンパイルされることがあります。そのようにコンパイルされると、それ自体で実行されて、適度に高速なコンパイラが生成されます。Von Neumann Machineと比較してください。:D
BMD11年

54

これがコンパイラのブートストラップの目的です(=と呼ばれる方法について誰も言及していないため)。

コンパイル対象のターゲットプログラミング言語でコンパイラー(またはアセンブラー)を作成するプロセス。この手法を適用すると、セルフホスティングコンパイラが実現します。

BASIC、ALGOL、C、Pascal、PL / I、Factor、Haskell、Modula-2、Oberon、OCaml、Common Lisp、Scheme、Java、Python、Scalaなどのコンパイラを含む、多くのプログラミング言語の多くのコンパイラがブートストラップされています。 。

鶏と卵の問題

言語Xのコンパイラ(言語Xで記述されている)を取得するために言語Xのコンパイラが必要な場合、最初のコンパイラはどのように記述されましたか?この鶏または卵の問題を解決する可能な方法は次のとおりです。

  • 言語Xのインタプリタまたはコンパイラを言語Yに実装しました。NiklausWirthは、Fortranで最初のPascalコンパイラを書いたと報告しました。
  • X用の別のインタープリターまたはコンパイラーは、すでに別の言語Yで作成されています。これはSchemeがしばしばブートストラップされる方法です。
  • コンパイラの以前のバージョンは、他のコンパイラが存在するXのサブセットで記述されていました。これが、Java、Haskell、および初期のFree Pascalコンパイラのいくつかのスーパーセットがブートストラップされる方法です。
  • Xのコンパイラは、Xのコンパイラが存在する別のアーキテクチャからクロスコンパイルされます。これは通常、Cコンパイラが他のプラットフォームに移植される方法です。また、これは初期ブートストラップ後にFree Pascalに使用される方法です。
  • Xでコンパイラを作成します。次に、ソースから手動でコンパイルし(最適化されていない方法が最も可能性が高い)、コード上で実行して最適化されたコンパイラを取得します。ドナルド・クヌースはこれを自分のWEBリテラシープログラミングシステムに使用しました...

また、en.wikipedia.org/wiki/History_of_compiler_writingへのリンクがあります。一般的に、元のコンパイラはアセンブリ言語(en.wikipedia.org/wiki/Assembly_language)で書かれていると思います。後になってから、ブートストラップまたはセルフホスティングのアイデアが生まれました。
マイケルレヴィ

1
+1 FINALLY!奇妙なことに、これは3番目に高い評価の答えにすぎません。はい、ブートストラップ。それが答えです
アダムラックス

15

最終的に、すべてのコンピューターはバイナリコードで動作し、CPUに供給されます。これらのバイナリコードはCPUにとって完全に自然ですが、人間にとってもまったく役に立ちません。プログラムを書く最初の方法の1つは、カードに穴を開けることでした。穴の位置は単語内の特定のビット位置を表し、穴の有無はゼロまたは1として解釈されました。これらのカードはボックス内の正しいシーケンスに入れられ、カードリーダーに送られ、CPUのバイナリコードに効果的に変換されました(ボックスを落とした場合、あなたの人生は事実上失われました)。

明らかに、最初のプログラマーはバイナリコードを1つずつ作成し、カードをパンチするマシンを用意しました。これは基本的に、あなたの手とひざの上のアセンブリ言語プログラミングです。それができたら、他のすべてのものを作成できます:単純なテキストエディター、アセンブリ言語コンパイラ(テキストアセンブリステートメントをバイナリコードに変換するため)、リンカー、ローダー。そして、彼らが言うように、残りは歴史です。


4
カードの前には、アドレスのセット、データワードのセット、およびデータをロードするためのスイッチがありました。アドレスとデータスイッチをバイナリ表現で設定し、ロードスイッチをオンにしてからオフにして、各メモリアドレスを個別にプログラムしました。それには何年もかかりましたが、プログラムはほんの数ワードの長さでした-バイトは当時発明されていませんでした。
ɐɪ

4
...そしてその前に、あなたはそれ再配線する必要がありまし。楽しい楽しい楽しい!
マイケルK

はい、しかし、それをしなければならなかったとき、フォンノイマンアーキテクチャはまだ発明されていなかったので、それは私たちが現代のコンピューターと考えるものではありませんでした。
デイブ・マークル

7

少しグーグルで40代後半からEDSACの初期注文が表示されます。これは最初のアセンブラーであるため、おそらく機械語でコーディングされていました。

後に、IBM 650用のSOAP IおよびIIのような他のマシン用のアセンブラーが登場しました。SOAPIもおそらく機械語でコーディングされていましたが、最終的なステートメントは見つかりませんでした。

少し後に、IBM 704用のFortran(式変換プログラム)が登場しました。おそらく、704用のアセンブラーで書かれたものです。701用の初期のアセンブラーはNathan Rochesterの功績によるものです。

コンピューターを機械語でプログラムする方法を知りたい場合は、私のお気に入りのサイトの1つであるHarry Porterのリレーコンピューターをチェックしてください。


なんてこった、ハリーポーター(ほとんどハリー・ポッター笑と言われる)自家製のコンピューターは素晴らしいです。そのようなものがどのように構築されたかを理解したいです

1
@サウロン:ハリー・ポーターはあなたに言うことよりも良いことを望んでいません。そのページから、彼はそれをすべて説明する美しく細工されたパワーポイントを手に入れました。回路の基本的な知識を前提としていますが、それほど難しくはありません。
マイクダンラベイ

私はIMがメッシン^ _ ^であることを知っていますが、それは非常に印象的なマシンであり、多くのウィザード時間を費やしたと確信しています:)。

6

(退屈な場合)直接マシンコードを書くことは可能です。多分あなたは紙の上にアセンブラーでプログラムを書き留めて、それからあなたが手で機械メモリに入力する数値の機械コード命令に翻訳します。すべてのマシンコード命令の数値を記憶している場合は、紙の上のアセンブラーの手順をスキップすることもできます。

最初のコンピューターは、物理スイッチを切り替えることにより、バイナリで直接プログラムされました。ハードウェアが進化してプログラマー(またはデータ入力アシスタント)がキーパッドを介して16進数のコードを入力できるようになったとき、生産性が大幅に向上しました。

ソフトウェアアセンブラは、アセンブラコードがrawマシンコードよりも多くのスペースを占有するため)より多くのメモリが使用可能になり、英数字入力を許可するように進化した場合にのみ関連しました。したがって、最初のアセンブラは、マシンコードに堪能な人々によって直接記述されました。

アセンブラーがある場合、アセンブラーで高レベル言語用のコンパイラーを作成できます。

Cのストーリーには複数のステップがあります。最初のCコンパイラはB(Cの前身)で書かれ、BCPLで書かれました。BCPLは非常に単純な言語です(たとえば、型がまったくありません)が、未加工のアセンブラーからのステップアップです。したがって、アセンブラーに至るまで、より複雑な言語がより単純な言語で徐々に構築されることがわかります。そして、C自体は今日の標準ではかなり小さくシンプルな言語です。

今日、新しい言語の最初のコンパイラはCで書かれていることがよくありますが、言語が特定の成熟度に達すると、しばしば「それ自体」で書き直されます。最初のJavaコンパイラはCで記述されていましたが、後にJavaで書き直されました。最初のC#コンパイラはC ++で記述されていましたが、最近ではC#で書き直されました。Pythonコンパイラ/インタープリターはCで書かれていますが、PyPyプロジェクトはPythonで書き直そうとしています。

ただし、言語自体に言語用のコンパイラ/インタープリターを書くことは常に実行可能ではありません。JavaScriptで記述されたJavaScriptインタープリターは存在しますが、現在のブラウザーのコンパイラー/インタープリターは、パフォーマンス上の理由からCまたはC ++で記述されています。JavaScriptで記述されたJavaScriptは単純に遅すぎます。

ただし、コンパイラの「開始言語」としてCを使用する必要はありません。最初のF#コンパイラはOCamlで作成されました。これは、F#に最も密接に関連する他の言語です。コンパイラが完成すると、F#で書き直されました。Perl 6の最初のコンパイラーはHaskell(Perlとは非常に異なる純粋な関数型言語)で作成されましたが、現在はCで作成されたコンパイラーがあります。

興味深いケースはRustです。最初のコンパイラはOCamlで記述されています(現在はRustで書き直されています)。OCamlは一般的にRustよりも高いレベルと考えられているため、これは注目に値します。Rustは、より金属に近いシステム言語です。したがって、常に低レベル言語で実装された高レベル言語であるとは限らず、逆の場合もあります。


3

あなたが裸の命令セットから始めて他に何もないと仮定すると、ファイルをロードし、ターゲット言語の最小限のサブセットを解析し、実行可能ファイルを生成できる、最小限の、ほとんど機能しないアセンブラーまたはコンパイラーを作成することから始めます16進エディタなどを使用してrawマシンコードを記述し、出力としてファイルします。

次に、そのほとんど機能しないコンパイラーまたはアセンブラーを使用して、ターゲット言語のより大きなサブセットを認識できる、わずかに高性能のコンパイラーまたはアセンブラーを実装します。最終製品が得られるまで、泡立て、すすぎ、繰り返します。


2

見た目ほど難しくありません。子供の頃;)私はいくつかのx86分解を念頭に置いていました。

あなたも特にそれを学ぶ必要はありません。ASMでプログラミングしてから、インタラクティブな逆アセンブラーを使用してサードパーティのバイナリを修正しようとすると、それが起こります。または、コード暗号化を使用して独自の保護を作成する場合。

つまり、言語からコードに移行するのも当然のことです。


1

最初のコンパイラは、アセンブリ言語を使用して実装されました。そして、最初のアセンブラは、プログラムをバイナリでコーディングすることにより実装されました...


バイナリでのプログラミングが依然として人々が使用するスキルであったことは、それほど昔ではありません。

私が学部生だったとき、PDP-8(と思う)マシンコードで小さなプログラムを作成し、フロントパネルのスイッチから入力して実行するプログラミング演習を行ったことを覚えています。数年後、プログラムを入力するための六角キーパッドと4kバイトのRAMを備えた6502システム開発キットを購入しました。


-3

非常に簡単な回答ハードワイヤードプログラムを作成し、ROMに保存するとします。コンパイラと見なすことができます。ですから、私が言いたいのは、最初のコンパイラはハードワイヤードであったということです。テクノロジーが改善されると、これらの単純なコンパイラーが高レベルのコンパイラーを作成するために使用されました。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.