Trình biên dịch đầu tiên được thực hiện như thế nào?


70

Tôi luôn tự hỏi điều này, và có lẽ tôi cần một bài học lịch sử tốt về ngôn ngữ lập trình. Nhưng vì hầu hết các trình biên dịch hiện nay đều được tạo bằng C, các trình biên dịch đầu tiên được tạo ra (AKA trước C) như thế nào hoặc tất cả các ngôn ngữ vừa được giải thích?

Nói như vậy, tôi vẫn không hiểu ngôn ngữ lắp ráp đầu tiên được thực hiện như thế nào, tôi hiểu ngôn ngữ lắp ráp là gì nhưng tôi không thấy cách chúng làm cho ngôn ngữ lắp ráp đầu tiên RẤT hoạt động các lệnh (như mov R21) hoặc w / e được đặt thành tương đương nhị phân?


9
Có một lập trình viên không hài hước trong nhóm của tôi một lần, nơi tất cả những gì anh ta làm là phàn nàn về C #. Chúng tôi thường nói đùa về một ngôn ngữ hư cấu mà ông đã phát minh ra được gọi là Crunk. Một sự thật ít được biết đến về Crunk, đây là ngôn ngữ đầu tiên mà trình biên dịch C ALNG được viết bằng Crunk. :)
maple_shaft

2
Tại sao ai đó sẽ phàn nàn về C #? Anh ta chưa bao giờ sử dụng smalltalk hay Lisp? lol


4
@maple_shaft: phải công bằng, các trình biên dịch gcc được viết bằng C . Đó thực sự không phải là vấn đề nếu bạn có một trình biên dịch chéo tốt để biên dịch phiên bản đầu tiên. Trình biên dịch C đầu tiên, tất nhiên, phải được viết bằng ngôn ngữ khác.
Scott Whitlock

Câu trả lời:


89

Ha, tôi đã làm điều này. Nhiều CPU có các lệnh đơn giản, có kích thước cố định chỉ dài vài byte. Ví dụ, đối với một CPU đơn giản như Motorola 6800, bạn có thể đặt tất cả các hướng dẫn của nó trên một tờ giấy . Mỗi hướng dẫn sẽ có một opcode hai byte được liên kết với nó và các đối số. Bạn có thể tự lắp ráp một chương trình bằng cách tra cứu opcode của mỗi lệnh. Sau đó, bạn sẽ viết chương trình của mình ra giấy , chú thích từng hướng dẫn với opcode tương ứng. Khi bạn đã viết ra chương trình của mình, bạn có thể ghi từng opcode theo trình tự vào EPROMmà sau đó sẽ lưu trữ chương trình của bạn. Kết nối EPROM với CPU chỉ bằng đúng hướng dẫn tại đúng địa chỉ và bạn có một chương trình làm việc đơn giản. Và để trả lời câu hỏi tiếp theo của bạn, vâng. Thật đau đớn (chúng tôi đã làm điều này ở trường trung học). Nhưng tôi phải nói rằng việc kết nối mọi chip trong máy tính 8 bit và viết chương trình theo cách thủ công đã cho tôi hiểu sâu về kiến ​​trúc máy tính mà tôi có lẽ không thể đạt được bằng bất kỳ cách nào khác.

Các chip nâng cao hơn (như x86) khó mã hóa hơn nhiều, vì chúng thường có các hướng dẫn có độ dài thay đổi. Các bộ xử lý VLIW / EPIC như Itanium gần như không thể mã hóa hiệu quả vì chúng xử lý các gói hướng dẫn được tối ưu hóa và lắp ráp bởi các trình biên dịch tiên tiến. Đối với kiến ​​trúc mới, các chương trình hầu như luôn được viết và lắp ráp trên một máy tính khác trước, sau đó được tải vào kiến ​​trúc mới. Trên thực tế, đối với các công ty như Intel, những người thực sự xây dựng CPU, họ có thể chạy các chương trình thực tế trên các kiến ​​trúc chưa tồn tại bằng cách chạy chúng trên các trình giả lập. Nhưng tôi lạc đề...

