《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模块在内存的映像示意图:
- 《linux内核完全注释0.11》 读书笔记 0
- linux内核完全注释【读书笔记】
- Linux内核体系结构--Linux内核完全注释读书笔记
- Linux内核完全注释
- Linux内核完全注释
- 《Linux内核完全注释》pdf v3.0
- linux内核完全注释目录
- Linux内核完全注释 PDF
- 《Linux内核完全注释》内核版本0.11 赵炯 著
- linux内核注释的读书笔记
- 《Linux内核完全剖析》读书笔记
- 《LINUX内核完全注释0.11》学习笔记(草稿)
- linux 0.11 内核完全注释V3.0学习笔记(一)
- 读核日记&《Linux内核完全注释》
- 《Linux内核完全注释》笔记(1)
- 《Linux内核完全注释》笔记(1)
- 《linux内核完全注释》的价值
- 《Linux 内核完全注释》阅读笔记
- Objective C定义私有方法
- Spring声明式事务配置管理方法
- 时间复杂度
- 三级指针作形参(命令行参数处理)
- java面试葵花宝典(中)
- 《linux内核完全注释0.11》 读书笔记 0
- PHP 变量与数组,非常有用
- 嵌入式ARM
- 敏用户故事驱动开发系列之三:用户故事来源之“北极星”计划
- java面试葵花宝典(下)
- Spring事务管理-aop切入配置
- UDK添加电脑自带的AI
- 自已来定义VK_0~VK_9,VK_A~VK_z
- Eclipse build Android时不生成apk问题解决方法(加了JAR以后,不重新生成APk)