컴파일러 작성자는 실제로 기계 코드를 '이해'해야합니까? [닫은]


10

이상한 질문 일 수도 있습니다.

C ++ 컴파일러 (또는 비 VM 언어)를 작성하는 사람 : 원시 기계 언어를 읽거나 쓸 수 있어야합니까? 어떻게 작동합니까?

편집 : 나는 다른 프로그래밍 언어가 아닌 머신 코드로 컴파일하는 컴파일러를 구체적으로 언급하고 있습니다.



1
아니요. 알 필요도없고 목표 ISA 사양을 맹목적으로 무의식적으로
SK-logic

1
Coffescript 는 자바 스크립트로 컴파일 됩니다.
Kartik

@Kartik Javascript로 컴파일하는 CoffeeScript 컴파일러에는 Javascript가 컴파일되는 모든 것을 컴파일하는 Javascript 컴파일러가 포함되어 있습니까? 아니면 Javascript 소스 코드로만 컴파일됩니까?
Aviv Cohn

coffeescript 컴파일러는 단순히 cofeescript를 javascript로 변환합니다. Javascript는 컴파일되지 않으며 브라우저에서 처리합니다. 한 언어를 다른 언어로 컴파일하는 컴파일러를 작성할 수 있다고 말하고 싶었습니다. 기계 언어를 알 필요가 없습니다. 또 다른 예는 셰익스피어 연극을 C ++로 컴파일하는 'SPL'컴파일러입니다. shakespearelang.sourceforge.net
Kartik

답변:


15

아뇨, 전혀 아닙니다. 컴파일러가 대신 어셈블리 코드를 생성하는 것이 가능합니다. 그런 다음 어셈블러는 실제 기계 코드 작성을 처리합니다.

그건 그렇고, 비 VM 구현과 VM 구현을 구별하는 것은 유용하지 않습니다.

  • 우선 머신 코드에 VM 또는 사전 컴파일을 사용하는 것은 언어를 구현하는 다른 방법 일뿐입니다. 대부분의 경우 하나의 전략을 사용하여 언어를 구현할 수 있습니다. 실제로 C ++ 인터프리터를 한 번 사용해야했습니다 .

  • 또한 JVM과 같은 많은 VM에는 일반 아키텍처와 마찬가지로 이진 기계 코드와 일부 어셈블러가 있습니다.

Clang 컴파일러에서 사용하는 LLVM은 여기에서 특별히 언급 할 가치가 있습니다. 명령어는 바이트 코드, 텍스트 어셈블리 또는 컴파일러에서 쉽게 방출 할 수있는 데이터 구조로 표시 될 수있는 VM을 정의합니다. 따라서 디버깅에 유용하고 수행중인 작업을 이해하는 데 유용하지만 어셈블리 언어에 대해서는 알 필요가 없으며 LLVM API에 대해서만 알 수 있습니다.

LLVM의 좋은 점은 VM이 단지 추상화이며 바이트 코드가 일반적으로 해석되지 않고 대신 투명하게 JIT된다는 것입니다. 따라서 CPU의 명령어 세트에 대해 알 필요없이 효과적으로 컴파일 된 언어를 작성할 수 있습니다.


LLVM의 또 다른 장점은 효율적인 백엔드를 구현하기 위해 대상 ISA를 깊이 이해할 필요가 없다는 것입니다. 매우 선언적이므로 이해하지 않아도 ISA 사양을 .td 파일에 거의 복사하여 붙여 넣을 수 있습니다.
SK-logic

대답 해줘서 고마워. 질문 : 컴파일러 작성자가 기계 코드를 이해할 필요가 없다는 답변과 다른 사람의 답변을 이해합니다. 그는 실제 기계를 기계 코드로 변환하는 다른 도구를 사용할 수 있습니다. 그러나이 도구를 쓴 사람은 않은 , 권리를 기계 언어를 이해해야한다? 어떤 언어에서 기계 코드로 실제로 변환하는 소프트웨어를 작성한 사람은 실제로 기계 언어를 이해해야합니까?
Aviv Cohn

5
@Prog 예. 추상화 계층을 작성하는 경우 아래 계층 만 이해하면됩니다. 모든 레이어를 기본적으로 이해하는 것이 유용하지만 실제로는 필요하지 않습니다. 트랜지스터를 사용하기 위해 양자 물리학을 이해할 필요는 없습니다. CPU를 사용하기 위해 칩 설계를 이해할 필요는 없습니다. 어셈블리를 작성하기 위해 머신 코드를 몰라도됩니다. VM 등을 사용할 때 플랫폼의 명령어 세트를 알 필요는 없습니다. 그러나 누군가는 자신의 추상화 수준을 자신의 수준 이하로 만들어야했습니다.
amon

1
@ SK-logic 내가 들었던 것에서 사실이 아닙니다. llvm을 위해 Aarch64 백엔드를 구현 한 사람들에게는 몇 가지 과제가있었습니다. 그리고 이것은 방에서 가장 큰 코끼리를 무시 하고 있습니다. ISA의 메모리 모델과 관심있는 언어의 메모리 모델. 컴파일러에서 작업 할 수 있지만 아키텍처를 이해하지 않고 백엔드에서 작업 할 수는 없습니다.
Voo