Đối với các trình biên dịch, rất đơn giản, chúng có thể ít hơn các chương trình "cắt và dán". Bạn có thể viết một "ngôn ngữ cấp cao" rất đơn giản, không tối ưu hóa, chỉ tập hợp các hướng dẫn ngôn ngữ lắp ráp đơn giản mà không cần nhiều nỗ lực.

Nếu bạn muốn có lịch sử trình biên dịch và ngôn ngữ lập trình, tôi khuyên bạn nên GOTO một lịch sử của FORTRAN .


27
. . . và không phải là "... Tôi đề nghị bạn JMP vào lịch sử ..."
Binary Worrier

2
Tôi rất rất rất xin lỗi. Nhưng tôi đã phải. Tôi chỉ ... đã có. đến ...
Dave Markle

9
@Dave: Bạn có nhận ra mình đã tự kết liễu đời mình bằng Velociraptor ?
Nhị phân nhị phân

7
Họ "biết" bởi vì họ thực sự cứng cáp để thực hiện thao tác đó khi họ thấy tín hiệu 101010100 cho một hướng dẫn cụ thể. Họ thực sự có một đơn vị trên chip chịu trách nhiệm hướng dẫn giải mã hướng dẫn: en.wikipedia.org/wiki/Decoder
Dave Markle

7
Đáng để thêm vào: trình biên dịch cho một ngôn ngữ mới, khi được viết bằng chính ngôn ngữ mới đó, đôi khi được biên dịch bằng một "trình biên dịch proto" được viết bằng một ngôn ngữ khác tạo ra mã chính xác, nhưng không hiệu quả khủng khiếp. Sau khi được biên dịch, nó sẽ tự chạy để tạo ra một trình biên dịch nhanh hợp lý. So sánh máy Von Neumann. : D
BMDan

54

Đó là những gì trình biên dịch bootstrapping nói về (vì không ai đề cập đến cách nó được gọi là =).

quá trình viết một trình biên dịch (hoặc trình biên dịch) trong ngôn ngữ lập trình đích mà nó dự định biên dịch. Áp dụng kỹ thuật này dẫn đến một trình biên dịch tự lưu trữ.

Nhiều trình biên dịch cho nhiều ngôn ngữ lập trình được bootstrapping, bao gồm các trình biên dịch cho BASIC, ALGOL, C, Pascal, PL / I, Factor, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Scheme, Java, Python, Scala, v.v. .

Vấn đề gà và trứng

Nếu người ta cần một trình biên dịch cho ngôn ngữ X để có được trình biên dịch cho ngôn ngữ X (được viết bằng ngôn ngữ X), trình biên dịch đầu tiên được viết như thế nào? Các phương pháp có thể để giải quyết vấn đề gà hoặc trứng này bao gồm:

  • Triển khai trình thông dịch hoặc trình biên dịch cho ngôn ngữ X bằng ngôn ngữ Y. Niklaus Wirth đã báo cáo rằng ông đã viết trình biên dịch Pascal đầu tiên ở Fortran.
  • Một trình thông dịch hoặc trình biên dịch cho X đã được viết bằng ngôn ngữ Y khác; đây là cách Scheme thường được bootstrapping.
  • Các phiên bản trước đó của trình biên dịch được viết trong một tập hợp con của X có tồn tại một số trình biên dịch khác; đây là cách một số supersets của Java, Haskell và trình biên dịch Free Pascal ban đầu được bootstrapping.
  • Trình biên dịch cho X được biên dịch chéo từ một kiến ​​trúc khác, nơi tồn tại một trình biên dịch cho X; đây là cách trình biên dịch cho C thường được chuyển sang các nền tảng khác. Ngoài ra đây là phương thức được sử dụng cho Free Pascal sau bootstrap ban đầu.
  • Viết trình biên dịch trong X; sau đó biên dịch thủ công từ nguồn (rất có thể theo cách không được tối ưu hóa) và chạy mã đó để có được trình biên dịch tối ưu hóa. Donald Knuth đã sử dụng điều này cho hệ thống lập trình biết chữ WEB của mình ...

