《linux内核完全注释0.11》 读书笔记 0

来源:互联网 发布:河南gov域名注册 编辑:程序博客网 时间:2024/04/29 08:19

Read the Fucking Souce Code微笑

第三章 引导启动程序(BOOT)

        打开电源---80x86结构cpu自动进入实模式从0xFFFF0【ROM-BIOS中地址】地址执行程序代码----BIOS进行系统检测在物理地址0处初始化中断向量-----将可启动设备的第一扇区(磁盘引导扇区512B)读入到内存的绝对地址0x7c00处,并跳转到这里
bootsec.s 将由BIOS读入到内存绝对地址0x7c00(31KB)处,当它被执行时会把自己移动到绝对地址为0x90000(567KB)处,并把启动设备中后2KB代码(setup.s)读到内存0x90200处,而内核的其他模块(system)则被读到从地址0x10000处【因此system模块不会超过0x80000字节即512KB,不会覆盖setup.s和bootset.s】;后面的setup程序将system模块移动到内存初始处,这样system模块的地址等于实际的物理地址,然后将控制权交给了setup模块,启动模块主要对主机的某些特性以及VGA卡的类型,然后将系统从0x10000移到0x0000处,进入保护模式并跳转到0x0000.便于操作。移动过程如图所示:
    疑问疑问:为什么不直接把系统模块直接加载到0x0000处而要在setup里面移动呢?这是因为setup模块需要ROMBIOS的中断获取机器的一些参数。当bios初始化时会在物理内存的开始处设置一个大小为0x400字节的中断向量表,因此需要在调用完成后将其覆盖掉。

bootsect.s程序 

        功能描述:
是磁盘引导块程序,驻留在磁盘第一个扇区(引导扇区,0磁道,0磁头,1扇区)。pc加电后,BIOS把它加载0x7c00处,然后将自己移动到0x90000处。主要作用是首先将setup模块从磁盘加载到内存,紧接着bootsect的后面位置(0x90200),然后使用BIOS中断0x13取磁盘列表中当前引导盘的参数,接着在屏幕上显示“Loading System”,再将System模块从磁盘加载到0x10000开始的地址处,随后确定根文件系统的设备号,若没指定,据磁道扇区判别出盘的种类和类型并保存设备号与root_dev(引导块的0x508),最后长跳到setup程序的开始处(0x90200)执行setup程序。
阅读到的相关信息:
|------------SYSSIZE = 0x3000 =196KB 编译连接后system模块的大小,最大默认值。
|------------REP prefixesapply only to one string instruction at a time
|------------jmpi go,INITSEG 跳转到INITSEG段,偏移go处==  CS的值设为#BOOTSEG,IP的值设为go ++jmpi是段间间接跳转
|------------寄存器 ---
|-------------------------通用寄存器AX,BX,CX,DX(16b)
|-------------------------变址寄存器 SI(源)DI(目的) 串操作指令{DS与SI 寻址数据段的源操作数 ES与DI 寻址附加段中的目的操作数}
|-------------------------指针寄存器 BP与SP指向堆栈段的数据单元 SS指示堆栈段的开始位置 SP指向相对堆顶的开始位置的偏移位置}
|-------------------------指令寄存器 CS指示代码段的开始位置 IP指示当前指令在代码段的偏移位置
|-------------------------GS 附加段寄存器
|------------JNC 当CF=0 到指定标号执行
源码阅读相关问题:
|------------bootsect的堆栈设置SS指向了0x9000,SP指向0xFF00{SP大于0x200(bootsect大小) +0x200*4(setup大小)+堆栈大小} 
|------------load_setup其中的读扇区到制定缓冲区   入口参数 AH=02H AL=扇区数 CH=柱面 CL=扇区
|----------------------------DH=磁头  DL=驱动器,00H~7FH:软盘;80H~0FFH:硬盘 ES:BX=缓冲区的地址 
|----------------------------出口参数:CF=0——操作成功AH=00H,AL=传输的扇区数,否则,AH=状态代码,
|------------ok_load_setup其中读取磁盘驱动器的参数  入口参数:AH=08H  DL=驱动器,00H~7FH:软盘;80H~0FFH
|----------------------------硬盘出口参数:CF=1——操作失败,AH=状态代码

setup.s程序

功能描述:

        主要利用ROM-BIOS中断读取机器系统数据,并将这些数据保存到0x90000开始的位置(覆盖bootsect程序所在的位置),所取的参数供其他程序使用如ttyio.c程序,然后将system模块从0x10000~~0x8ffff(不会超过512KB)整块移动到内存绝对地址0x00000处,接下来加载中断描述符表寄存器和全局描述符表寄存器,并开启A20地址线,重设中断芯片8259A,将硬件的中断号设置为0x20~~0x2f。最后设置CPU控制寄存器CR0(也称机器状态字)从而进入32位保护模式运行,并跳转到位于system模块最前面的head.s程序继续运行。

源码阅读相关问题:

|--------jmpi 0,8会跳转到head.s程序开始继续运行,8是段选择符,用于制定所需使用的描述符项{是代码段描述符项} 0 是代码段偏移

setup程序执行完成后的内存中程序的示意图:


head.s程序

功能描述:

首先加载各个数据段寄存器,重新设置中断描述符表idt,共256项,并使每一个表项指向一个只报错误的哑中断程序。然后重设全局描述符表gd,检测A20地址线是否开启{使用物理地址0与1MB开始处的内容相比较的方法},然后测试是否存在数学协处理芯片,并在控制寄存器CR0中设置相应的标志位。接着管理内存的分页处理机制,将页目录放在绝对物理地址0开始处,紧随其后的是可寻址16MB的内存的四个页表,并分别设置他们的表项。最后利用返回指令将预先放置到堆栈中的main.c程序的入口地址弹出,运行main程序。

阅读到的相关信息:

|-----将堆栈放置到stack_start所指向的user_stack数组内

|-----中断描述符表中的项由8B组成,也称作门描述符(Gate Descriptor)

|-----设置每个页表为4KB,每个页表项需要4B,一个页表共可以存放1024个表项。

system模块在内存的映像示意图:




原创粉丝点击