Możliwe jest (jeśli jest to uciążliwe) pisanie bezpośredniego kodu maszynowego. Może zapisujesz program w asemblerze na kawałku papieru, a następnie tłumaczysz go ręcznie na instrukcje numerycznego kodu maszynowego, które wprowadzasz do pamięci maszyny. Możesz nawet pominąć krok asemblera na papierze, jeśli zapamiętałeś wartości liczbowe wszystkich instrukcji kodu maszynowego - nierzadko w tych dniach, wierz lub nie!
Pierwsze komputery były programowane bezpośrednio w systemie binarnym poprzez przełączanie fizycznych przełączników. To była wielka poprawa wydajności, gdy sprzęt ewoluował, aby pozwolić programistowi (lub asystentowi wprowadzania danych) wprowadzać kod w liczbach szesnastkowych za pomocą klawiatury!
Asembler oprogramowania stał się istotny tylko wtedy, gdy stała się dostępna większa pamięć (ponieważ kod asemblera zajmuje więcej miejsca niż surowy kod maszynowy) i sprzęt ewoluował, aby umożliwić wprowadzanie alfanumeryczne. Tak więc pierwsze asemblery zostały napisane bezpośrednio przez osoby biegle posługujące się kodem maszynowym.
Gdy masz asembler, możesz napisać kompilator dla języka wyższego poziomu w asemblerze.
Historia dla C ma wiele kroków. Pierwszy kompilator C został napisany w B (poprzednik C), który z kolei został napisany w BCPL. BCPL jest dość prostym językiem (na przykład w ogóle nie ma typów), ale wciąż jest o krok od surowego asemblera. Widzisz więc, jak stopniowo coraz bardziej skomplikowane języki są budowane w prostszych językach aż do asemblera. A samo C jest dość małym i prostym językiem według dzisiejszych standardów.
Dzisiaj pierwszy kompilator nowego języka jest często pisany w C, ale kiedy język osiąga pewną dojrzałość, często jest przepisywany „sam w sobie”. Pierwszy kompilator Java został napisany w C, ale później przepisany w Javie. Pierwszy kompilator C # został napisany w C ++, ale ostatnio został przepisany w C #. Kompilator / interpreter języka Python jest napisany w języku C, ale projekt PyPy jest próbą przepisania go w języku Python.
Jednak nie zawsze jest możliwe napisanie kompilatora / tłumacza dla języka w samym języku. Istnieje interpreter JavaScript napisany w JavaScript, ale kompilatory / interpretatory w obecnych przeglądarkach są nadal napisane w C lub C ++ ze względu na wydajność. JavaScript napisany w JavaScript jest po prostu zbyt wolny.
Ale nie musisz używać C jako „języka początkowego” kompilatora. Pierwszy kompilator F # został napisany w OCaml, który jest drugim językiem najbardziej zbliżonym do F #. Gdy kompilator został ukończony, został przepisany w języku F #. Pierwszy kompilator dla Perla 6 został napisany w Haskell (czysty język funkcjonalny bardzo różny od Perla), ale teraz ma kompilator napisany w C.
Ciekawym przypadkiem jest Rust, gdzie pierwszy kompilator został napisany w OCaml (teraz jest napisany w Rust). Jest to godne uwagi, ponieważ OCaml jest ogólnie uważany za wyższy poziom niż Rust, który jest językiem systemów zbliżonych do metalu. Dlatego nie zawsze języki wyższego poziomu są implementowane w językach niższego poziomu, może być też na odwrót.