최초의 컴파일러는 어떻게 만들어 졌습니까?


70

나는 항상 이것을 궁금해하며 프로그래밍 언어에 대한 좋은 역사 수업이 필요할 것입니다. 그러나 오늘날 대부분의 컴파일러는 C로 만들어 졌으므로 최초의 컴파일러는 어떻게 만들어 졌습니까 (C 이전의 AKA) 또는 모든 언어가 방금 해석 되었습니까?

그럼에도 불구하고, 나는 여전히 첫 번째 어셈블리 언어가 어떻게 수행되었는지 이해하지 못합니다. 어떤 어셈블리 언어가 무엇인지 이해합니다. 같은 명령 mov R21또는 이진 등가로 설정되어 있습니까?


9
우리 팀에는 만화 적으로 부적절한 프로그래머가 한 번 있었고 C #에 대해 불평했습니다. 우리는 그가 Crunk라고 불리는 가상의 언어에 대해 농담했습니다. Crunk에 대해 조금 알려진 사실은 컴파일러가 Crunk로 작성된 최초의 언어입니다. :)
maple_shaft

2
누군가 C #에 대해 왜 불평합니까? 스몰 토크 나 리스프를 사용한 적이 없습니까? lol


4
@maple_shaft : 공정하게 말하면 gcc 컴파일러는 C로 작성됩니다 . 첫 번째 버전을 컴파일하기에 좋은 크로스 컴파일러가 있다면 실제로 문제가되지 않습니다. 물론 첫 번째 C 컴파일러는 다른 언어로 작성해야했습니다.
Scott Whitlock 2016 년

답변:


89

하, 나는 이것을했다. 많은 CPU에는 몇 바이트 길이의 간단한 고정 크기 명령어가 있습니다. 예를 들어 Motorola 6800과 같은 간단한 CPU의 경우 모든 지침을 한 장의 용지 에 맞출 수 있습니다. 각 명령어에는 2 바이트의 opcode와 관련된 인수와 인수가 있습니다. 각 명령어의 opcode를 찾아 프로그램을 수동으로 어셈블 할 수 있습니다. 그런 다음 각 명령에 해당 opcode로 주석을 달아 프로그램을 paper에 작성합니다 . 프로그램을 작성한 후에는 각 opcode를 EPROM 에 순차적으로 구울 수 있습니다.그러면 프로그램이 저장됩니다. 올바른 주소에 올바른 지침만으로 EPROM을 CPU에 연결하면 간단한 작업 프로그램이 있습니다. 그리고 다음 질문에 대답하기 위해 그렇습니다. 그것은 고통 스러웠다 (우리는 이것을 고등학교에서했다). 그러나 8 비트 컴퓨터의 모든 칩을 배선하고 프로그램을 수동으로 작성하면 다른 방법으로는 달성 할 수 없었던 컴퓨터 아키텍처에 대한 깊이있는 이해를 얻었습니다.

x86과 같은 고급 칩은 종종 가변 길이 명령어를 사용하기 때문에 수작업으로 코딩하기가 훨씬 어렵습니다. Itanium 과 같은 VLIW / EPIC 프로세서 는 고급 컴파일러에 의해 최적화되고 어셈블 된 명령 패킷을 처리하므로 효율적으로 수작업 코딩이 거의 불가능합니다. 새로운 아키텍처의 경우 프로그램은 거의 항상 다른 컴퓨터에서 먼저 작성되고 조립 된 다음 새 아키텍처에로드됩니다. 실제로 실제로 CPU를 구축하는 인텔과 같은 회사의 경우 시뮬레이터에서 실행하여 아직 존재하지 않는 아키텍처에서 실제 프로그램을 실행할 수 있습니다. 하지만 난 ...

컴파일러는 가장 간단하게 "잘라 내기 및 붙여 넣기"프로그램 이상일 수 있습니다. 많은 노력없이 간단한 어셈블리 언어 명령어를 함께 묶는 매우 단순하고 최적화되지 않은 "고급 언어"를 작성할 수 있습니다.

컴파일러와 프로그래밍 언어의 역사를 원한다면 GOTO에게 FORTRAN 의 역사를 제안합니다 .


27
. . . "... 나는 역사에 JMP 를 제안한다 ..."
Binary Worrier

2
정말 죄송합니다 그러나 나는해야만했다. 방금 .. to ...
Dave Markle

9
@Dave : Velociraptor가 당신을 죽음으로 몰아 넣었다는 것을 알고 있습니까?
이진 걱정

