2010-04-03 45 views
6

Tôi đang cố gắng hiểu đầy đủ quy trình viết mã chuyên nghiệp bằng một số ngôn ngữ để thực thi bằng hệ điều hành. Trong trường hợp của tôi, ngôn ngữ sẽ là C và hệ điều hành sẽ là Windows. Cho đến nay, tôi đã đọc nhiều bài viết khác nhau, nhưng tôi không chắc chắn, liệu tôi có hiểu đúng quy trình hay không và tôi muốn hỏi bạn liệu bạn có biết một số bài viết hay về một số chủ đề mà tôi không thể tìm thấy hay không.Một số câu hỏi C chung

Vì vậy, những gì tôi nghĩ rằng tôi biết về C (và các ngôn ngữ cơ bản khác):

C biên dịch này chỉ kiểm soát các kiểu dữ liệu, hoạt động toán học cơ bản, hoạt động con trỏ, và làm việc với chức năng. Bằng cách làm việc với các hàm tôi ngụ ý cách chuyển đối số cho nó, và làm thế nào để lấy kết quả từ hàm. Trong quá trình biên dịch, cuộc gọi chức năng được thay thế bằng cách chuyển đối số sang ngăn xếp và hơn nếu hàm không ở trong nội tuyến, cuộc gọi của nó được thay thế bằng một số ký hiệu cho trình liên kết. Linker hơn tìm định nghĩa hàm, và thay thế ký hiệu để nhảy địa chỉ đến hàm đó (và dĩ nhiên là nhảy trở lại chương trình).

Nếu thông tin trên nói chung là đúng và tôi hiểu đúng, nơi để tệp .exe cuối cùng thực sự liên kết lưu các chức năng? Sau hàm main()? Và điều gì tạo ra tiêu đề .exe? Trình biên dịch hoặc Trình liên kết? Bây giờ, các khả năng bổ sung của C, ngày nay được gọi là thư viện standart C là tập hợp các hàm và các khai báo của chúng, mà các lập trình viên khác đã viết để mở rộng và đơn giản hóa việc sử dụng ngôn ngữ C. Nhưng những chức năng này như printf() là (hoặc có thể?) Được viết bằng ngôn ngữ khác, hoặc người lắp ráp. Và có câu hỏi tiếp theo của tôi, có thể được, ví dụ như printf() chức năng được viết bằng tinh khiết C mà không cần sử dụng assembler?

Tôi biết đây là câu hỏi khá lớn, nhưng tôi hầu như chỉ muốn biết, tôi có đúng hay không. Và tin tôi đi, tôi đã đọc rất nhiều bài báo trên web, và tôi sẽ không hỏi bạn, Nếu tôi có thể tìm thấy những thông tin này cùng nhau ở một nơi, trong một bài báo. Insted tôi phải mảnh bằng cách thu thập thông tin, vì vậy tôi không chắc chắn nếu tôi là đúng. Cảm ơn.

+1

Tôi khuyên bạn nên học chương trình trước. Bất kỳ cuốn sách lập trình tốt nào cũng sẽ cho bạn biết quy trình chung về liên kết và biên dịch. –

Trả lời

6

Tôi nghĩ rằng bạn đang tiếp xúc với một số thông tin ít liên quan hơn với tư cách là lập trình viên khởi đầu C và có thể khiến bạn khó hiểu - một phần của mục tiêu sử dụng ngôn ngữ cấp cao hơn như thế này là không phải suy nghĩ ban đầu quá trình này hoạt động như thế nào. Tuy nhiên, theo thời gian, điều quan trọng là phải hiểu quy trình. Tôi nghĩ bạn thường có sự hiểu biết đúng đắn về nó.

Trình biên dịch C chỉ đơn thuần lấy mã C và tạo tệp đối tượng chứa ngôn ngữ máy. Hầu hết các tập tin đối tượng được lấy bởi nội dung của các hàm. Một cuộc gọi hàm đơn giản trong C, ví dụ, sẽ được biểu diễn dưới dạng được biên dịch như toán tử cấp thấp để đẩy mọi thứ vào ngăn xếp, thay đổi con trỏ chỉ dẫn, v.v.

Thư viện C và bất kỳ thư viện nào khác bạn sẽ sử dụng đã có sẵn trong biểu mẫu đã biên dịch này.

Trình liên kết là thứ kết hợp tất cả các tệp đối tượng có liên quan, giải quyết tất cả các phụ thuộc (ví dụ: một tệp đối tượng gọi hàm trong thư viện chuẩn) và sau đó tạo tệp thi hành.

Đối với thư viện ngôn ngữ được viết bằng: Hãy suy nghĩ về mọi chức năng dưới dạng hộp đen. Miễn là hộp đen có giao diện chuẩn (quy ước gọi C, nghĩa là, nó lấy đối số theo một cách nào đó, trả về giá trị theo một cách nhất định, v.v.), cách nó được viết bên trong không quan trọng. Thông thường, các hàm sẽ được viết bằng C hoặc trực tiếp trong assembly. Bởi thời gian họ làm cho nó thành một tập tin đối tượng (hoặc như một thư viện biên dịch), nó không thực sự quan trọng như thế nào họ đã được tạo ra ban đầu, những gì quan trọng là họ đang ở dạng máy biên dịch.

Định dạng của tệp thi hành phụ thuộc vào hệ điều hành, nhưng phần lớn nội dung của tệp thực thi trong cửa sổ rất giống với tệp của đối tượng. Hãy tưởng tượng như thể một người nào đó sáp nhập với nhau tất cả các tập tin đối tượng và sau đó thêm một số keo. Các keo không tải các công cụ liên quan và sau đó gọi chính(). Ví dụ, khi tôi còn là một đứa trẻ, người ta đã đá ra khỏi "thay đổi keo" để thêm một hàm khác trước hàm main() sẽ hiển thị một màn hình giật gân với tên của chúng.

Một điều cần lưu ý, mặc dù là bất kể ngôn ngữ bạn sử dụng, cuối cùng bạn phải tận dụng các dịch vụ của hệ điều hành. Ví dụ: để hiển thị nội dung trên màn hình, quản lý quy trình, v.v. Hầu hết các hệ điều hành đều có API cũng có thể gọi theo cách tương tự nhưng nội dung của nó không được bao gồm trong EXE của bạn. Ví dụ, khi bạn chạy trình duyệt của bạn, nó là một thực thi, nhưng tại một số điểm có một cuộc gọi đến Windows API để tạo ra một cửa sổ hoặc để tải một phông chữ. Nếu đây là một phần của EXE của bạn, EXE của bạn sẽ rất lớn. Vì vậy, ngay cả trong thực thi của bạn, có "thiếu tài liệu tham khảo". Thông thường, chúng được giải quyết tại thời gian tải hoặc thời gian chạy, tùy thuộc vào hệ điều hành.

+0

Cảm ơn rất nhiều. Vì vậy, để chắc chắn, khi tôi gọi hàm hoạt động chính, thì trình liên kết thêm nhảy vào hàm đó và nối hàm đó vào cuối tệp exe, hoặc là các hàm nằm trên các phần khác nhau của tệp exe và hơn trình tải thực sự kết nối chúng với nhau? –

+0

Trở thành người lắp ráp 8051, tôi chỉ thêm các thói quen vào cuối chương trình, và bằng cách nhảy vào và bắt đầu nhập lại cho họ và quay trở lại. Nhưng để sử dụng trình biên dịch nhảy cần phải biết địa chỉ của lệnh đầu tiên trong thường trình. Nhưng khi các cửa sổ tải progam vào RAM, trình biên dịch không thể biết được địa chỉ của lệnh đầu tiên của thường trình đã cho. –

+0

Tôi không chắc chắn cách thức này hiện hoạt động trong Windows nhưng trình tải thường làm rất nhiều và có thể di chuyển mọi thứ. Ví dụ, trong những ngày cũ của MS DOS, có sử dụng được một giới hạn về kích thước của thực thi, vì vậy nếu bạn có rất nhiều mã phụ, thủ thuật đặc biệt là cần thiết để tải và loại bỏ mã trong thời gian chạy. – Uri

0

Trình biên dịch chịu trách nhiệm dịch tất cả các hàm của bạn được viết bằng C thành assembly, mà nó lưu trong tệp đối tượng (ví dụ: DLL hoặc EXE). Vì vậy, nếu bạn viết một file .c có chức năng chính và một vài chức năng khác, trình biên dịch sẽ dịch tất cả những thứ đó thành assembly và lưu chúng lại với nhau trong file EXE. Sau đó, khi bạn chạy tệp, trình tải (là một phần của hệ điều hành) biết để bắt đầu chạy hàm chính trước tiên. Nếu không, hàm main cũng giống như bất kỳ hàm nào khác cho trình biên dịch.

Trình liên kết chịu trách nhiệm giải quyết mọi tham chiếu giữa các hàm và biến trong một tệp đối tượng có tham chiếu trong các tệp khác. Ví dụ, nếu bạn gọi printf(), vì bạn không tự định nghĩa hàm printf(), trình liên kết chịu trách nhiệm đảm bảo rằng lệnh gọi printf() chuyển tới thư viện hệ thống đúng nơi printf() được định nghĩa. Điều này được thực hiện tại thời gian biên dịch.

printf() thực sự được viết bằng C. Thật là gọi một cuộc gọi hệ thống trong hệ điều hành biết cách gửi các ký tự đến đầu ra chuẩn (như cửa sổ). Khi bạn gọi printf() trong chương trình của bạn, tại thời gian biên dịch, trình liên kết có trách nhiệm liên kết cuộc gọi của bạn với hàm printf() trong các thư viện C chuẩn. Khi hàm được truyền vào thời gian chạy, printf() định dạng các đối số đúng cách và sau đó gọi các cuộc gọi hệ thống hệ điều hành thích hợp để thực sự hiển thị các ký tự.

1

Tôi là người dùng mới và hệ thống này không cho phép tôi đăng nhiều liên kết. Để vượt qua giới hạn đó, tôi đã đăng một số ý tưởng tại blog của tôi http://zhinkaas.blogspot.com/2010/04/how-does-c-program-work.html. Nó đã cho tôi một thời gian để có được tất cả các liên kết, nhưng trong tổng thể, những người sẽ giúp bạn bắt đầu.