Liên kết tốt cũng đưa bạn đến en.wikipedia.org/wiki/History_of_compiler_ Writing . Nói chung, tôi nghĩ rằng các trình biên dịch gốc đã được viết bằng ngôn ngữ hội ( en.wikipedia.org/wiki/Ass lanh_lingu ). Chỉ sau đó, ý tưởng về bootstrapping hoặc tự lưu trữ xuất hiện.
Michael Levy

1
+1 CUỐI CÙNG! Điều lạ lùng là đây chỉ là câu trả lời được đánh giá cao thứ ba. Vâng, bootstrapping. Đó là câu trả lời
Adam Rackis

15

Cuối cùng, tất cả các máy tính hoạt động trên mã nhị phân, được đưa vào CPU. Các mã nhị phân này là hoàn toàn tự nhiên đối với CPU, nhưng cũng hoàn toàn vô dụng đối với con người. Một trong những cách đầu tiên để viết chương trình là bằng cách đục lỗ vào thẻ. Vị trí của các lỗ đại diện cho một vị trí bit cụ thể trong một từ và sự hiện diện hay vắng mặt của lỗ được hiểu là số 0 hoặc số một. Các thẻ này được đưa vào đúng trình tự trong một hộp, sau đó được đưa vào đầu đọc thẻ, giúp chuyển đổi chúng thành mã nhị phân cho CPU một cách hiệu quả (và cuộc sống của bạn đã bị mất hiệu quả nếu bạn đánh rơi hộp).

Rõ ràng là các lập trình viên đầu tiên đã tìm ra từng mã nhị phân và có một máy để đục các thẻ. Đây thực chất là lập trình ngôn ngữ lắp ráp trên tay và đầu gối của bạn. Khi bạn đã có, bạn có thể tạo tất cả những thứ khác từ nó: trình soạn thảo văn bản đơn giản, trình biên dịch ngôn ngữ lắp ráp (để chuyển đổi các câu lệnh lắp ráp văn bản thành mã nhị phân), trình liên kết và trình tải. Và cuối cùng. Như họ nói, là lịch sử.


4
Trước thẻ bạn có một bộ công tắc cho địa chỉ, một bộ cho từ dữ liệu và công tắc để tải dữ liệu. Bạn đã lập trình riêng từng địa chỉ bộ nhớ bằng cách đặt địa chỉ và chuyển đổi dữ liệu với biểu diễn nhị phân và bật công tắc tải sau đó tắt. Mất nhiều thời gian nhưng chương trình chỉ dài vài từ - byte chưa được phát minh.
uɐɪ

4
... Và trước đó, bạn phải tua lại . Vui vui vui!
Michael K

Vâng, nhưng khi bạn phải làm điều đó, đó thực sự không phải là những gì chúng ta nghĩ về một máy tính hiện đại, vì kiến ​​trúc Von Neumann chưa được phát minh.
Dave Markle

7

Một chút googling bật lên Đơn đặt hàng ban đầu EDSAC từ cuối những năm 40. Vì nó là trình biên dịch đầu tiên, nên nó có thể được mã hóa bằng ngôn ngữ máy.

Sau đó, các nhà lắp ráp cho các máy khác, như SOAP I và II cho IBM 650. SOAP I cũng có thể được mã hóa bằng ngôn ngữ máy, mặc dù tôi không tìm thấy tuyên bố dứt khoát.

Một lát sau, Fortran (dịch giả công thức), cho IBM 704. Có lẽ nó được viết bằng trình biên dịch cho 704. Một trình biên dịch ban đầu cho 701 được ghi có vào Nathan Rochester .

Nếu bạn muốn có ý tưởng về cách lập trình máy tính bằng ngôn ngữ máy, hãy xem một trong những trang web yêu thích của tôi, máy tính chuyển tiếp của Harry Porter .


