私はいつもこれを疑問に思っており、おそらくプログラミング言語に関する良い歴史のレッスンが必要です。しかし、最近のほとんどのコンパイラーはCで作成されているため、最初のコンパイラーはどのようにして(Cの前にAKAで)作成されたのか、またはすべての言語が単に解釈されたのか?
それが言われても、私は最初のアセンブリ言語でさえどのように行われたのかまだ理解していません、アセンブリ言語が何であるかは理解していますが、彼らが非常に最初のアセンブリ言語をどのように機能させたのかわかりませんコマンド(mov R21
など)または同等のバイナリに設定されたw/e?
ハ、私はこれをやった。多くのCPUには、数バイト長の単純な固定サイズの命令があります。たとえばMotorola 6800のような単純なCPUの場合、そのすべての命令を 1枚の紙 に収めることができます。各命令には、それに関連付けられた2バイトのオペコードと引数があります。各命令のオペコードを調べることにより、プログラムを手動で組み立てることができます。次に、それぞれの命令に対応するオペコードの注釈を付ける 紙のプログラム を記述します。プログラムを作成したら、各オペコードを順番に [〜#〜] eprom [〜#〜] に書き込むことができます。これにより、プログラムが保存されます。適切なアドレスで適切な命令を使用してEPROMをCPUに配線すると、簡単な作業プログラムができます。そして、あなたの次の質問に答えるために、はい。痛かった(高校でやった)。しかし、8ビットコンピュータのすべてのチップを配線してプログラムを手動で作成すると、コンピュータアーキテクチャを深く理解できたので、他の方法では達成できなかったと思います。
より高度なチップ(x86など)は、可変長の命令を持っていることが多いため、手動でコード化するのははるかに困難です。 Itanium のようなVLIW/EPICプロセッサは、高度なコンパイラによって最適化およびアセンブルされた命令のパケットを処理するため、効率的にハンドコーディングすることはほぼ不可能です。新しいアーキテクチャーの場合、プログラムはほとんどの場合、最初に別のコンピューターで作成およびアセンブルされ、次に新しいアーキテクチャーにロードされます。実際、実際にCPUを構築しているIntelなどの企業は、シミュレータで実行することにより、まだ存在しないアーキテクチャで実際のプログラムを実行できます。しかし、私は余談です...
コンパイラーについては、非常に単純な場合、「カットアンドペースト」プログラムにすぎません。非常にシンプルで最適化されていない、「高水準言語」を書くことができます。これは、多くの労力をかけずに、単純なアセンブリ言語の命令をクラスター化するだけです。
コンパイラとプログラミング言語の履歴が必要な場合は、履歴 [〜#〜] fortran [〜#〜] にGOTOすることをお勧めします。
それが コンパイラブートストラップ の意味です(これが=と呼ばれる方法について誰も言及していないため)。
コンパイラー(またはアセンブラー)をコンパイルすることを目的としたターゲット・プログラミング言語で作成するプロセスこの手法を適用すると、セルフホスティングコンパイラが作成されます。
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リテラシープログラミングシステムに使用しました...
最終的に、すべてのコンピュータは、CPUに供給されるバイナリコードで動作します。これらのバイナリコードは、CPUにとって完全に自然ですが、人間にとってはまったく役に立ちません。プログラムを作成する最初の方法の1つは、カードに穴を開けることでした。穴の位置はワード内の特定のビット位置を表し、穴の有無はゼロまたは1と解釈されました。これらのカードは箱の正しい順序に入れられてからカードリーダーに送られ、CPUのバイナリコードに効果的に変換されました(箱を落とした場合、あなたの人生は事実上没収されました)。
明らかに、最初のプログラマはバイナリコードを1つずつ作成し、カードをパンチするマシンを持っていました。これは基本的に、あなたの手と膝のアセンブリ言語プログラミングです。それができたら、簡単なテキストエディター、アセンブリ言語コンパイラー(テキストのAssemblyステートメントをバイナリコードに変換するため)、リンカー、ローダーなど、他のすべてのものを作成できます。そして、残りは、彼らが言うように、歴史です。
少しグーグルが発生します EDSAC初回注文 40代後半から。それは最初のアセンブラーだったので、おそらく機械語でコード化されました。
後で他のマシン用のアセンブラ、たとえばIBM 650の SOAP IとII が登場しました。SOAP決定的な声明。
少し後、IBM 704用のFortran(式変換プログラム)が登場しました。おそらく704用のアセンブラーで作成されたものです。701用の初期のアセンブラーは Nathan Rochester とされています。
コンピューターを機械語でプログラミングする方法について知りたい場合は、私のお気に入りのサイト ハリーポーターのリレーコンピューター をチェックしてください。
(面倒な場合は)直接のマシンコードを書くことは可能です。多分あなたは一枚の紙にアセンブラでプログラムを書き留め、それからあなたはそれをあなたがマシンのメモリに入力する数値のマシンコード命令に手で翻訳します。マシンコードのすべての命令の数値を記憶している場合は、アセンブラーオンペーパーの手順をスキップすることもできます。
非常に最初のコンピュータは、物理スイッチを切り替えることによってバイナリで直接プログラムされました。プログラマー(またはデータ入力アシスタント)がキーパッドを介して16進数でコードを入力できるようにハードウェアが進化したとき、それは生産性の大幅な向上でした!
ソフトウェアアセンブラは、より多くのメモリが利用可能になり(アセンブラコードが未加工のマシンコードよりも多くのスペースを占めるため)、英数字入力を可能にするようにハードウェアが進化した場合にのみ関連しました。したがって、最初のアセンブラは、機械コードに精通した人々によって直接作成されました。
アセンブラーがある場合、アセンブラーで高水準言語用のコンパイラーを作成できます。
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で作成されました。OCamlは、F#に最も密接に関連している他の言語です。コンパイラが完了すると、F#で書き直されました。 Perl 6の最初のコンパイラはHaskell(純粋な関数型言語very Perlとは異なる)で書かれていましたが、現在はCで書かれたコンパイラがあります。
興味深いケースはRustで、最初のコンパイラはOCamlで書かれています(現在はRustで書き直されています)。 OCamlは一般に、金属に近いシステム言語であるRustよりも高いレベルと見なされているため、これは注目に値します。したがって、それは常に低水準言語で実装された高水準言語であるとは限らず、逆の場合もあります。
最小限の命令セットから始めて、他に何もないと仮定すると、ファイルをロードし、最小限のサブセットを解析できるminimal 16進エディタなどを使用して未加工のマシンコードを書き込むことにより、ターゲット言語と出力として実行可能ファイルを生成します。
次に、そのほとんど機能しないコンパイラーまたはアセンブラーを使用して、ターゲット言語のより大きなサブセットを認識できる、わずかに機能的なコンパイラーまたはアセンブラーを実装します。最終製品ができるまで、泡立て、すすぎ、繰り返します。
見た目はそれほど難しくありません。子供の頃;)私はいくつかのx86分解を念頭に置いていました。
あなたは特にそれを学ぶ必要さえありません。これは、ASMでプログラミングしてから、インタラクティブな逆アセンブラを使用してサードパーティのバイナリを修正しようとしたときに発生します。または、コード暗号化を使用して独自の保護を記述する場合。
つまり時には、言語からコードへと移行するのも不思議ではありません。
最初のコンパイラは、アセンブリ言語を使用して実装されました。そして、最初のアセンブラは、プログラムをバイナリでコーディングすることによって実装されました...
バイナリでのプログラミングがまだ人々が使っていたスキルだったのはそれほど昔ではありません。
私が大学生だったとき、PDP-8(と思う)のマシンコードで小さなプログラムを作成し、フロントパネルのスイッチから入力して実行するプログラミング演習をしたことを覚えています。数年後、プログラムを入力するための16進キーパッドと4kバイトのRAMを備えた6502システム開発キットを購入しました。