7
그들은 주어진 명령에 대해 101010100 신호를 보았을 때 그 동작을 수행하기 위해 문자 그대로 배선되어 있기 때문에 "알았다". 실제로 명령어 디코딩 명령을 담당하는 온칩 유닛이 있습니다. en.wikipedia.org/wiki/Decoder
Dave Markle

7
추가 할 가치가있다 : 새로운 언어를위한 컴파일러는 같은 언어로 작성 될 때, 다른 언어로 작성된 "프로토 컴파일러"로 컴파일 될 수있다. 컴파일이 완료되면 자체적으로 실행되어 상당히 빠른 컴파일러를 생성합니다. Von Neumann Machine을 비교하십시오. : D
BMDan

54

그것이 컴파일러 부트 스트랩 에 관한 것입니다.

컴파일하려는 대상 프로그래밍 언어로 컴파일러 (또는 어셈블러)를 작성하는 프로세스 이 기술을 적용하면 자체 호스팅 컴파일러가 생성됩니다.

BASIC, ALGOL, C, Pascal, PL / I, Factor, Haskell, Modula-2, Oberon, OCaml, Common Lisp, Scheme, Java, Python, Scala 등의 컴파일러를 포함하여 많은 프로그래밍 언어를위한 많은 컴파일러가 부트 스트랩됩니다. .

닭고기와 달걀 문제

언어 X (언어 X로 작성 됨) 용 컴파일러를 얻기 위해 언어 X 용 컴파일러가 필요한 경우 첫 번째 컴파일러는 어떻게 작성 되었습니까? 이 닭 또는 계란 문제를 해결하는 가능한 방법은 다음과 같습니다.

  • 언어 Y에서 언어 X에 대한 인터프리터 또는 컴파일러 구현 Niklaus Wirth는 Fortran에서 최초의 Pascal 컴파일러를 작성했다고보고했습니다.
  • X에 대한 다른 인터프리터 또는 컴파일러는 이미 다른 언어 Y로 작성되었습니다. 이것이 Scheme이 종종 부트 스트랩되는 방법입니다.
  • 이전 버전의 컴파일러는 다른 컴파일러가 존재했던 X의 서브 세트로 작성되었습니다. 이것이 Java, Haskell 및 초기 Free Pascal 컴파일러의 일부 상위 세트가 부트 스트랩되는 방식입니다.
  • X 용 컴파일러는 X 용 컴파일러가있는 다른 아키텍처에서 크로스 컴파일됩니다. 이것이 C 컴파일러가 일반적으로 다른 플랫폼으로 이식되는 방법입니다. 초기 부트 스트랩 후 Free Pascal에 사용되는 방법이기도합니다.
  • X에서 컴파일러 작성; 그런 다음 소스에서 (최적화되지 않은 방식으로) 수동 컴파일하고 코드에서 실행하여 최적화 된 컴파일러를 얻습니다. 도널드 크 누스는 그의 웹 문맹 프로그래밍 시스템에 이것을 사용했습니다 ...

또한 en.wikipedia.org/wiki/History_of_compiler_writing 링크가 있습니다 . 일반적으로 원래 컴파일러는 Assembly Language ( en.wikipedia.org/wiki/Assembly_language ) 로 작성되었다고 생각합니다 . 나중에 야 부트 스트랩 또는 자체 호스팅이라는 아이디어가 나왔습니다.
Michael Levy 2016 년

1
마지막으로 +1! 이것이 세 번째로 높은 등급의 답변 일뿐입니다. 예, 부트 스트랩 그게 답입니다
Adam Rackis

15

궁극적으로 모든 컴퓨터는 이진 코드로 작동하며 CPU에 공급됩니다. 이 이진 코드는 CPU에는 완벽하지만 인간에게는 완벽하게 쓸모가 없습니다. 프로그램을 작성하는 첫 번째 방법 중 하나는 카드에 구멍을 뚫는 것입니다. 홀의 위치는 워드 내의 특정 비트 위치를 나타내며, 홀의 유무는 0 또는 1로 해석되었다. 이 카드들은 상자에 올바른 순서로 넣은 다음 카드 판독기에 공급되어 CPU의 바이너리 코드로 효과적으로 변환했습니다.

분명히 첫 번째 프로그래머는 이진 코드를 하나씩 해결하고 카드를 펀칭하는 기계를 가지고있었습니다. 이것은 본질적으로 손과 무릎에 대한 어셈블리 언어 프로그래밍입니다. 일단 가지고 나면 간단한 텍스트 편집기, 어셈블리 언어 컴파일러 (텍스트 어셈블리 문을 이진 코드로 변환하기 위해), 링커 및 로더와 같은 다른 모든 것을 만들 수 있습니다. 그리고 나머지는 그들이 말하는 것처럼 역사입니다.


