在C中写入Bootloader

Dny*_*ate 21 c linux assembly gcc bootloader

我是编写引导加载程序的新手.我在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"
);
}
Run Code Online (Sandbox Code Playgroud)

pho*_*xis 19

我建议你看看http://wiki.osdev.org/Rolling_Your_Own_Bootloader以及http://www.brokenthorn.com/Resources/OSDevIndex.html的Bootloader部分.

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


小智 13

让我在这里假设很多东西:你想在x86系统上运行你的bootloader,你在*nix框上设置了gcc工具链.

编写引导加载程序时需要考虑以下几点:

  1. VBR的510字节限制,由于分区表(如果您的系统需要一个),MBR甚至更小
  2. 实模式 - 16位寄存器和seg:关闭寻址
  3. bootloader必须是平面二进制文件,必须链接到物理地址7c00h运行
  4. 没有外部'图书馆'参考(呃!)

现在如果你想让gcc输出这样的二进制文件,你需要用它来玩一些技巧.

  1. gcc默认情况下会拆分32位代码.要获得将以实模式运行的gcc输出代码,请在__asm__(".code16gcc\n")每个C文件的顶部添加.
  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 */    
        }
    }
    
    Run Code Online (Sandbox Code Playgroud)
  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
    
    Run Code Online (Sandbox Code Playgroud)
  4. 由于您已经使用ASM构建了引导加载程序,我想其余部分对您来说很明显.

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


Mac*_*ade 6

Bootloader用ASM编写。

编译C代码(或C ++或其他)时,编译器会将您的可读代码“转换”为机器代码。因此,您无法确定结果。

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

这就是为什么要使用汇编的原因。这是拥有未更改的代码的唯一方法,该代码将由处理器按编写的方式运行。

如果要使用C语言编写代码,则仍然必须编写ASM引导加载程序的代码,该加载程序将负责正确加载由您使用的编译器生成的机器代码。

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

BIOS不允许您预处理机器代码。PC引导只是跳转到存储位置,这意味着将直接执行位于此位置的机器代码。

  • 这个答案被大大简化,以至于无用与错误之间。 (3认同)
  • @Dnyanesh:您的引导程序不得链接到任何动态库。甚至没有链接到stdc。 (2认同)