2015-12-05 18 views
6

Sau khi nghiên cứu một chút về trình biên dịch và cách chúng hoạt động, tôi đã học được rằng quá trình này thường được chia thành 4 bước: Preprocessor, Compiler, Assembler và Linker. Cách tôi hình dung các bước này từng là chương trình riêng của nó; Một chương trình tiền xử lý, một chương trình biên dịch, một chương trình lắp ráp và một chương trình liên kết. Tuy nhiên, bạn biết rằng đôi khi quá trình tạo mã lắp ráp và tạo các tệp đối tượng là tất cả được xử lý bởi chương trình trình biên dịch và đôi khi nó không phải. Nó dường như phụ thuộc rất nhiều vào ngữ cảnh và ngôn ngữ lập trình được sử dụng. Câu hỏi của tôi là quá trình dịch thuật điển hình được chia nhỏ như thế nào để dịch mã nguồn C++ thành mã máy?Trình biên dịch C++ điển hình xử lý những công việc gì?

  1. Trình xử lý trước có phải là chương trình riêng biệt từ trình biên dịch không? Hay là quá trình đó thường là một phần của chương trình biên dịch?
  2. Trình biên dịch thường chịu trách nhiệm về điều gì? Tạo mã lắp ráp và sau đó chuyển đổi sang mã máy?
  3. Trình liên kết có phải là chương trình riêng biệt riêng được chạy sau khi trình biên dịch kết thúc không?

Lưu ý phụ: Câu hỏi của tôi khác với các trình biên dịch C++ khác vì tôi hỏi không chỉ trình biên dịch hoạt động như thế nào, nhưng nếu một số quy trình khác, chẳng hạn như liên kết, có chương trình thực thi riêng. vào một chương trình biên dịch.

+2

Bản sao có thể có của [Trình biên dịch C/C++ hoạt động như thế nào?] (Http: // stackoverflow.com/questions/1085490/how-do-c-c-compilers-work) – wimh

+1

Trình xử lý trước, front-end, back-end (trình tạo mã và trình tối ưu hóa), trình liên kết. Vẫn còn sử dụng một bộ lắp ráp là hiếm ngày hôm nay, quá chậm. Không thực sự là thẳng về phía trước nữa, trình biên dịch có thể dừng ở mặt trước và tạo ra mã trung gian. Được tiêu thụ bởi trình liên kết có thể bắt đầu back-end để thực hiện tối ưu hóa toàn bộ chương trình. –

+1

"bằng cách sử dụng một assembler là hiếm ngày hôm nay" tốt đẹp, rõ ràng không ai đang sử dụng gcc ngày hôm nay. Hoặc llvm với một mục tiêu mà nó không đi kèm với một bộ tích hợp. Hoặc nhiều mục khác ... –

Trả lời

4

Tất cả các trình biên dịch hiện đại (ít nhất là gcc và clang, nhưng tôi nghi ngờ những người khác có nhiều khác biệt) có tiền xử lý và trình biên dịch là một tệp thực thi. Điều này chủ yếu là do trình biên dịch muốn có khả năng tạo ra các thông báo lỗi tốt [trỏ đến đúng dòng và cột, và khi nó liên quan đến macro, có thể nói "Được gọi từ macro FOO (x)"] và hiểu "tệp nào chúng tôi 'lại trong' là dễ dàng hơn khi trình biên dịch có mã nguồn thực tế để xem xét, thay vì mã được xử lý trước.

Trình liên kết thường là một chương trình riêng biệt và trình biên dịch chỉ được sử dụng cho mã lắp ráp nội tuyến [thường là một phần tích hợp của trình biên dịch] - nếu không, trình biên dịch sẽ tạo mã máy trực tiếp mà không cần sử dụng trình biên dịch [ít nhất là LLVM, đó là trình biên dịch tôi biết rõ nhất]. Vì vậy, trong trình biên dịch có một tệp đối tượng được tạo thành hoàn chỉnh.

Nếu bạn có tùy chọn chính xác, trình liên kết sẽ được gọi, nhưng sẽ là tệp thực thi riêng biệt, sẽ liên kết tệp đối tượng cùng với thư viện thời gian chạy và mã khởi đầu "trước chính" (xây dựng đối tượng toàn cầu và tương tự) cũng như "chuẩn bị gọi chính"). Điều này sẽ tạo ra các tập tin thực thi.

Với các tùy chọn khác, trình biên dịch sẽ chỉ tạo một tệp đối tượng hoặc tháo gỡ mã máy được tạo ở dạng biểu tượng (tùy chọn -S).

Phần phụ trợ của trình biên dịch, chịu trách nhiệm về tạo mã, cũng thường đề cập đến tối ưu hóa và các biến đổi mã khác nhau để giúp các giai đoạn tối ưu hóa - ví dụ Clang + LLVM sẽ tạo ra các vòng "đồng nhất" nếu bạn đã sử dụng while, for hoặc goto để tạo vòng lặp.

Điều này giúp các giai đoạn nâng cao hơn không phải xác định nhiều dạng vòng lặp khác nhau và cho phép trình biên dịch tạo mã "tốt" bất kể lập trình viên đã hình thành vòng lặp như thế nào. [Tất nhiên, nếu bạn làm cho nó đủ phức tạp, trình biên dịch có lẽ sẽ không tìm ra cách vòng lặp của bạn hoạt động, và không tối ưu hóa khá tốt, nhưng để chuyển đổi đơn giản giữa các dạng cơ bản, nó sẽ làm cùng một thế hệ mã cuối cùng bất kể về nguồn trông như thế nào].

+0

Wow câu trả lời tuyệt vời. Chính xác những gì tôi đang tìm kiếm. Cảm ơn bạn! – Jason

Các vấn đề liên quan