4
카드 이전에는 주소에 대한 스위치 세트, 데이터 워드 세트 및 데이터를로드하는 스위치가있었습니다. 이진 표현으로 주소 및 데이터 스위치를 설정하여 각 메모리 주소를 개별적으로 프로그래밍하고로드 스위치를 껐다 켜십시오. 나이가 들었지만 프로그램은 몇 마디 길이에 불과했습니다. 당시에는 바이트가 발명되지 않았습니다.
uɐɪ

4
... 그리고 그 전에는 다시 배선해야했습니다 . 펀 펀펀!
Michael K

그렇습니다.하지만 Von Neumann 아키텍처가 아직 발명되지 않았기 때문에 우리가 현대 컴퓨터로 생각한 것은 아닙니다.
Dave Markle

7

약간의 인터넷 검색으로 40 년대 후반부터 EDSAC 초기 주문 이 시작 됩니다. 첫 번째 어셈블러이기 때문에 아마도 기계 언어로 코딩되었을 것입니다.

나중에 IBM 650 용 SOAP I 및 II와 같은 다른 시스템 용 어셈블러가 제공되었습니다 . SOAP I은 아마도 명확한 설명을 찾지 못했지만 기계어로 코딩되었습니다.

조금 후에 IBM 704를 위해 포트란 (Formula Translator)이 나왔습니다. 아마도 704를위한 어셈블러로 작성된 것 같습니다. 701의 초기 어셈블러는 Nathan Rochester 입니다.

컴퓨터 언어로 컴퓨터를 프로그래밍하는 방법에 대한 아이디어를 얻으려면 내가 좋아하는 사이트 중 하나 인 Harry Porter의 릴레이 컴퓨터를 확인하십시오 .


거룩한 쓰레기, 해리 포터 (거의 해리 포터 롤) 집에서 만든 컴퓨터는 굉장합니다. 나는 그것이 어떻게 구축되었는지 이해했으면 좋겠다 :(.

1
@Sauron : Harry Porter는 당신에게 말하는 것보다 더 좋은 것을 원하지 않습니다. 그 페이지에서 그는 모든 것을 설명하는 아름답게 제작 된 파워 포인트를 얻었습니다. 회로에 대한 기본 지식이 있다고 가정하지만 그렇게하기는 어렵지 않습니다.
Mike Dunlavey 2016 년

나는 그것이 매우 인상적인 기계인지에 관계없이 메신저 ^ _ ^를 메 신다는 것을 알고 마법사에 많은 마법사 시간이 걸렸다는 것을 확신합니다. :).

6

직접 기계 코드를 작성할 수 있습니다 (지루한 경우). 어쩌면 프로그램을 한 장의 종이에 어셈블러에 기록한 다음 수동으로 기계 메모리에 입력하는 숫자 기계 코드 명령으로 변환 할 수 있습니다. 모든 머신 코드 명령어의 숫자 값을 기억 한 경우에는 용지 조립 단계를 건너 뛸 수도 있습니다. 당시에는 드문 일이 아니 었습니다.

최초의 컴퓨터는 물리적 스위치를 토글하여 바이너리로 직접 프로그래밍되었습니다. 프로그래머 (또는 데이터 입력 지원)가 키패드를 통해 16 진수로 코드를 입력 할 수 있도록 하드웨어가 발전했을 때 생산성이 크게 향상되었습니다!

소프트웨어 어셈블러는 더 많은 메모리를 사용할 수있게되었을 때 (어셈블러 코드가 원시 기계 코드보다 더 많은 공간을 차지하므로) 영숫자 입력을 허용하도록 하드웨어를 발전시킨 경우에만 관련이있었습니다. 따라서 첫 번째 어셈블러는 기계 코드에 능숙한 사람들이 직접 작성했습니다.

어셈블러가 있으면 어셈블러에서 고급 언어 용 컴파일러를 작성할 수 있습니다.

C 이야기에는 여러 단계가 있습니다. 첫 번째 C 컴파일러는 B (전임자)로 작성되었으며 BCPL로 작성되었습니다. BCPL은 매우 간단한 언어이지만 (예를 들어 유형이 전혀 없음) 여전히 원시 어셈블러에서 한 단계 발전했습니다. 따라서 더 복잡한 언어가 어셈블러에 이르기까지 점점 더 간단한 언어로 어떻게 구축되는지 알 수 있습니다. 그리고 C 자체는 오늘날의 표준에 따르면 매우 작고 간단한 언어입니다.

