簡體   English   中英

C 中的引導加載程序無法編譯

[英]Bootloader in C won't compile

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

這是我的代碼。 我究竟做錯了什么? 為什么編譯不出來?

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

我建議您查看http://wiki.osdev.org/Rolling_Your_Own_Bootloader以及以下的引導加載程序部分: http://www.brokenthorn.com/Resources/OSDev2FCC675238FDC30D825

有很好的教程可以讓你自己開始制作你自己的引導加載程序。 如果您需要更多信息,也可以加入 freenode 中的#osdev 頻道以加入討論。

讓我在這里假設很多事情:您想在 x86 系統上運行引導加載程序,您在 *nix 機器上設置了 gcc 工具鏈。

編寫引導加載程序時需要考慮以下幾點:

  1. VBR 的 510 字節限制,由於分區表,MBR 的限制更小(如果您的系統需要一個)
  2. 實模式 - 16 位寄存器和 seg:off 尋址
  3. 引導加載程序必須是平面二進制文件,必須鏈接才能在物理地址 7c00h 處運行
  4. 沒有外部“庫”引用(呃!)

現在如果你想要 gcc 到 output 這樣的二進制文件,你需要用它玩一些技巧。

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

     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中編寫您的引導加載程序代碼並構建引導加載程序

    $ 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 構建了引導加載程序,我想 rest 對您來說是顯而易見的。

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

引導加載程序是用 ASM 編寫的。

在編譯 C 代碼(或 C++ 或其他)時,編譯器會將您的人類可讀代碼“轉換”為機器代碼。 所以你不能確定結果。

當 PC 啟動時,BIOS 將執行來自特定地址的代碼。 該代碼需要直接可執行。

這就是您將使用匯編的原因。 這是擁有未經更改的代碼的唯一方法,該代碼將由處理器按編寫的方式運行。

如果您想在 C 中編寫代碼,您仍然需要編寫 ASM 引導加載程序,該引導加載程序將負責正確加載您使用的編譯器生成的機器代碼。

您需要了解每個編譯器會生成不同的機器代碼,這可能需要在執行前進行預處理。

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

由於您使用的是 GCC,因此您應該閱讀有關不同“目標環境”的信息頁面。 您很可能想要使用-ffreestanding標志。 我還必須使用-fno-stack-protector標志來避免編譯器的一些丑陋的魔力。

然后,您將收到 linker 錯誤,說找不到memset等。 所以你應該實現你自己的版本並將它們鏈接起來。

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

您必須使用-ffreestanding gcc不要鏈接),然后使用帶有標志的ld鏈接-static-nostdlib

據我所知,您不能在 C 中編寫引導加載程序。 這是因為,C 需要您在 32 位保護模式下工作,而在引導加載程序中某些部分處於 16 位模式。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM