资源描述
实验一总结——启动系统
zhangliang73@
此次实验的基本内容是:
1. 阅读《Linux内核完全注释》的第6章,对计算机和Linux 0.11的引导过程进行初步的了解;
2. 按照下面的要求改写0.11的引导程序bootsect.s
3. 有兴趣同学可以做做进入保护模式前的设置程序setup.s。
改写bootsect.s主要完成如下功能:
1. bootsect.s能在屏幕上打印一段提示信息“XXX is booting...”,其中XXX是你给自己的操作系统起的名字,例如LZJos、Sunix等(可以上论坛上秀秀谁的OS名字最帅,也可以显示一个特色logo,以表示自己操作系统的与众不同。)
改写setup.s主要完成如下功能:
1. bootsect.s能完成setup.s的载入,并跳转到setup.s开始地址执行。而setup.s向屏幕输出一行"Now we are in SETUP"。
2. setup.s能获取至少一个基本的硬件参数(如内存参数、显卡参数、硬盘参数等),将其存放在内存的特定地址,并输出到屏幕上。
3. setup.s不再加载Linux内核,保持上述信息显示在屏幕上即可。
bootsect.s代码解读
SYS_SIZE表示系统模块的大小,此处设置有冗余。
bootsect.s被BIOS启动程序装载到0x7c00处,然后把自己移开,复制到0x90000处,然后跳转到那里。
之后,它使用BIOS中断,将setup模块直接装载在紧邻它之后的0x90200处,又把system装载到0x10000处。
注意!当前的系统最大是8*65536字节。这没问题,未来也是。我想让它保持简单。这512KB的kernel大小是足够的,尤其是它像minix一样不包含缓存。
装载器被实现得尽量简单,持续的读取错误将导致死循环。请手动重启。在可能的情况下,它一次得到整个扇区,这样可使装载十分迅速。
setup扇区的长度 = 4
boot扇区的原地址 = 0x07c0 ;由于20位地址寻址时,段地址左移四位,表现为16进制1位
initseg = 0x9000 ;bootsect将移至的地址
setupseg = 0x9020 ;setup装载的位置
sysseg = 0x1000 ;system装载的地址
endseg = sysseg + syssize ;sys的结尾地址
总之是定义了根文件系统的物理位置。
data seg = bootseg ;源
extra seg = initseg ;目的
cx = 256 ;计数256,为bootsect长度
si = di = 0 ;源和目的的偏移指针为0.
重复移动字(256次),为512字节,一个扇区。
移好了之后,跳到initseg段的go标签执行。(本来就是下一句接着执行,不过做了段间跳转。)
go将数据段和扩展段都置为代码段。(此三句在后面常出现)
设置栈段和栈指针。(注,段间跳转时,IP = go, CS = INITSEG = 0x9000. 故,ax = 0x9000, 故ss = 0x9000, sp = 0xFF00. 根据20位段寻址规则,栈指针就在0x9ff00处。)
调用int 13读磁盘,在此前设置参数。
至此,setup被装载到0x90200处。
取磁盘驱动器的参数。
sectors = cl
ax被冲掉。bl有。ch被冲掉。cl给sectors。dx有。es被冲掉,di也作废了。最终只有sectors变量在后面被使用。
恢复es为当前段。
打印欢迎信息!
bh用xor清零囧
这一段代码用来打印,只改cx和bp即可。
之后加载system。置扩展段为系统所在段的地址(扩展段一般作为目的段。)
调用read_it.
关于test语句,可知,它可以限制ax的后12位必须为0,而前面没要求。注意,这是4KB,但因为它是es扩展段,因此寻址将会被左移4位,就成了64KB。
……
再往下,除了139行的之外,都是读入system的细节。正确读入完毕后,程序将跳到SETUP执行。
bootsect干的事:移自己,设置栈指针,装载setup,装载system。
setup.s代码解读
功能描述
简单说就是读取机器系统数据。
移动system模块。加载IDTR和GDTR,开启A20,重设中断芯片和硬件中断号。最后设置CR0,从而进入32位保护模式,并跳转到system的头部head.s执行。
setup.s将系统数据从BIOS得到并放在系统内存的合适位置。
向BIOS请求内存、磁盘、其他参数,放在安全的0x90000~0x901ff之间(setup.s前面,从原bootsect.s处开始),供保护模式来读取他们,在被缓冲区覆盖前。
一些段。
从开始到105行都是调用各种中断读取硬件信息的。
之后,关中断,移动system到0x00000处
加载段描述符。根据读书笔记(^_^),我们知道GDT和IDT是相似的(而LDT和TR是相似的,是段。),其表项就是段描述符,直接用两条语句load就行了。
下面是开启A20地址线。
之后是重新对中断进行编程。(略囧)
最后,进入保护模式。
189 置PE位
190 加载机器状态字
191 段间跳转到8段0偏移。
解释如下:
到此,setup就结束了。程序跳到head处执行。
展开阅读全文