1
개념적으로 어셈블리 코드와 기계 코드 사이에는 실질적인 차이가 없다고 덧붙입니다. 특정 명령어를 사용하는 방법을 알고 나면 해당 명령어의 opcode가 무엇인지 실제로는 큰 이점을 얻지 못할 것입니다. MOV 사용 방법을 알고 있다면 그것이 명령 27인지 모르는 것이 중요하지 않습니다. @ SK-logic이 설명하는 것과 비슷하다고 생각합니다.
whatsisname

9

아닙니다. 질문의 핵심은 컴파일이 매우 광범위하다는 것입니다. 컴파일은 모든 언어에서 모든 언어로 발생할 수 있습니다. 그리고 어셈블리 / 머신 코드는 컴파일 대상을위한 많은 언어 중 하나 일뿐입니다. 예를 들어 C #, F # 및 VB.NET과 같은 Java 및 .NET 언어는 모두 머신 별 코드 대신 일종의 중간 코드로 컴파일됩니다. VM에서 실행되는지 여부는 중요하지 않으며 언어는 여전히 컴파일됩니다. C와 같은 다른 언어로 컴파일하는 옵션도 있습니다. C는 실제로 매우 인기있는 컴파일 대상이며 많은 도구가이를 수행합니다. 마지막으로 일부 도구 또는 라이브러리를 사용하여 기계 코드를 생성하는 데 어려움을 겪을 수 있습니다. 예를 들어 독립 컴파일러를 만드는 데 필요한 노력을 줄일 수있는 LLVM 이 있습니다.

또한 편집 내용이 의미가 없습니다. "모든 엔지니어가 엔진의 작동 방식을 이해해야합니까? 그리고 엔진을 사용하는 엔지니어에 대해 묻고 있습니다." 기계 코드를 생성하는 프로그램이나 라이브러리에서 작업하는 경우이를 이해해야합니다. 요점은 컴파일러를 작성할 때 그런 일을 할 필요가 없다는 것입니다. 많은 사람들이 당신보다 먼저 했으므로 다시해야 할 심각한 이유가 있어야합니다.


실제 기계 언어로 변환하는 도구 또는 라이브러리를 작성하는 사람은 기계 언어를 완전히 이해해야합니까?
Aviv Cohn

3
@Prog 프로그래밍 언어를 완전히 이해해야 프로그래밍 할 수 있습니까? 아니요, 그러나 최적이 아닌 코드를 작성하면 다른 사람들이 할 수있는 특정 작업을 수행 할 수 없습니다. 이를 번역하는 컴파일러를 작성하는 경우 기계 언어를 완전히 이해해야합니다. 아니요, 그러나 컴파일러는 차선책이며 특정 작업을 수행 할 수 없습니다.
Sumurai8

@ Sumurai8 : 어느 정도는 기계 언어를 부분적으로 이해하여 모든 것을보다 잘 이해하는 기계 코드 이미 터를 작성할 수 있습니다. 예를 들어, 좋은 프레임 워크를 작성하면 비용 및 파이프 라이닝 고려 사항과 함께 각 opcode의 정의를 구성 할 수 있으며 특정 머신을 최적화하는 데 전문 지식이 없더라도 프레임 워크에서 최적화 된 머신 코드를 작성할 수 있습니다. 해당 머신 코드를 유능하게 프로그래밍 할 수 있다고해도 아프지 않을 것입니다.
Steve Jessop

@SteveJessop 각 opcode를 이해하여 기계를 다른 opcode와 함께 연결하여 더 높은 수준의 개념을 표현하는 방법을 배울 수있는 시점까지 기계 언어를 완전히 이해합니다. 그런 다음 모든 문제에 대한 최적의 솔루션을 찾기에는 너무 게으르다 ;-)
Sumurai8

@ Sumurai8 : 흠, 그러나 적어도 원칙적으로 5 분 동안 각 opcode를 간략하게 "이해"하여 구성하는 데 걸리는 시간이 있고 다음에 opcode를 "이해"할 때까지 잊어 버렸습니다. 그것은 아마도 "원어 기계 언어를 읽고 쓸 수있다"는 질문자가 의미하는 바가 아닙니다. 물론 여기서는 꽤 대담한 좋은 프레임 워크를 가정하고 있습니다. 명령 세트의 각 opcode에 대한 모든 유용한 정보를 정의하고 사용할 수있을 정도로 구성 할 수 있습니다. LLVM은 다소 이것을 목표로하지만 "Voo"에 따르면 (아래 주석에서) 적중하지 않았습니다.
Steve Jessop

3

일반적으로 컴파일러는 어휘 분석, 구문 분석 및 코드 생성의 세 부분으로 구성됩니다. 어휘 분석은 프로그램의 텍스트를 언어 키워드, 이름 및 값으로 나눕니다. 구문 분석은 어휘 분석에서 나온 토큰이 구문 적으로 올바른 언어 문장으로 결합되는 방법을 보여줍니다. 코드 생성은 파서가 생성 한 데이터 구조를 가져 와서 기계 코드 또는 다른 표현으로 변환합니다. 오늘날 어휘 분석 및 구문 분석은 단일 단계로 결합 될 수 있습니다.

