Câu trả lời:
=====> COMPILATION PROCESS <======
|
|----> Input is Source file(.c)
|
V
+=================+
| |
| C Preprocessor |
| |
+=================+
|
| ---> Pure C file ( comd:cc -E <file.name> )
|
V
+=================+
| |
| Lexical Analyzer|
| |
+-----------------+
| |
| Syntax Analyzer |
| |
+-----------------+
| |
| Semantic Analyze|
| |
+-----------------+
| |
| Pre Optimization|
| |
+-----------------+
| |
| Code generation |
| |
+-----------------+
| |
| Post Optimize |
| |
+=================+
|
|---> Assembly code (comd: cc -S <file.name> )
|
V
+=================+
| |
| Assembler |
| |
+=================+
|
|---> Object file (.obj) (comd: cc -c <file.name>)
|
V
+=================+
| Linker |
| and |
| loader |
+=================+
|
|---> Executable (.Exe/a.out) (com:cc <file.name> )
|
V
Executable file(a.out)
Tiền xử lý C là bước đầu tiên trong quá trình biên dịch. Nó xử lý:
#define
các câu lệnh.#include
các câu lệnh.Mục đích của thiết bị là chuyển đổi tệp nguồn C thành tệp mã Pure C.
Có sáu bước trong đơn vị:
Nó kết hợp các ký tự trong tệp nguồn để tạo thành một "TOKEN". Mã thông báo là một tập hợp các ký tự không có 'dấu cách', 'tab' và 'dòng mới'. Do đó đơn vị biên dịch này còn được gọi là "TOKENIZER". Nó cũng loại bỏ các nhận xét, tạo bảng biểu tượng và các mục nhập bảng di chuyển.
Đơn vị này kiểm tra cú pháp trong mã. Đối với ví dụ:
{
int a;
int b;
int c;
int d;
d = a + b - c * ;
}
Đoạn mã trên sẽ tạo ra lỗi phân tích cú pháp vì phương trình không cân bằng. Đơn vị này kiểm tra nội bộ điều này bằng cách tạo cây phân tích cú pháp như sau:
=
/ \
d -
/ \
+ *
/ \ / \
a b c ?
Do đó đơn vị này còn được gọi là PARSER.
Đơn vị này kiểm tra ý nghĩa trong các câu lệnh. Đối với ví dụ:
{
int i;
int *p;
p = i;
-----
-----
-----
}
Đoạn mã trên tạo ra lỗi "Gán loại không tương thích".
Đơn vị này độc lập với CPU, tức là có hai loại tối ưu hóa
Đơn vị này tối ưu hóa mã ở các dạng sau:
Đối với ví dụ:
{
int a = 10;
if ( a > 5 ) {
/*
...
*/
} else {
/*
...
*/
}
}
Ở đây, trình biên dịch biết giá trị của 'a' tại thời điểm biên dịch, do đó nó cũng biết rằng điều kiện if luôn đúng. Do đó, nó loại bỏ phần khác trong mã.
Đối với ví dụ:
{
int a, b, c;
int x, y;
/*
...
*/
x = a + b;
y = a + b + c;
/*
...
*/
}
có thể được tối ưu hóa như sau:
{
int a, b, c;
int x, y;
/*
...
*/
x = a + b;
y = x + c; // a + b is replaced by x
/*
...
*/
}
Đối với ví dụ:
{
int a;
for (i = 0; i < 1000; i++ ) {
/*
...
*/
a = 10;
/*
...
*/
}
}
Trong đoạn mã trên, nếu 'a' là cục bộ và không được sử dụng trong vòng lặp, thì nó có thể được tối ưu hóa như sau:
{
int a;
a = 10;
for (i = 0; i < 1000; i++ ) {
/*
...
*/
}
}
Ở đây, trình biên dịch tạo mã hợp ngữ để các biến được sử dụng thường xuyên hơn được lưu trữ trong thanh ghi.
Ở đây việc tối ưu hóa phụ thuộc vào CPU. Giả sử nếu có nhiều hơn một bước nhảy trong mã thì chúng được chuyển đổi thành một bước như:
-----
jmp:<addr1>
<addr1> jmp:<addr2>
-----
-----
Điều khiển chuyển đến trực tiếp.
Sau đó, giai đoạn cuối cùng là Liên kết (tạo tệp thực thi hoặc thư viện). Khi tệp thực thi được chạy, các thư viện mà nó yêu cầu sẽ được tải.
Biểu diễn ASCII:
[Source Code] ---> Compiler ---> [Object code] --*
|
[Source Code] ---> Compiler ---> [Object code] --*--> Linker --> [Executable] ---> Loader
| |
[Source Code] ---> Compiler ---> [Object code] --* |
| |
[Library file]--* V
[Running Executable in Memory]
Hy vọng điều này sẽ giúp bạn nhiều hơn một chút.
Đầu tiên, hãy xem sơ đồ này:
(img source->internet)
Bạn tạo một đoạn mã và lưu tệp (Mã nguồn), sau đó
Tiền xử lý : - Như tên cho thấy, nó không phải là một phần của quá trình biên dịch. Họ hướng dẫn trình biên dịch thực hiện xử lý trước cần thiết trước khi biên dịch thực sự. Bạn có thể gọi giai đoạn này là Thay thế Văn bản hoặc diễn giải các chỉ thị tiền xử lý đặc biệt được ký hiệu bằng #.
Biên dịch : - Biên dịch là một quá trình trong đó một chương trình được viết bằng một ngôn ngữ được dịch sang một ngôn ngữ đích khác. Nếu có một số lỗi, trình biên dịch sẽ phát hiện chúng và báo cáo.
Lắp ráp : - Mã lắp ráp được dịch thành mã máy. Bạn có thể gọi trình hợp dịch là một loại trình biên dịch đặc biệt.
Liên kết : - Nếu những đoạn mã này cần một số tệp nguồn khác được liên kết, trình liên kết hãy liên kết chúng để biến nó thành tệp thực thi.
Có rất nhiều quá trình xảy ra sau nó. Có, bạn đoán nó ngay ở đây là vai trò của trình tải:
Bộ tải : - Nó tải mã thực thi vào bộ nhớ; chương trình và ngăn xếp dữ liệu được tạo, thanh ghi được khởi tạo.
Thông tin bổ sung nhỏ: - http://www.geeksforgeeks.org/memory-layout-of-c-program/ , bạn có thể xem bố cục bộ nhớ ở đó.
Trình biên dịch: Là một chương trình dịch một chương trình ngôn ngữ cấp cao thành một chương trình ngôn ngữ máy. Một trình biên dịch thông minh hơn một trình biên dịch. Nó kiểm tra tất cả các loại giới hạn, phạm vi, lỗi ... Nhưng thời gian chạy chương trình của nó nhiều hơn và chiếm một phần lớn hơn của bộ nhớ. Nó có tốc độ chậm. Bởi vì một trình biên dịch đi qua toàn bộ chương trình và sau đó dịch toàn bộ chương trình thành mã máy. Nếu một trình biên dịch chạy trên một máy tính và tạo ra các mã máy cho cùng một máy tính thì nó được gọi là trình biên dịch tự biên dịch hoặc trình biên dịch thường trú. Mặt khác, nếu một trình biên dịch chạy trên một máy tính và tạo ra mã máy cho máy tính khác thì nó được gọi là trình biên dịch chéo.
Trình liên kết: Trong các ngôn ngữ cấp cao, một số tệp tiêu đề hoặc thư viện được tích hợp sẵn được lưu trữ. Các thư viện này được xác định trước và chúng chứa các chức năng cơ bản cần thiết để thực hiện chương trình. Các chức năng này được liên kết với các thư viện bởi một chương trình có tên là Linker. Nếu trình liên kết không tìm thấy thư viện của một hàm thì nó sẽ thông báo cho trình biên dịch và sau đó trình biên dịch tạo ra lỗi. Trình biên dịch tự động gọi trình liên kết là bước cuối cùng trong quá trình biên dịch chương trình. Không được xây dựng trong các thư viện, nó cũng liên kết các chức năng do người dùng xác định với các thư viện do người dùng xác định. Thông thường một chương trình dài hơn được chia thành các chương trình con nhỏ hơn gọi là mô-đun. Và các module này phải được kết hợp với nhau để thực thi chương trình. Quá trình kết hợp các mô-đun được thực hiện bởi trình liên kết.
Loader: Loader là một chương trình tải các mã máy của một chương trình vào bộ nhớ hệ thống. Trong Máy tính, bộ nạp là một phần của Hệ điều hành chịu trách nhiệm tải các chương trình. Đó là một trong những giai đoạn thiết yếu của quá trình bắt đầu một chương trình. Bởi vì nó đặt các chương trình vào bộ nhớ và chuẩn bị cho chúng thực thi. Tải một chương trình liên quan đến việc đọc nội dung của tệp thực thi vào bộ nhớ. Sau khi tải xong, hệ điều hành khởi động chương trình bằng cách chuyển quyền điều khiển đến mã chương trình đã tải. Tất cả các hệ điều hành hỗ trợ tải chương trình đều có bộ nạp. Trong nhiều hệ điều hành, bộ nạp thường trú trong bộ nhớ.
Wikipedia phải có câu trả lời hay, đây là suy nghĩ của tôi:
*
*
Trình liên kết và Trình tải từ LinuxJournal giải thích rõ ràng khái niệm này. Nó cũng giải thích cách cái tên cổ điển a.out ra đời. (đầu ra của trình lắp ráp)
Một bản tóm tắt nhanh,
c program --> [compiler] --> objectFile --> [linker] --> executable file (say, a.out)
chúng tôi đã có tệp thực thi, bây giờ hãy đưa tệp này cho bạn bè của bạn hoặc cho khách hàng của bạn, những người đang cần phần mềm này :)
khi họ chạy phần mềm này, hãy nói bằng cách nhập nó vào dòng lệnh ./a.out
execute in command line ./a.out --> [Loader] --> [execve] --> program is loaded in memory
Khi chương trình được tải vào bộ nhớ, quyền điều khiển được chuyển đến chương trình này bằng cách làm cho PC (bộ đếm chương trình) trỏ đến lệnh đầu tiên của a.out
Nó sẽ đọc tệp nguồn có thể thuộc loại .c hoặc .cpp, v.v. và chuyển tệp đó sang tệp .o được gọi là tệp đối tượng.
Nó kết hợp một số tệp .o có thể được tạo cho nhiều tệp nguồn thành một tệp thực thi (định dạng ELF trong GCC). Có hai loại liên kết:
Một chương trình tải tệp thực thi vào bộ nhớ chính của máy.
Để có nghiên cứu chi tiết về ba giai đoạn thực thi chương trình này trong Linux, vui lòng đọc phần này .
thay đổi trình biên dịch kiểm tra mã nguồn của bạn để tìm lỗi và thay đổi nó thành mã đối tượng. đây là mã mà hệ điều hành chạy.
Bạn thường không viết toàn bộ chương trình trong một tệp duy nhất nên trình liên kết liên kết tất cả các tệp mã đối tượng của bạn.
chương trình của bạn sẽ không được thực thi trừ khi nó nằm trong bộ nhớ chính
Trình liên kết & Trình thông dịch là Trình thông dịch loại trừ lẫn nhau nhận mã từng dòng và thực thi từng dòng.
Trình biên dịch Nó chuyển đổi mã nguồn thành mã đối tượng.
Trình liên kết Nó kết hợp nhiều tệp đối tượng thành một tệp chương trình thực thi duy nhất.
Bộ tải Nó tải tệp thực thi vào bộ nhớ chính.
Trình biên dịch là một chương trình đặc biệt xử lý các câu lệnh được viết bằng một ngôn ngữ lập trình cụ thể và biến chúng thành ngôn ngữ máy hoặc "mã" mà bộ xử lý của máy tính sử dụng
Trình biên dịch dịch các dòng mã từ ngôn ngữ lập trình sang ngôn ngữ máy.
Trình liên kết tạo ra một liên kết giữa hai chương trình.
Bộ tải nạp chương trình vào bộ nhớ trong cơ sở dữ liệu chính, chương trình, v.v.
Trình biên dịch: nó là một phần mềm hệ thống sửa lỗi của chương trình, tệp đối tượng, thông báo, v.v.
Trình liên kết: nó là một phần mềm hệ thống kết hợp Một hoặc nhiều tệp đối tượng và có thể một số mã thư viện vào một số thư viện có thể thực hiện được hoặc một danh sách lỗi
Loader: Một chương trình tải tệp thực thi vào bộ nhớ chính của máy