发布于 2017-10-24 20:23:06
我欢迎更好的答案,但我的理解是,这是在程序集中手工编写的内核启动代码(它是特定于体系结构的)(请记住,此时我们只有一个裸金属CPU和对内存的原始访问;我们无法访问存储在文件系统上的复杂库,因为我们还没有文件管理器--这就像询问是谁创建了大爆炸一样)。不要将其与引导加载程序(它将引导扇区从磁盘加载到RAM)混淆。在我先前的回答中,我自己也把他们搞糊涂了。
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
' bootloader ' ' kernel '
' ' ' '
+------+ ' +-----------------------------------+ +------------------------------+ ' ' +-----------------------------+ +---------------------------------------+ '
| BIOS | --> ' | arch/x86/boot/header.S::call main | --> | arch/x86/boot/main.c::main() | ' --> ' | init/main.c::start_kernel() | --> | arch/x86/kernel/setup.c::setup_arch() | '
+------+ ' +-----------------------------------+ +------------------------------+ ' ' +-----------------------------+ +---------------------------------------+ '
' ' ' '
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +(编辑:这是Minix,我把它放错了)
+------+ +--------------------+ +------------------+ +------------------------+
| BIOS | --> | Bootloader (mbr.S) | --> | startup (head.S) | --> | kernel/main.c::kmain() |
+------+ +--------------------+ +------------------+ +------------------------+
在头的末尾,你会看到这条线
call _C_LABEL(kmain)它是内核的入口点:
kernel/main.c我相信head.S在编译时被附加到内核映像的顶部。BIOS知道如何执行这段代码,因为它刚刚开始,是ram磁盘的根文件系统。
至于为什么会有压缩和未压缩的部分,我认为这是因为内核映像中特定于体系结构的组装部分,没有一个程序员有足够的技能来进行压缩。一旦我们可以跳转到用C编写的kmain例程(但是编译成程序集),我们就可以访问一个解压缩例程,这使得内核占用空间大大减小。

http://duartes.org/gustavo/blog/post/kernel-boot-process/
使用程序集的入口点我们喜欢用C编写所有东西,但是我们不能避免一点汇编。我们将用x86汇编语言编写一个小文件,作为内核的起点。我们的程序集文件所要做的就是调用一个外部函数,我们将用C编写它,然后停止程序流。我们如何确保这个程序集代码作为内核的起点?我们将使用链接器脚本来链接对象文件来生成最终的内核可执行文件。在这个链接器脚本中,我们将显式地指定希望将二进制文件加载到地址0x100000。正如我前面所说的,这个地址是内核应该在的位置。因此,引导程序将负责触发内核的入口点。
http://arjunsreedharan.org/post/82710718100/kernel-101-lets-write-a-kernel
https://unix.stackexchange.com/questions/139297
复制相似问题