Bagaimana kompiler pertama dibuat?

70

Saya selalu bertanya-tanya, dan mungkin saya perlu pelajaran sejarah yang baik tentang bahasa pemrograman. Tetapi karena sebagian besar kompiler saat ini dibuat dalam C, bagaimana kompiler pertama dibuat (AKA sebelum C) atau semua bahasa hanya ditafsirkan?

Dengan itu dikatakan, saya masih tidak mengerti bagaimana bahkan bahasa assembly pertama dilakukan, saya mengerti apa bahasa assembly tapi saya tidak melihat bagaimana mereka membuat bahasa assembly pertama SANGAT bekerja (seperti, bagaimana mereka membuat yang pertama perintah (suka mov R21) atau tidak diatur ke setara biner?

agas
sumber
9
Pernah ada programmer yang benar-benar tidak kompeten di tim saya, di mana yang dia lakukan hanyalah mengeluh tentang C #. Kami biasa bercanda tentang bahasa fiksi yang ia ciptakan bernama Crunk. Sebuah fakta yang sedikit diketahui tentang Crunk, itu adalah bahasa pertama di mana kompiler JUGA ditulis dalam Crunk. :)
maple_shaft
2
Mengapa seseorang mengeluh tentang C #? apakah dia tidak pernah menggunakan smalltalk atau Lisp? lol
2
kemungkinan duplikat dari kompiler C dan Dennis Ritchie
vartec
4
@maple_shaft: untuk menjadi adil, compiler gcc ditulis dalam C . Itu sebenarnya bukan masalah jika Anda memiliki cross compiler yang baik untuk mengkompilasi versi pertama. Kompiler C pertama, tentu saja, harus ditulis dalam bahasa lain.
Scott Whitlock
5
kemungkinan duplikat dari Bagaimana kompiler pertama ditulis?
Greg Hewgill

Jawaban:

89

Ha, saya sudah melakukan ini. Banyak CPU memiliki instruksi sederhana, ukuran tetap yang panjangnya hanya beberapa byte. Untuk CPU sederhana seperti Motorola 6800 misalnya, Anda dapat memasukkan semua instruksinya pada selembar kertas . Setiap instruksi akan memiliki opcode dua byte yang terkait dengannya, dan argumen. Anda dapat menyusun program dengan mencari opcode setiap instruksi. Anda kemudian akan menulis program Anda di atas kertas , membubuhi keterangan setiap instruksi dengan opcode yang sesuai. Setelah menulis program Anda, Anda dapat membakar setiap opcode secara berurutan ke EPROMyang kemudian akan menyimpan program Anda. Sambungkan EPROM ke CPU dengan instruksi yang tepat di alamat yang benar, dan Anda memiliki program kerja yang sederhana. Dan untuk menjawab pertanyaan Anda selanjutnya, ya. Itu menyakitkan (kami melakukan ini di sekolah menengah). Tapi saya harus mengatakan bahwa memasang setiap chip di komputer 8-bit dan menulis program secara manual memberi saya pemahaman mendalam tentang arsitektur komputer yang mungkin tidak bisa saya dapatkan dengan cara lain.

Chip yang lebih canggih (seperti x86) jauh lebih sulit untuk kode tangan, karena mereka sering memiliki instruksi panjang variabel. Prosesor VLIW / EPIC seperti Itanium hampir tidak mungkin untuk kode tangan secara efisien karena mereka berurusan dengan paket instruksi yang dioptimalkan dan dirakit oleh kompiler canggih. Untuk arsitektur baru, program hampir selalu ditulis dan dirakit di komputer lain terlebih dahulu, kemudian dimuat ke dalam arsitektur baru. Bahkan, untuk perusahaan seperti Intel yang benar-benar membangun CPU, mereka dapat menjalankan program aktual pada arsitektur yang belum ada dengan menjalankannya pada simulator. Tapi saya ngelantur ...

Sedangkan untuk kompiler, yang paling sederhana, mereka bisa sedikit lebih dari program "cut and paste". Anda dapat menulis "bahasa tingkat tinggi" yang sangat sederhana, tidak dioptimalkan, yang hanya mengelompokkan bersama instruksi bahasa rakitan sederhana tanpa banyak usaha.

Jika Anda ingin riwayat kompiler dan bahasa pemrograman, saya sarankan Anda GOTO sejarah FORTRAN .

Dave Markle
sumber
27
. . . dan tidak harus itu menjadi "... Saya sarankan Anda JMP ke sejarah ..."
Binary Worrier
2
Saya sangat sangat menyesal. Tetapi saya harus melakukannya. Saya hanya ... pernah. untuk ...
Dave Markle
9
@ Dave: Kamu sadar kamu sudah mati sampai mati oleh Velociraptor ?
Binary Worrier
7
Mereka "tahu" karena mereka benar-benar terprogram untuk melakukan operasi itu ketika mereka melihat sinyal 101010100 untuk instruksi yang diberikan. Mereka sebenarnya memiliki unit on-chip yang bertanggung jawab untuk instruksi decoding instruksi: en.wikipedia.org/wiki/Decoder
Dave Markle
7
Layak ditambahkan: kompiler untuk bahasa baru, ketika ditulis dalam bahasa baru yang sama, kadang-kadang dikompilasi dengan "proto-compiler" yang ditulis dalam bahasa lain yang menghasilkan kode yang benar-benar terbukti, tetapi tidak efisien. Setelah dikompilasi, ia kemudian dijalankan dengan sendirinya untuk menghasilkan kompiler yang cukup cepat. Bandingkan Mesin Von Neumann. : D
BMDan
54

Itulah kompilasi bootstrap tentang (karena tidak ada yang menyebutkan bagaimana itu disebut =).

proses penulisan kompiler (atau assembler) dalam bahasa pemrograman target yang dimaksudkan untuk dikompilasi. Menerapkan teknik ini mengarah ke kompiler self-hosting.

Banyak kompiler untuk banyak bahasa pemrograman yang bootstrap, termasuk kompiler untuk BASIC, ALGOL, C, Pascal, PL / I, Factor, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Skema, Java, Python, Scala dan banyak lagi .. .

Masalah ayam dan telur

Jika seseorang membutuhkan kompiler untuk bahasa X untuk mendapatkan kompiler untuk bahasa X (yang ditulis dalam bahasa X), bagaimana kompiler pertama bisa ditulis? Kemungkinan metode untuk memecahkan masalah ayam atau telur ini termasuk:

  • Menerapkan juru bahasa atau kompiler untuk bahasa X dalam bahasa Y. Niklaus Wirth melaporkan bahwa ia menulis kompilator Pascal pertama di Fortran.
  • Penerjemah atau kompiler lain untuk X telah ditulis dalam bahasa lain Y; ini adalah bagaimana Skema sering di-bootstrap.
  • Versi sebelumnya dari kompiler ditulis dalam subset X yang ada beberapa kompiler lain; ini adalah bagaimana beberapa superset dari Java, Haskell, dan kompiler Free Pascal awal di-bootstrap.
  • Kompiler untuk X dikompilasi silang dari arsitektur lain di mana terdapat kompiler untuk X; beginilah kompiler untuk C biasanya porting ke platform lain. Juga ini adalah metode yang digunakan untuk Free Pascal setelah bootstrap awal.
  • Menulis kompiler dalam X; kemudian mengompilasinya dari sumber (kemungkinan besar dengan cara yang tidak dioptimalkan) dan menjalankannya pada kode untuk mendapatkan kompiler yang dioptimalkan. Donald Knuth menggunakan ini untuk sistem pemrograman melek WEB-nya ...
tanaman merambat
sumber
Tautan bagus yang juga membawa Anda ke en.wikipedia.org/wiki/History_of_compiler_writing . Secara umum, saya pikir kompiler asli ditulis dalam Bahasa Majelis ( en.wikipedia.org/wiki/Assembly_language ). Baru kemudian muncul ide bootstrap atau self-hosting.
Michael Levy
1
+1 AKHIRNYA! Aneh bahwa ini hanya jawaban ketiga yang berperingkat paling tinggi. Ya, bootstrap. Itulah jawabannya
Adam Rackis
15

Pada akhirnya semua komputer beroperasi pada kode biner, yang dimasukkan ke dalam CPU. Kode biner ini sangat alami untuk CPU, tetapi juga sangat tidak berguna bagi manusia. Salah satu cara pertama untuk menulis sebuah program adalah dengan membuat lubang pada kartu. Posisi lubang mewakili posisi bit tertentu dalam sebuah kata, dan ada atau tidaknya lubang ditafsirkan sebagai nol atau satu. Kartu-kartu ini dimasukkan ke dalam urutan yang benar dalam sebuah kotak, dan kemudian dimasukkan ke dalam pembaca kartu, yang secara efektif mengubahnya menjadi kode biner untuk CPU (dan hidup Anda secara efektif hangus jika Anda menjatuhkan kotak itu).

Jelas pemrogram pertama mengerjakan kode biner satu per satu dan memiliki mesin untuk meninju kartu. Ini pada dasarnya adalah pemrograman bahasa rakitan di tangan dan lutut Anda. Setelah Anda memilikinya, Anda dapat membuat semua hal lain dari itu: editor teks sederhana, kompiler bahasa assembly (untuk mengubah pernyataan perakitan teks menjadi kode biner), linker dan loader. Dan sisanya, seperti kata mereka, adalah sejarah.

wolfgangsz
sumber
4
Sebelum kartu Anda memiliki satu set sakelar untuk alamat, satu set untuk kata data dan sakelar untuk memuat data. Anda memprogram setiap alamat memori satu per satu dengan menyetel sakelar alamat dan data dengan representasi biner dan mematikan sakelar muat. Butuh waktu lama tetapi program hanya beberapa kata - byte belum ditemukan saat itu.
uɐɪ
4
... Dan sebelum itu, Anda harus memperbaikinya . Senang senang senang!
Michael K
Ya, tetapi ketika Anda harus melakukan itu, itu tidak benar-benar apa yang kita pikirkan sebagai komputer modern, karena arsitektur Von Neumann belum ditemukan.
Dave Markle
7

Sedikit googling muncul Pesanan Awal EDSAC dari akhir 40-an. Karena itu adalah assembler pertama, itu mungkin dikodekan dalam bahasa mesin.

Kemudian datang assembler untuk mesin lain, seperti SOAP I dan II untuk IBM 650. SOAP saya juga mungkin dikodekan dalam bahasa mesin, meskipun saya belum menemukan pernyataan definitif.

Beberapa saat kemudian datang Fortran (penerjemah rumus), untuk IBM 704. Agaknya itu ditulis dalam assembler untuk 704. Assembler awal untuk 701 dikreditkan ke Nathan Rochester .

Jika Anda ingin mendapatkan ide bagaimana memprogram komputer dalam bahasa mesin, lihat salah satu situs favorit saya, komputer relai Harry Porter .

Mike Dunlavey
sumber
Omong kosong, Harry Porter (hampir dikatakan harry potter lol) komputer homebuilt adalah MENGAGUMKAN. Saya berharap saya mengerti bagaimana sesuatu seperti itu dibangun :(.
1
@Sauron: Harry Porter tidak ingin lebih baik daripada memberi tahu Anda. Dari halaman itu dia punya powerpoint yang dibuat dengan indah menjelaskan semuanya. Memang mengasumsikan beberapa pengetahuan dasar tentang sirkuit, tapi itu tidak terlalu sulit untuk didapatkan.
Mike Dunlavey
Saya tahu saya hanya messin ^ _ ^, terlepas dari itu mesin yang sangat mengesankan dan saya yakin banyak jam penyihir dimasukkan ke dalamnya :).
6

Mungkin (jika membosankan) untuk menulis kode mesin langsung. Mungkin Anda menuliskan program dalam assembler di selembar kertas, dan kemudian Anda menerjemahkannya dengan tangan ke dalam instruksi kode mesin numerik yang Anda masukkan ke dalam memori mesin. Anda bahkan dapat melewatkan langkah assembler-on-paper jika Anda telah menghafal nilai numerik dari semua instruksi kode mesin - tidak jarang pada masa itu, percaya atau tidak!

Komputer pertama diprogram secara langsung dalam biner dengan mengaktifkan sakelar fisik. Itu adalah peningkatan produktivitas yang hebat ketika perangkat keras berevolusi untuk membiarkan programmer (atau asisten entri data) memasukkan kode dalam angka heksadesimal melalui keypad!

Assembler perangkat lunak hanya menjadi relevan ketika lebih banyak memori tersedia (karena kode assembler membutuhkan lebih banyak ruang daripada kode mesin mentah) dan perangkat keras berevolusi untuk memungkinkan input alfanumerik. Jadi assembler pertama ditulis langsung oleh orang yang fasih dalam kode mesin.

Ketika Anda memiliki assembler, Anda dapat menulis kompiler untuk bahasa tingkat yang lebih tinggi di assembler.

Kisah untuk C memiliki beberapa langkah. Kompiler C pertama ditulis dalam B (pendahulu C) yang pada gilirannya ditulis dalam BCPL. BCPL adalah bahasa yang cukup sederhana (misalnya tidak memiliki tipe sama sekali), tetapi masih merupakan langkah maju dari assembler mentah. Jadi, Anda dapat melihat bagaimana bahasa yang lebih rumit secara bertahap dibangun dalam bahasa yang lebih sederhana sampai ke assembler. Dan itu sendiri C adalah bahasa yang sangat kecil dan sederhana menurut standar todays.

Saat ini, kompiler pertama untuk bahasa baru sering ditulis dalam C, tetapi ketika bahasa mencapai kematangan tertentu sering ditulis ulang "dalam dirinya sendiri". Kompiler Java pertama ditulis dalam C, tetapi kemudian ditulis ulang dalam Java. Compiler C # pertama ditulis dalam C ++, tetapi baru-baru ini telah ditulis ulang dalam C #. Compiler / interpreter Python ditulis dalam C, tetapi proyek PyPy adalah upaya untuk menulis ulang dengan Python.

Namun tidak selalu layak untuk menulis kompiler / juru bahasa untuk bahasa itu sendiri. Penerjemah JavaScript yang ditulis dalam JavaScript ada, tetapi kompiler / juru bahasa di browser saat ini masih ditulis dalam C atau C ++ untuk alasan kinerja. JavaScript yang ditulis dalam JavaScript terlalu lambat.

Tetapi Anda tidak harus menggunakan C sebagai "bahasa awal" untuk kompiler. Kompiler F # pertama ditulis dalam OCaml, yang merupakan bahasa lain yang paling dekat hubungannya dengan F #. Ketika kompiler selesai, itu ditulis ulang dalam F #. Kompiler pertama untuk Perl 6 ditulis dalam Haskell (bahasa fungsional murni yang sangat berbeda dari Perl) tetapi sekarang memiliki kompiler yang ditulis dalam C.

Kasus yang menarik adalah Rust, di mana kompiler pertama ditulis dalam OCaml (sekarang ditulis ulang di Rust). Ini penting karena OCaml umumnya dianggap tingkat yang lebih tinggi daripada Rust, yang merupakan bahasa sistem yang lebih dekat dengan logam. Jadi tidak selalu bahasa tingkat tinggi diimplementasikan dalam bahasa tingkat rendah, mungkin juga sebaliknya.

JacquesB
sumber
3

Dengan asumsi Anda mulai dengan set instruksi kosong dan tidak ada yang lain, Anda akan mulai dengan membuat assembler atau kompiler minimal , yang hampir tidak berfungsi yang dapat memuat file, parsing subset minimal dari bahasa target, dan menghasilkan executable file sebagai output, dengan menulis kode mesin mentah menggunakan hex editor atau sejenisnya.

Anda kemudian akan menggunakan kompiler atau assembler yang baru saja berfungsi untuk mengimplementasikan kompiler atau assembler yang sedikit lebih mampu yang dapat mengenali subset yang lebih besar dari bahasa target. Busurkan, bilas, ulangi, sampai Anda memiliki produk akhir.

John Bode
sumber
2

Tidak begitu sulit, seperti yang terlihat. Di masa kecil;) Saya membuat beberapa x86 dalam pikiran.