분명히 코드 생성기를 작성하는 사람은 명령 세트, 프로세서 파이프 라인 및 캐시 동작을 포함하여 매우 깊은 수준에서 대상 머신 코드를 이해해야합니다. 그렇지 않으면 컴파일러가 생성 한 프로그램이 느리고 비효율적입니다. 8 진수 또는 16 진수로 표시되는 기계어 코드를 읽고 쓸 수 있을지 모르지만 일반적으로 기계어 명령어 테이블을 내부적으로 참조하여 기계어 코드를 생성하는 함수를 작성합니다. 이론적으로 어휘 분석기와 파서를 작성하는 사람들은 머신 코드 생성에 대해 아무것도 알지 못할 수도 있습니다. 실제로 일부 최신 컴파일러를 사용하면 렉서 및 파서 작성자가 들어 본 적이없는 일부 CPU의 기계 코드를 생성 할 수있는 자체 코드 생성 루틴을 연결할 수 있습니다.

그러나 실제로 각 단계의 컴파일러 작성자는 서로 다른 프로세서 아키텍처에 대해 많은 것을 알고 있으며이를 통해 코드 생성 단계에 필요한 데이터 구조를 설계 할 수 있습니다.


2

오래 전에 두 개의 다른 셸 스크립트 사이에서 변환되는 컴파일러를 작성했습니다. 기계 코드 근처에는 가지 못했습니다.

컴파일러 쓰기는 출력 을 이해해야 하지만 종종 기계 코드가 아닙니다.

대부분의 프로그래머는 것이다 결코 출력 기계 코드 또는 어셈블리 코드 만 사용자 정의 컴파일러는 다른 출력을 생산하는 많은 프로젝트에 매우 유용 할 수있는 컴파일러를 써주세요.

YACC는 머신 코드를 출력하지 않는 컴파일러 중 하나입니다.


0

입력 및 출력 언어의 의미에 대한 자세한 지식 으로 시작할 필요는 없지만 둘 다에 대한 정교하게 자세한 지식으로 마무리 하는 것이 좋습니다 . 그렇지 않으면 컴파일러가 사용할 수 없을 정도로 버그가 있습니다. 따라서 입력이 C ++이고 출력이 특정 기계 언어 인 경우 결국 두 가지의 의미를 모두 알아야합니다.

다음은 C ++을 기계 코드로 컴파일하는 데있어 미묘한 부분입니다. (머리 꼭대기에서 잊어 버릴 것이 더 있다고 확신합니다.)

  1. 어떤 크기입니까 int? 여기서 "정확한"선택은 기계의 자연적인 포인터 크기, 다양한 크기의 산술 연산에 대한 ALU의 성능 및 기계의 기존 컴파일러가 선택한 선택을 기반으로하는 기술입니다. 기계에도 64 비트 산술이 있습니까? 그렇지 않은 경우 32 비트 정수를 추가하면 명령어로 변환되고 64 비트 정수를 추가하면 64 비트 추가를 수행하는 함수 호출로 변환해야합니다. 머신에 8 비트 및 16 비트 추가 작업이 있습니까? 아니면 32 비트 ops 및 마스킹 (예 : DEC Alpha 21064)을 사용하여 시뮬레이션해야합니까?

  2. 머신의 다른 컴파일러, 라이브러리 및 언어에서 사용되는 호출 규칙은 무엇입니까? 매개 변수가 스택에서 오른쪽에서 왼쪽으로 또는 왼쪽에서 오른쪽으로 푸시됩니까? 일부 매개 변수는 레지스터에 들어가고 다른 매개 변수는 스택에 있습니까? 정수와 부동 소수점이 다른 레지스터 공간에 있습니까? 레지스터 할당 매개 변수는 varargs 호출에서 특별히 처리되어야합니까? 발신자가 저장되는 레지스터와 수신자가 저장되는 레지스터는 무엇입니까? 리프 호출 최적화를 수행 할 수 있습니까?

  3. 기계의 각 변속 명령은 무엇을합니까? 64 비트 정수를 65 ​​비트로 이동하도록 요청하면 결과는 무엇입니까? (많은 기계에서 결과는 1 비트만큼 이동하는 것과 같고 다른 기계에서는 결과는 "0"입니다.)

  4. 머신의 메모리 일관성 의미는 무엇입니까? C ++ 11에는 매우 최적화 된 메모리 의미론이있어 어떤 경우에는 일부 최적화에 제한을 두지 만 다른 경우에는 최적화를 허용합니다. 메모리 의미론이 잘 정의 되지 않은 언어 (C ++ 11 이전의 모든 C / C ++ 버전 및 다른 많은 명령형 언어)를 컴파일하는 경우 에는 메모리 의미론을 개발해야합니다. 머신 시맨틱과 가장 일치하는 메모리 시맨틱을 발명하려고합니다.

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