簡単な答え:最初のプログラムは生のマシンコードで細心の注意を払って書かれ、そこからすべてが構築されました。
このアイデアはブートストラップと呼ばれます。プロセッサ、フラッシュメモリ、およびハードディスクを備えたベアマシンがあるとします。通常、プロセッサは電源投入時に、不揮発性メモリ(CMOSやフラッシュなど)の固定位置からブートローダーと呼ばれる単純なオペレーティングシステムをロードするように構成されています。このOSは非常にシンプルで、実際のOSが存在するディスク上の場所にコンピューターを向けるのに十分な機能を備えています。このOSは、最終的にOS全体が稼働するまで、ますます多くのデバイスをオンにし、ますます複雑なプログラムをロードできます。
しかし、このブートローダーは何で書かれていますか?もともと、これらは生のマシンコードで書かれ、マシンにハードコードされていました。実行するプログラムもマシンコードで記述されるため、信じられないほど遅く、操作が面倒になります。最終的に、誰かがマシンコードで最初の単純なアセンブラを作成しました。このアセンブラを入手したら、アセンブラ自体を含め、アセンブリでプログラムの記述を開始できます。実際、単純なアセンブラがあれば、マシンコードを再度記述する必要はありません。アセンブリでアセンブラを書き続けることができます!
この時点から、最初に既存のツール(アセンブラーなど)を使用してコンパイラーを作成し、コンパイラーが基本的なプログラミングを実行できるように十分な機能を利用できるようにすることで、より複雑なプログラミング言語を構築できます。次に、そのコンパイラを使用してプログラミング言語自体のコンパイラを作成し、同じトリックを使用して前の作業を基に、より大きくてクールなものを作成します。この手法は現在でも使用されています。ほとんどのコンパイラは、コンパイル先の言語で記述されています。
要約すると、過去のあるひどい時点ですべてを手作業で行わなければなりませんでしたが、これを行った人々の努力のおかげで、私たちはすでにそこにあるものから構築することができます。