Anda bahkan tidak perlu mempelajarinya terutama. Itu hanya terjadi, ketika Anda dapat memprogram dalam ASM dan kemudian mencoba untuk memperbaiki biner pihak ketiga menggunakan disassembler interaktif. Atau saat menulis perlindungan Anda sendiri dengan enkripsi kode.

Yaitu kadang-kadang Anda bermigrasi bahkan dari bahasa ke kode tanpa heran.

Pavel Koryagin
sumber
1

Kompiler pertama diimplementasikan menggunakan bahasa assembly. Dan assembler pertama diimplementasikan oleh program pengkodean dalam biner ...


Belum lama ini bahwa pemrograman dalam biner masih merupakan keterampilan yang digunakan orang.

Ketika saya masih sarjana, saya ingat melakukan latihan pemrograman yang mengharuskan menulis sebuah program kecil dalam kode mesin PDP-8 (saya pikir), memasukkannya melalui saklar panel depan, dan menjalankannya. Saya beberapa tahun kemudian, saya membeli sendiri kit pengembangan sistem 6502 yang memiliki tombol hex untuk memasukkan program ... dan 4k byte RAM.

Stephen C
sumber
-3

JAWABAN SANGAT SEDERHANA Misalkan kita menulis program bawaan dan menyimpannya dalam ROM. Itu dapat dianggap sebagai kompiler. Jadi saya hanya ingin mengatakan bahwa kompiler pertama adalah bawaan. Ketika teknologi ditingkatkan, kompiler sederhana ini kemudian digunakan untuk menulis kompiler tingkat tinggi.

DINOTOPO
sumber