2011-08-16 31 views
14

Tôi là người mới viết bộ nạp khởi động. Tôi đã viết một bộ tải khởi động helloworld trong asm, và Tôi hiện đang cố gắng viết một trong C. Tôi đã viết một bộ nạp khởi động helloworld trong C, nhưng tôi không thể biên dịch nó.Viết bộ nạp khởi động vào C

Đây là mã của tôi. Tôi đang làm gì sai? Tôi có sử dụng sai cách tiếp cận hoàn toàn không?

void print_char(); 
int main(void){ 
char *MSG = "Hello World!"; 
int i; 

__asm__(
    "mov %0, %%SI;" 
    : 
    :"g"(MSG) 
); 
for(i=0;i<12;i++){ 
    __asm__(
     "mov %0, %%AL;" 
     : 
     :"g"(MSG[i]) 
    ); 
    print_char(); 
} 

return 0; 
} 

void print_char(){ 
__asm__(
    "mov $0X0E, %AH;" 
    "mov $0x00, %BH;" 
    "mov $0x04, %BL;" 
    "int $0x10" 
); 
} 

Trả lời

13

tôi sẽ đề nghị bạn để có một cái nhìn tại http://wiki.osdev.org/Rolling_Your_Own_Bootloader và cũng là phần Bootloader của: http://www.brokenthorn.com/Resources/OSDevIndex.html

Có hướng dẫn tuyệt vời để có được cho mình bắt đầu để làm cho mình bootloader của riêng bạn. Ngoài ra, bạn có thể tham gia kênh #osdev trong freenode để tham gia thảo luận nếu bạn cần thêm thông tin.

+0

hướng dẫn tuyệt vời.Cảm ơn bạn –

3

Trình tải khởi động được viết bằng ASM.

Khi biên dịch mã C (hoặc C++ hoặc bất kỳ thứ gì), trình biên dịch sẽ 'biến đổi' mã người có thể đọc được của bạn thành mã máy. Vì vậy, bạn không thể chắc chắn về kết quả.

Khi PC khởi động, BIOS sẽ thực thi mã từ một địa chỉ cụ thể. Mã đó cần phải được thực thi, trực tiếp.

Đó là lý do tại sao bạn sẽ sử dụng lắp ráp. Đó là cách duy nhất để có mã không bị thay đổi, sẽ được chạy dưới dạng văn bản, bởi bộ vi xử lý.

Nếu bạn muốn mã trong C, bạn sẽ vẫn phải mã bộ nạp khởi động ASM, sẽ chịu trách nhiệm tải đúng mã máy do trình biên dịch bạn sử dụng.

Bạn cần phải hiểu rằng mỗi trình biên dịch sẽ tạo ra các mã máy khác nhau, có thể cần được xử lý trước khi thực thi.

BIOS sẽ không cho phép bạn xử lý trước mã máy của mình. Khởi động PC chỉ là một bước nhảy đến một vị trí bộ nhớ, có nghĩa là mã máy được đặt tại vị trí này sẽ được thực hiện trực tiếp.

+1

tôi sẽ gọi toàn bộ điều bootloader, điểm mấu chốt, dẫn vào cuộc gọi đầu tiên để một hàm C là lắp ráp có, nhưng phần lớn các bootloader có thể được (và thường là) bằng văn bản trong C. (tốt hơn để viết lắp ráp thực sự cho mã khởi động này hơn là rối tung xung quanh với lắp ráp nội tuyến). –

+0

Cảm ơn bạn đã trả lời. nhưng tôi muốn ot biết làm thế nào tôi có thể tạo tập tin .bin từ mã c để tôi có thể khởi động nó. tôi thấy các hướng dẫn biên dịch trên trang web này http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html nhưng nó mang lại cho tôi lỗi trên lệnh ld file linker.ld không tìm thấy. Xin vui lòng giúp tôi –

+2

@ Dnyanesh: bộ nạp khởi động của bạn PHẢI KHÔNG được liên kết với bất kỳ thư viện động nào. Thậm chí không liên quan đến stdc. – jweyrich

1

Vì bạn đang sử dụng GCC, bạn nên đọc các trang thông tin về "môi trường đích" khác nhau. Bạn có thể muốn sử dụng cờ -ffreestanding. Ngoài ra tôi đã phải sử dụng các cờ -fno-stack-protector để tránh một số phép thuật xấu xí của trình biên dịch.

Sau đó, bạn sẽ nhận được lỗi trình liên kết nói rằng memset và các nội dung tương tự không được tìm thấy. Vì vậy, bạn nên triển khai phiên bản của riêng mình và liên kết chúng.

1

Tôi đã thử cách đây vài năm - các tùy chọn có thể đã thay đổi.

Bạn phải chạy gcc với -ffreestanding (không liên kết) và sau đó liên kết sử dụng ld với những lá cờ -static, -nostdlib

+0

Và hãy xem mã FreeBSD có liên quan, ngoại trừ từ bộ nạp khởi động, cũng là CSU, mã khởi động ELF cung cấp các ví dụ hay về cách làm hỗn hợp C-asm lowlevel. –

9

Hãy để tôi giả định rất nhiều thứ ở đây: bạn muốn chạy bootloader của bạn trên một x86 hệ thống, bạn có gcc toolchain được thiết lập trên một hộp * nix.

Có một số điểm cần được xem xét khi viết một bootloader:

  1. giới hạn 510 byte cho một VBR, thậm chí ít hơn cho MBR do bảng phân vùng (nếu hệ thống của bạn cần một)
  2. chế độ thực - 16 thanh ghi bit và seg: off giải quyết
  3. bootloader phải nhị phân bằng phẳng mà phải gắn với chạy ở 7c00h địa chỉ vật lý
  4. không bên ngoài 'thư viện' tài liệu tham khảo (duh!)
012.

ngay bây giờ nếu bạn muốn gcc xuất tệp nhị phân như vậy, bạn cần phải chơi một số thủ thuật với nó.

  1. gcc theo mặc định chia nhỏ mã 32 bit. Để có mã đầu ra gcc sẽ chạy ở chế độ thực, hãy thêm __asm__(".code16gcc\n") ở đầu mỗi tệp C.
  2. kết quả đầu ra gcc được biên dịch đối tượng trong ELF. Chúng ta cần một thùng được liên kết tĩnh ở 7c00h. Tạo một file linker.ld với nội dung sau

    ENTRY(main); 
    SECTIONS 
    {  
        . = 0x7C00;  
        .text : AT(0x7C00) 
        { 
         _text = .; 
         *(.text); 
         _text_end = .; 
        } 
        .data : 
        { 
         _data = .; 
         *(.bss); 
         *(.bss*); 
         *(.data); 
         *(.rodata*); 
         *(COMMON) 
         _data_end = .; 
        }  
        .sig : AT(0x7DFE)  
        {   
         SHORT(0xaa55); 
        }  
        /DISCARD/ : 
        { 
         *(.note*); 
         *(.iplt*); 
         *(.igot*); 
         *(.rel*); 
         *(.comment); 
         /* add any unwanted sections spewed out by your version of gcc and flags here */  
        } 
    } 
    
  3. viết mã bootloader của bạn trong bootloader.c và xây dựng bootloader

    $ gcc -c -g -Os -march=i686 -ffreestanding -Wall -Werror -I. -o bootloader.o bootloader.c 
    $ ld -static -Tlinker.ld -nostdlib --nmagic -o bootloader.elf bootloader.o 
    $ objcopy -O binary bootloader.elf bootloader.bin 
    
  4. Vì bạn đã đã xây dựng bộ tải khởi động với ASM, tôi đoán phần còn lại là hiển nhiên đối với bạn.

- lấy từ blog của tôi: http://dc0d32.blogspot.in/2010/06/real-mode-in-c-with-gcc-writing.html

+0

Đây là câu trả lời hoàn chỉnh. –

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