오늘날 새 언어의 첫 번째 컴파일러는 종종 C로 작성되지만 언어가 특정 성숙도에 도달하면 종종 "자체로"다시 작성됩니다. 첫 번째 Java 컴파일러는 C로 작성되었지만 나중에 Java로 다시 작성되었습니다. 첫 번째 C # 컴파일러는 C ++로 작성되었지만 최근에는 C #으로 다시 작성되었습니다. Python 컴파일러 / 인터프리터는 C로 작성되었지만 PyPy 프로젝트는 Python으로 다시 작성하려는 시도입니다.

언어 자체의 언어에 대한 컴파일러 / 인터프리터를 작성하는 것이 항상 가능한 것은 아닙니다. JavaScript로 작성된 JavaScript 인터프리터가 있지만 현재 브라우저의 컴파일러 / 인터프리터는 여전히 성능상의 이유로 C 또는 C ++로 작성됩니다. JavaScript로 작성된 JavaScript는 너무 느립니다.

그러나 C를 컴파일러의 "시작 언어"로 사용할 필요는 없습니다. 첫 번째 F # 컴파일러는 F #과 가장 밀접한 관련이있는 다른 언어 인 OCaml로 작성되었습니다. 컴파일러가 완료되면 F #으로 다시 작성되었습니다. Perl 6의 첫 번째 컴파일러는 Haskell ( Perl과 매우 다른 순수 기능 언어 )로 작성되었지만 이제는 C로 작성된 컴파일러를 갖습니다.

흥미로운 사례는 첫 번째 컴파일러가 OCaml로 작성된 Rust입니다 (이제 Rust로 다시 작성 됨). OCaml은 일반적으로 금속에 더 가까운 Rust보다 높은 수준으로 간주되기 때문에 주목할 만합니다. 따라서 항상 낮은 수준의 언어로 구현 된 고급 언어는 아니며 다른 방법 일 수도 있습니다.


3

간단한 명령어 세트 만으로 시작한다고 가정하면 파일을로드하고 대상 언어의 최소 하위 집합을 구문 분석하고 실행 파일을 생성 할 수있는 최소한의 기능을 갖춘 최소한의 어셈블러 또는 컴파일러를 만드는 것으로 시작합니다. 16 진 편집기 또는 유사한 도구를 사용하여 원시 기계 코드를 작성하여 출력으로 파일을 작성하십시오.

그런 다음 그 기능이 거의없는 컴파일러 또는 어셈블러를 사용하여 대상 언어의 더 큰 하위 집합을 인식 할 수있는 약간 더 유능한 컴파일러 또는 어셈블러를 구현합니다. 최종 제품이 나올 때까지 헹구고 반복하십시오.


2

보이는 것처럼 그렇게 어렵지 않습니다. 어린 시절;) 나는 x86 분해를 염두에 두었다.

당신은 특히 그것을 배울 필요가 없습니다. ASM에서 프로그래밍하고 대화식 디스어셈블러를 사용하여 타사 바이너리를 수정하려고 할 때 발생합니다. 또는 코드 암호화로 자체 보호 기능을 작성할 때.

즉, 때로는 언어에서 코드로 마이그레이션하는 것도 놀라운 일이 아닙니다.


1

첫 번째 컴파일러는 어셈블리 언어를 사용하여 구현되었습니다. 그리고 첫 번째 어셈블러는 프로그램을 바이너리로 코딩하여 구현되었습니다 ...


오래 전부터 바이너리 프로그래밍이 사람들이 사용한 기술인 것은 아닙니다.

학부 시절에 PDP-8 (제 생각에는) 머신 코드로 작은 프로그램을 작성하고 전면 패널 스위치를 통해 입력 한 후 실행하는 프로그래밍 연습을했던 것을 기억합니다. 몇 년 후, 나는 프로그램을 입력하기위한 16 진수 키패드가있는 6502 시스템 개발 키트와 4k 바이트의 RAM을 구입했습니다.


-3

매우 간단한 답변 유선 프로그램을 작성하여 ROM에 저장한다고 가정 해 봅시다. 컴파일러로 간주 될 수 있습니다. 그래서 나는 단순히 첫 번째 컴파일러가 고정 배선되었다고 말하고 싶습니다. 기술이 향상됨에 따라이 간단한 컴파일러를 사용하여 고급 컴파일러를 작성했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.