Holy crap, Harry Porter (gần như đã nói harry potter lol) máy tính xây dựng nhà là TUYỆT VỜI. Tôi ước tôi hiểu làm thế nào một thứ như thế được xây dựng :(.

1
@Sauron: Harry Porter không muốn gì tốt hơn là nói với bạn. Trên trang đó , anh ta có một powerpoint được chế tạo rất đẹp để giải thích tất cả. Nó không thừa nhận một số kiến ​​thức cơ bản về mạch điện, nhưng điều đó không quá khó để có được.
Mike Dunlavey

Tôi biết tôi chỉ làm hỏng ^ _ ^, bất kể đó là một cỗ máy rất ấn tượng và tôi chắc chắn rằng nhiều giờ thuật sĩ đã được đưa vào đó :).

6

Có thể (nếu tẻ nhạt) để viết mã máy trực tiếp. Có thể bạn viết chương trình xuống trình biên dịch trên một tờ giấy và sau đó bạn dịch nó bằng tay vào các hướng dẫn mã số máy mà bạn nhập vào bộ nhớ máy. Bạn thậm chí có thể bỏ qua bước biên dịch trên trình biên dịch nếu bạn đã ghi nhớ các giá trị số của tất cả các hướng dẫn mã máy - không phổ biến trong những ngày đó, tin hay không!

Các máy tính đầu tiên được lập trình trực tiếp dưới dạng nhị phân bằng cách chuyển đổi các công tắc vật lý. Đó là một cải tiến năng suất tuyệt vời khi phần cứng phát triển để cho phép lập trình viên (hoặc trợ lý nhập dữ liệu) nhập mã theo số thập lục phân thông qua bàn phím!

Trình biên dịch phần mềm chỉ trở nên có liên quan khi có nhiều bộ nhớ hơn (vì mã trình biên dịch chiếm nhiều dung lượng hơn mã máy thô) và phần cứng được phát triển để cho phép nhập chữ và số. Vì vậy, các bộ lắp ráp đầu tiên được viết trực tiếp bởi những người thông thạo mã máy.

Khi bạn có trình biên dịch chương trình, bạn có thể viết trình biên dịch cho ngôn ngữ cấp cao hơn trong trình biên dịch chương trình.

Câu chuyện cho C có nhiều bước. Trình biên dịch C đầu tiên được viết bằng B (tiền thân của C), lần lượt được viết bằng BCPL. BCPL là một ngôn ngữ khá đơn giản (ví dụ: nó hoàn toàn không có loại), nhưng vẫn là một bước tiến từ trình biên dịch thô. Vì vậy, bạn thấy các ngôn ngữ phức tạp hơn dần dần được xây dựng bằng các ngôn ngữ đơn giản hơn tất cả các cách quay lại trình biên dịch. Và bản thân C là một ngôn ngữ khá nhỏ và đơn giản theo tiêu chuẩn ngày nay.

Ngày nay, trình biên dịch đầu tiên cho một ngôn ngữ mới thường được viết bằng C, nhưng khi ngôn ngữ đạt đến độ chín nhất định, nó thường được viết lại "trong chính nó". Trình biên dịch Java đầu tiên được viết bằng C, nhưng sau đó được viết lại bằng Java. Trình biên dịch C # đầu tiên được viết bằng C ++, nhưng gần đây nó đã được viết lại bằng C #. Trình biên dịch / trình thông dịch Python được viết bằng C, nhưng dự án PyPy là một nỗ lực để viết lại nó trong Python.

Mặc dù không phải lúc nào cũng có thể viết trình biên dịch / trình thông dịch cho một ngôn ngữ bằng chính ngôn ngữ đó. Trình thông dịch JavaScript được viết bằng JavaScript tồn tại, nhưng trình biên dịch / trình thông dịch trong các trình duyệt hiện tại vẫn được viết bằng C hoặc C ++ vì lý do hiệu suất. JavaScript được viết bằng JavaScript đơn giản là quá chậm.

