[英]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 工具链。
编写引导加载程序时需要考虑以下几点:
现在如果你想要 gcc 到 output 这样的二进制文件,你需要用它玩一些技巧。
__asm__(".code16gcc\n")
。 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 */ } }
在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
由于您已经使用 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.