2008-08-15 43 views

Trả lời

25

Các tập tin .exe (hoặc tương đương trên các nền tảng khác) có chứa một 'điểm nhập cảnh ' địa chỉ nhà. Để một xấp xỉ đầu tiên, hệ điều hành tải các phần có liên quan của tập tin .EXE vào ram, và sau đó nhảy đến điểm vào.

Như những người khác đã nói, điểm vào này sẽ không là 'chính', nhưng thay vào đó sẽ là một phần của thư viện thời gian chạy - nó sẽ làm những việc như khởi tạo đối tượng tĩnh, thiết lập tham số argc/argv, thiết lập stdin/stdout/stderr, vv Khi nó được thực hiện tất cả, nó sẽ gọi hàm main() của bạn. Khi thoát ra chính, thời gian chạy đi qua một quá trình analagous truyền mã trả về của bạn trở lại môi trường, gọi là destructor tĩnh, gọi các thường trình _atexit, v.v.

Nếu bạn có công cụ MS (có thể không phải là freebie), thì bạn có tất cả các nguồn thời gian chạy, và một cách dễ dàng để xem xét nó là đặt một điểm ngắt trên dấu ngoặc đóng của phương thức main() của bạn và một bước duy nhất sao lưu vào thời gian chạy.

8

main() là một phần của thư viện C và không phải là chức năng của hệ thống. Tôi không biết cho OS X hoặc Linux, nhưng Windows thường bắt đầu một chương trình với WinMainCRTStartup(). Biểu tượng này bắt đầu quá trình của bạn, trích xuất đối số dòng lệnh và môi trường (argc, argv, end) và gọi main(). Nó cũng chịu trách nhiệm gọi bất kỳ mã nào sẽ chạy sau main(), như atexit().

Bằng cách tìm trong tệp Visual Studio của bạn, bạn sẽ có thể tìm thấy triển khai mặc định là WinMainCRTStartup để xem nó hoạt động như thế nào.

Bạn cũng có thể xác định một chức năng của riêng bạn để gọi khi khởi động, điều này được thực hiện bằng cách thay đổi "điểm vào" trong tùy chọn trình liên kết. Đây thường là một hàm không có đối số và trả về một khoảng trống.

1

Expert C++/CLI (kiểm tra trang 279) có chi tiết rất cụ thể về các kịch bản khởi động khác nhau cho các cụm CLR gốc, hỗn hợp và thuần túy.

1

Tùy thuộc vào hệ điều hành. Trong OS X, có một khung trong tiêu đề mach chứa địa chỉ xuất phát cho thanh ghi EIP (chỉ dẫn).

Khi nhị phân được nạp, hệ điều hành khởi động thực hiện từ địa chỉ này:

 
cristi:test diciu$ otool -l ./a.out | grep -A 10 LC_UNIXTHREAD 
     cmd LC_UNIXTHREAD 
    cmdsize 80 
    flavor i386_THREAD_STATE 
     count i386_THREAD_STATE_COUNT 
[..] 
     ss 0x00000000 eflags 0x00000000 eip 0x00001f8c cs 0x00000000 
[..] 

Địa chỉ là địa chỉ của các "bắt đầu" chức năng từ nhị phân:

 
cristi:test diciu$ nm ./a.out 
0000200c D _NXArgc 
00002008 D _NXArgv 
00002000 D ___progname 
00001fe0 t __dyld_func_lookup 
00001000 A __mh_execute_header 
[..] 
00001f8c T start 

Trong Mac OS X, đó là chức năng "bắt đầu" được gọi là đầu tiên, ngay cả trước chức năng "chính":

 
(gdb) b start 
Breakpoint 1 at 0x1f90 
(gdb) b main 
Breakpoint 2 at 0x1ff4 
(gdb) r 
Starting program: /Users/diciu/Programming/test/a.out 
Reading symbols for shared libraries ++. done 

Breakpoint 1, 0x00001f90 in start() 
5

Theo như w indows đi, các chức năng nhập điểm là:

  • Console: void __cdecl mainCRTStartup(void) {}
  • GUI: void __stdcall WinMainCRTStartup(void) {}
  • DLL: BOOL __stdcall _DllMainCRTStartup(HINSTANCE hinstDLL,DWORD fdwReason,void* lpReserved) {}

Lý do duy nhất để sử dụng các so với bình thường chính/WinMain/DllMain là nếu bạn muốn sử dụng thư viện thời gian chạy của riêng mình (Nếu bạn muốn kích thước tệp hoặc các tính năng tùy chỉnh nhỏ hơn)

Để triển khai tùy chỉnh thời gian chạy ion và thủ thuật khác để có được file PE nhỏ, xem:

0

Nếu Bạn đang quan tâm đến một cuốn sách liên quan đến Windows và Win32 API hãy thử

"Ứng dụng lập trình cho Mi "Windows của" Jeffrey Richter.

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