哈尔滨工业大学李治军老师的《操作系统》课程实验,相关资源:
哈工大操作系统实验手册
实验资源与参考
不配环境懒人福利:实验楼
在线课程:操作系统,李治军,哈工大(网易云课堂)
参考阅读:《Linux内核完全注释》——赵炯,《操作系统原理、实现与实践》——李治军,刘宏伟
改写bootsect.s
,功能:能在屏幕上打印一段提示信息“XXX is booting...”。
改写setup.s
,功能:
bootsect.s能完成setup.s的载入,并跳转到setup.s开始地址执行。而setup.s向屏幕输出一行"Now we are in SETUP"。
setup.s获取一些基本的硬件参数(如内存参数、显卡参数、硬盘参数等),将其存放在内存的特定地址,并输出到屏幕上。
setup.s不再加载Linux内核,保持上述信息显示在屏幕上即可。
bootsect.s驻留在引导扇区(0磁道,0磁头,第1个扇区)。上电自检后,ROM BIOS把bootsect加载到0x7c00处。bootsect做4件事:
将自身移动到0x90000处并继续执行。
利用INT 0X13中断将setup模块读到0x90200处,一共读四个扇区。
显示“Loading system...”的字符串
再把setup模块后的system模块加载到内存0x10000处。
注:由于实验裁剪Linux 0.11的源代码,没有使用root_dev。
汇编看起来有点头大,大部分源码问题都能在《注释》里找到答案,几个比较重要的点:
将自身加载到0x9000后,跳到go处执行:
jmpi go,INITSEG ! 段间跳转, INITSEG是目的段地址, go是段内偏移地址
由于自身代码移动了位置,所以需要段间跳转:
修改显示字符串 将“Loading system ..."修改为”Welcome to NewOS“
原字符串共18个字符,加上回车和换行共24个字符,修改后字符串长16个字符。
调用INT 0X10中断,cx寄存器内存放显示字符数,bx寄存器存放属性(可修改字符串颜色),es:bp 指向待显示字符串。
mov ah,#0x03 ! 读取光标位置
xor bh,bh
int 0x10
mov cx,#22
mov bx,#0x0009 ! page 0, attribute c
mov bp,#msg1 ! es:bp 指向待显示字符串
mov ax,#0x1301 ! write string, move cursor
int 0x10
!开始执行setup代码
jmpi 0,SETUPSEG
msg1:
.byte 13,10
.ascii "Welcome to NewOS"
.byte 13,10,13,10
setup.s
主要功能:
利用中断读取机器系统数据,保存到0x90000处(覆盖了bootsect.s)
将system模块从0x10000-0x8ffff整块下移到0x00000处。
进入32位保护模式,跳转到system模块的head.s
注:实验要求setup不加载后续的system模块,故暂时不必要实现。
参考bootsect.s中显示字符串的代码部分,很容易修改得到:
! 显示"Now we are in SETUP"
mov ax,cs
mov ds,ax
mov es,ax
mov ah,#0x03 ! 读取光标位置
xor bh,bh
int 0x10
mov cx,#25
mov bx,#0x0007 ! page 0, attribute normal
mov bp,#msg1 ! es:bp 指向待显示 字符串
mov ax,#0x1301 ! write string, move cursor
int 0x10
注意,在显示前务必设置cs = es = ds,在显示时需要es定位字符串,现在是setup程序,SETUPSEG = cs = 0x9020
显示硬件参数前,先将ds寄存器重置为0x90000(INITSEG),在读取参数时使用了ds寄存器并覆盖了bootsect.s,所以重置ds,寻址硬件参数,ps:汇编中,mov ax, [0]
默认为mov ax, ds:[0]
。 后面按照取硬件参数的顺序,复制内存中的数据打印即可,比如光标信息:
! 打印光标信息
mov ax, [0]
call print_hex
call print_nl
ps:根据读取时,磁盘硬件参数从[0x80]开始。
根据实验指导在build.c中添加:
if(strcmp(argv[3],"none")==0) return 0;