2011-04-21 30 views
8

Gần đây tôi đã bắt đầu khám phá cách thư viện thời gian chạy C++ được sử dụng bởi mã được tạo ra.Biên dịch C++ dưới Linux mà không có thư viện thời gian chạy

Chủ yếu là tôi rất tò mò, nhưng tôi cũng muốn đánh giá số lượng công việc cần thiết để phát triển các công cụ cần thiết tối thiểu để khởi động hạt nhân trong C++.

Vì vậy, tôi bắt đầu triển khai thư viện thời gian chạy của riêng mình, nhưng tôi có một vấn đề nhỏ.

int main(int argc, char **argv) 
{ 
    return 0; 
} 

Biên dịch này với lệnh sau đây:

$ g ++ -ffreestanding -nostdlib -fno-BUILTIN -fno-rtti -fno-ngoại lệ -c main.cpp

Tôi nhận được cảnh báo này:

/usr/bin/ld: warning: không thể tìm thấy ký hiệu nhập _start; mặc định là 00000000080480b8

Sau đó, khi tôi cố thực thi nhị phân, tôi nhận được lỗi "Phân đoạn". Tôi đã cố gắng biên dịch "main.cpp" và tệp ASM.

[global _start] 
[extern main] 

_start: 
    call main 

Liên kết tệp đối tượng theo cách thủ công với "ld", tôi không có cảnh báo nhưng nhị phân vẫn đang tăng "Lỗi phân đoạn".

Tôi cho rằng tôi đang thiếu thứ gì đó. Có lẽ một cái gì đó đã được thực hiện trước và sau khi cuộc gọi đến "chính" như thư viện hệ thống C hiện trong "__libc_start_main" ví dụ.

Ngoài ra, nếu ai đó có bất kỳ đề xuất nào về trang web, tài liệu hoặc sách về chủ đề này mà tôi nên đọc, tôi thực sự sẽ đánh giá cao nó.

Cảm ơn,

Patrick

+5

[Cách xây dựng tệp thực thi Unix thiếu niên nhất] (http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html) – QuantumMechanic

+0

FYI, '_start' nằm trong CRT. –

Trả lời

5

Được rồi vì vậy nhờ liên kết QuantumMechanic của tôi quản lý để tìm ra vấn đề: http://www.muppetlabs.com/~breadbox/software/tiny/teensy.html

Tôi chỉ quên vấn đề cơ bản của tôi trong lập trình linux, quan trọng hơn là cách cuối chương trình được xử lý.

Về cơ bản, tôi cần tạo ra "thoát" syscall ngắt để xử lý kết thúc chương trình.

[BITS 32] 

[global _start] 
[extern main] 

_start: 
    call main 
    mov ebx, eax ; Move the returned value in the register used as argument of exit() 
    mov eax, 1 ; Indicates the id of the syscall to execute 
    int 0x80  ; Triggers the syscall interrupt 

Vì vậy, bây giờ tôi có thể biên dịch chương trình C++ trên Linux bằng RTL của riêng tôi để thực hiện một số kiểm tra.

Lưu ý rằng sẽ không cần thiết trong hạt nhân nếu không kết thúc chức năng "chính".

Cảm ơn!

1

Nếu bạn sẵn sàng để sử dụng một phần nhỏ (200K) của gcc của cài đặt, bạn có thể liên kết trong libgcc_s. Điều này sẽ cung cấp cho bạn tất cả mã bạn cần để chương trình của bạn thực hiện init tĩnh và gọi main.

1

Khi bạn xây dựng hạt nhân, bạn sẽ phải xem xét cách khởi động hạt nhân. Thông thường đó là trách nhiệm của bộ nạp khởi động và chúng không nằm trong tiêu chuẩn. Nó chắc chắn không giống như các ứng dụng Linux. Do đó, thực sự không phải lo lắng quá nhiều về _start khi bạn sẽ bỏ qua cách bắt đầu đó.

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