Nhưng bạn không phải sử dụng C làm "ngôn ngữ bắt đầu" cho trình biên dịch. Trình biên dịch F # đầu tiên được viết bằng OCaml, đây là ngôn ngữ khác có liên quan chặt chẽ nhất với F #. Khi trình biên dịch hoàn tất, nó đã được viết lại trong F #. Trình biên dịch đầu tiên cho Perl 6 được viết bằng Haskell (một ngôn ngữ chức năng thuần túy rất khác với Perl) nhưng giờ đây có một trình biên dịch được viết bằng C.

Một trường hợp thú vị là Rust, nơi trình biên dịch đầu tiên được viết bằng OCaml (bây giờ nó được viết lại trong Rust). Điều này là đáng chú ý vì OCaml thường được coi là cấp cao hơn Rust, là ngôn ngữ hệ thống gần gũi với kim loại hơn. Vì vậy, không phải lúc nào các ngôn ngữ cấp cao hơn cũng được triển khai bằng các ngôn ngữ cấp thấp hơn, nó cũng có thể là cách khác.


3

Giả sử bạn bắt đầu với một tập lệnh trần và không có gì khác, bạn sẽ bắt đầu bằng cách tạo một trình biên dịch hoặc trình biên dịch tối thiểu , hầu như không có chức năng có thể tải tệp, phân tích một tập hợp con tối thiểu của ngôn ngữ đích và tạo ra một tệp thực thi tập tin như đầu ra, bằng cách viết mã máy thô bằng trình soạn thảo hex hoặc tương tự.

Sau đó, bạn sẽ sử dụng trình biên dịch hoặc trình biên dịch chỉ có chức năng hầu như không có chức năng này để triển khai trình biên dịch hoặc trình biên dịch có khả năng hơn một chút có thể nhận ra một tập hợp con lớn hơn của ngôn ngữ đích. Bọt, rửa, lặp lại, cho đến khi bạn có sản phẩm cuối cùng.


2

Nó không quá khó, như có vẻ. Trong thời thơ ấu;) Tôi đã thực hiện một số phân tách x86 trong tâm trí.

Bạn thậm chí không cần phải học nó đặc biệt. Nó chỉ xảy ra, khi bạn có thể lập trình trong ASM và sau đó cố gắng sửa lỗi nhị phân của bên thứ ba bằng cách sử dụng trình phân tách tương tác. Hoặc khi viết bảo vệ của riêng bạn với mã hóa mã.

Tức là đôi khi bạn đang di chuyển thậm chí từ ngôn ngữ sang mã mà không có gì lạ.


1

Các trình biên dịch đầu tiên được thực hiện bằng ngôn ngữ lắp ráp. Và các trình biên dịch đầu tiên được thực hiện bởi các chương trình mã hóa trong nhị phân ...


Cách đây không lâu, lập trình nhị phân vẫn là một kỹ năng mà mọi người sử dụng.

Khi tôi còn là sinh viên, tôi nhớ đã làm một bài tập lập trình đòi hỏi phải viết một chương trình nhỏ bằng mã máy PDP-8 (tôi nghĩ), nhập nó thông qua các công tắc bảng mặt trước và chạy nó. Vài năm sau, tôi đã mua cho mình một bộ công cụ phát triển hệ thống 6502 có bàn phím hex để vào các chương trình ... và 4k byte RAM.


-3

MỘT TRẢ LỜI ĐƠN GIẢN RẤT NHIỀU Giả sử rằng chúng ta viết một chương trình cứng và lưu trữ nó trong ROM. Nó có thể được coi là trình biên dịch. Vì vậy, tôi chỉ muốn nói rằng trình biên dịch đầu tiên đã được cài đặt sẵn. Khi công nghệ cải tiến, các trình biên dịch đơn giản này sau đó được sử dụng để viết các trình biên dịch cấp cao.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.