在C中写入Bootloader

我是一个新手在写bootloaders。 我已经写了一个helloworld bootloader在asm中,现在我正在用C写一个。我用C编写了一个helloworld bootloader,但是我不能编译它。

这是我的代码。 我究竟做错了什么? 我完全采取错误的做法吗?

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以及Bootloader部分&#xFF1A; http : //www.brokenthorn.com/Resources/OSDevIndex.html

有很好的教程让自己开始做自己的引导程序。 如果您需要更多信息,您也可以加入freenode的#osdev频道加入讨论。

让我在这里假设很多东西:你想在x86系统上运行你的引导程序,你在* nix框上安装了gcc toolchain。

编写引导程序时需要注意以下几点:

  1. 一个VBR的510字节限制,由于分区表的MBR更小(如果你的系统需要的话)
  2. 实模式 – 16位寄存器和seg:关闭寻址
  3. 引导程序必须是平面二进制,必须链接到物理地址7c00h运行
  4. 没有外部的“图书馆”参考(杜!)

现在如果你想要gcc输出这样一个二进制文件,你需要玩一些技巧。

  1. gcc默认分割出32位的代码。 要让gcc输出代码在真实模式下运行,请在每个C文件的顶部添加__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中编写自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构建了引导装载程序,我想其余的对你来说是显而易见的。

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

引导程序是用ASM编写的。

编译C代码(或C ++,或其他)时,编译器会将您的可读代码“转换”为机器代码。 所以你不能确定结果。

当PC启动时,BIOS将执行特定地址的代码。 该代码需要直接执行。

这就是为什么你要使用程序集。 这是处理器未经修改的代码的唯一方式,它将以书面形式运行。

如果您想用C语言编写代码,您仍然需要编写一个ASM引导加载程序,它将负责正确加载您使用的编译器生成的机器代码。

您需要了解每个编译器将生成不同的机器代码,这可能需要在执行之前进行预处理。

BIOS不会让您预先处理机器码。 PC启动只是跳转到内存位置,这意味着位于此位置的机器代码将被直接执行。

由于您使用的是GCC,因此您应该阅读关于不同“目标环境”的信息页面。 你很可能想要使用旗帜。 此外,我不得不使用-fno-stack-protector标志来避免编译器的一些难题。

然后,你会得到连接器错误,说memset等没有找到。 所以你应该实现你自己的版本并链接它们。

几年前我尝试过这种方法 – 选项可能已经改变了。

你必须运行gcc -ffreestanding (不要链接)然后用ld和标志链接-static-nostdlib