2011-08-16 25 views
14

我是寫入引導程序的新手。我已經在asm中編寫了一個helloworld引導程序,並且我現在試圖用C編寫一個引導程序。我已經用C編寫了一個helloworld引導程序,但是我無法編譯它。在C中寫入引導加載程序

這是我的代碼。我究竟做錯了什麼?我完全採用錯誤的方法嗎?

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" 
); 
} 

回答

3

引導程序是用ASM編寫的。

當編譯的C代碼(或C++,或其他),編譯器將「變換」您的人類可讀代碼轉換爲機器代碼。所以你不能確定結果。

當電腦開機,BIOS會從特定地址執行代碼。 該代碼需要直接執行。

這就是爲什麼你要使用程序集。 這是處理器未經修改的代碼的唯一方式,它將以書面形式運行。

如果你想在C代碼,你還是要編寫一個ASM引導程序,這將負責正確加載通過使用編譯器生成的機器代碼。

你要明白,每個編譯器會產生不同的機器代碼,這可能在執行前需要進行預處理。

BIOS不會讓您預先處理機器碼。 PC啓動只是跳轉到內存位置,這意味着位於此位置的機器代碼將被直接執行。

+1

我會打電話整個事情的引導程序,入口點,領先進入第一次調用C函數是彙編肯定的,但大部分的bootloader可以(並且經常)用C語言編寫(最好是爲這個啓動代碼編寫真正的彙編程序,而不是亂碼內聯彙編程序)。 –

+0

謝謝你的回覆。但我想知道如何從C代碼創建.bin文件,以便我可以啓動它。我看到了這個網站上的編譯指令http://dc0d32.blogspot.com/2010/06/real-mode-in-c-with-gcc-writing.html,但它給我錯誤的ld命令ie linker.ld文件未找到。請幫助我 –

+2

@Dnyanesh:你的引導程序不能鏈接到任何動態庫。甚至沒有鏈接到stdc。 – jweyrich

1

由於您使用GCC,你應該瞭解不同的「目標環境」的信息頁。你很可能想要使用-可行的標誌。此外,我不得不使用-fno-stack-protector標誌來避免編譯器的一些難看的魔法。

然後,您將收到鏈接器錯誤,說明找不到memset等。所以你應該實現自己的這些版本,並在鏈接它們

1

我在幾年前嘗試這個 - 選項可能已經改變。

你必須運行gcc-ffreestanding(不鏈接),然後使用ld與標誌-static鏈接,-nostdlib

+0

並看看相關的FreeBSD代碼,除了引導加載程序,也CSU,ELF啓動代碼提供了很好的示例如何做低級C-asm混合。 –

9

讓我承擔了很多的東西在這裏:你想在x86處理器上運行的bootloader系統,您可以在* nix框中設置gcc工具鏈。

有寫一個引導程序時要考慮的一些要點:

  1. 的510字節限制的VBR,甚至更小的MBR由於分區表(如果你的系統需要一個)
  2. 實模式 - 16位寄存器和賽格:一次性尋址
  3. 引導程序必須是必須鏈接到物理地址7C00h處漏氣二進制
  4. 沒有外部「庫」引用(廢話!)

現在如果你希望gcc輸出這樣的二進制文件,你需要用它來玩一些技巧。

  1. gcc默認分割出32位的代碼。要使gcc輸出代碼在實模式下運行,請在每個C文件的頂部添加__asm__(".code16gcc\n")
  2. gcc輸出ELF中的編譯對象。我們需要一個在7c00h靜態鏈接的bin。具有下列內容

    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. 寫你的引導程序代碼bootloader.c創建一個文件linker.ld,並建立引導程序

    $ 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. 既然你已經建有ASM引導加載程序,我想剩下的就是明顯您。

- 從我的博客採取:http://dc0d32.blogspot.in/2010/06/real-mode-in-c-with-gcc-writing.html

+0

這是一個很好的完整答案。 – 2012-07-02 17:54:17