当前位置: 技术问答>linux和unix
linux asm 启动 bios 等很多概念性的问题请教
来源: 互联网 发布时间:2015-04-05
本文导语: 我们知道pc 在启动的时候 是转到0000:7c00 H的进行启动的 dos 下调入io.sys 模块的 linux 的话 应该是运行lilo (我猜的!) 那么一开始的那段asm 代码(启动 )是在一个裸机的情况下直接运行的 它没有得到任何操作...
我们知道pc 在启动的时候
是转到0000:7c00 H的进行启动的
dos 下调入io.sys 模块的
linux 的话 应该是运行lilo (我猜的!)
那么一开始的那段asm 代码(启动 )是在一个裸机的情况下直接运行的
它没有得到任何操作系统的支持吧 !
我想请问一下 是否能在裸机的情况下 利用c编程呢? 因为代码完全用汇编编写的 好像太复杂了! 我的想法是在asm 代码 运行以后 直接调入一个由c 语言编写的程序 完成我需要做的事情。按照我的想法 这个时候os 都还没有,所以不知道是否可行? 这个c 代码似乎应该不能调用操作系统的支持 而是全部由bios 支持? 不知道说得对不对
是转到0000:7c00 H的进行启动的
dos 下调入io.sys 模块的
linux 的话 应该是运行lilo (我猜的!)
那么一开始的那段asm 代码(启动 )是在一个裸机的情况下直接运行的
它没有得到任何操作系统的支持吧 !
我想请问一下 是否能在裸机的情况下 利用c编程呢? 因为代码完全用汇编编写的 好像太复杂了! 我的想法是在asm 代码 运行以后 直接调入一个由c 语言编写的程序 完成我需要做的事情。按照我的想法 这个时候os 都还没有,所以不知道是否可行? 这个c 代码似乎应该不能调用操作系统的支持 而是全部由bios 支持? 不知道说得对不对
|
a.其实,linux现在就是你说的这样做的:(我以linux.2.5.70为例)
b.首先,x86 CPU加电,初始化自己进入16位实模式,然后跳转到0xFFFF0,BIOS地址,调用显卡Bios初始化显卡,进行自检,然后装载可引导设备的第一个扇区到0x7c00,然后跳转到那儿。这部分代码其实是archi386bootbootsect.S。新的内核已经不支持从bootsect启动,bootsect.S其实只是提示用户按任何键重启。因为现在的可引导设备的第一个扇区是lilo或grub,然后由他们装载lilo或grub引导代码进入0x90000,然后装载内核setup代码进入0x90200,然后装载内核剩余部分进入0x10000。
c.内核setup代码就是archi386bootsetup.S,它读取硬盘参数, 检查签名0xAA55.0x5A5A, 检查是否大内核(检查标志),使用不同的方法获取内存大小,初始化设置键盘硬件。检查显卡及其参数,然后调用。video.S中的video函数。
d.video 检查内核参数,vga= 让用户选择视频模式,然后返回Setup.S。
e.然后将内核从0x10000移动到0x1000这部分代码的开始就是archi386
bootcompressedhead.S。然后进入32位保护模式。然后跳转到head.S 中startup_32=0x1000。注意:以上全是汇编代码。
f.然后head.S调用archi386bootcompressedmisc.c中的decompress_kernel函数(C语言代码),然后调用libinflate.c中的gunzip函数,将内核解压缩到0x100000(32位指针)。然后显示”Uncompressing Linux...”。最后返回head.S
g.然后进入archi386kernelhead.S。(汇编语言)在这里初始化内存页表(PT),初始化(IDT)中断描述表。检查CPU类型,配置对称多处理器。接着调用start_kernel在initmain.c中这个函数永不返回。致此,开始启动内核,之后的代码都变成了C语言代码。start_kernel中才是真正的linux内核初始化,启动过程。
上面我们可以看出除了bootsector,Setup代码必须用汇编之外 (因为这些代码要严格限制代码段大小,对齐边界),其它的部分都可以使用C语言,但入口函数一定要设置入口点地址,而且编译成静态库。
b.首先,x86 CPU加电,初始化自己进入16位实模式,然后跳转到0xFFFF0,BIOS地址,调用显卡Bios初始化显卡,进行自检,然后装载可引导设备的第一个扇区到0x7c00,然后跳转到那儿。这部分代码其实是archi386bootbootsect.S。新的内核已经不支持从bootsect启动,bootsect.S其实只是提示用户按任何键重启。因为现在的可引导设备的第一个扇区是lilo或grub,然后由他们装载lilo或grub引导代码进入0x90000,然后装载内核setup代码进入0x90200,然后装载内核剩余部分进入0x10000。
c.内核setup代码就是archi386bootsetup.S,它读取硬盘参数, 检查签名0xAA55.0x5A5A, 检查是否大内核(检查标志),使用不同的方法获取内存大小,初始化设置键盘硬件。检查显卡及其参数,然后调用。video.S中的video函数。
d.video 检查内核参数,vga= 让用户选择视频模式,然后返回Setup.S。
e.然后将内核从0x10000移动到0x1000这部分代码的开始就是archi386
bootcompressedhead.S。然后进入32位保护模式。然后跳转到head.S 中startup_32=0x1000。注意:以上全是汇编代码。
f.然后head.S调用archi386bootcompressedmisc.c中的decompress_kernel函数(C语言代码),然后调用libinflate.c中的gunzip函数,将内核解压缩到0x100000(32位指针)。然后显示”Uncompressing Linux...”。最后返回head.S
g.然后进入archi386kernelhead.S。(汇编语言)在这里初始化内存页表(PT),初始化(IDT)中断描述表。检查CPU类型,配置对称多处理器。接着调用start_kernel在initmain.c中这个函数永不返回。致此,开始启动内核,之后的代码都变成了C语言代码。start_kernel中才是真正的linux内核初始化,启动过程。
上面我们可以看出除了bootsector,Setup代码必须用汇编之外 (因为这些代码要严格限制代码段大小,对齐边界),其它的部分都可以使用C语言,但入口函数一定要设置入口点地址,而且编译成静态库。