(浓缩+精华)哈工大-操作系统-MOOC-李治军教授-实验1-操作系统的引导
操作系统实验1:引导
实验基本内容:
- 阅读《Linux 内核完全注释》的第 6 章,对计算机和 Linux 0.11 的引导过程进行初步的了解;
- 更改
bootsect.s
引导程序的开机显示文字,并能完成setup.s
的载入- 更改
setup.s
接管硬件程序的开机显示文字,并将基本硬件参数显示在硬盘上- 有时,继承传统意味着别手蹩脚。x86 计算机为了向下兼容,导致启动过程比较复杂。请找出 x86 计算机启动过程中,被硬件强制,软件必须遵守的两个“多此一举”的步骤(多找几个也无妨),说说它们为什么多此一举,并设计更简洁的替代方案。
一.阅读linux
内核完全注释:了解引导 P205
- 引导启动程序:boot/目录
- 启动引导时内核在内存中的位置和移动后的位置情况。(
bootsect.s
移位后引导其他扇区,setup.s
:探测+os
移位+临时建表进入保护模式) ROOT_DEV
:根文件系统所在的默认块-设备号。交换设备号SWAP_DEV
:用作虚拟存储交换空间的外部设备号
- 启动引导时内核在内存中的位置和移动后的位置情况。(
bootsect.S
程序- 该程序作用:
- 首先把从磁盘第 2 个扇区开始的 4 个扇区的 setup 模块(由
setup.s
编译而成)加载到内存紧接着bootsect
后面位置处(0x90200) - 然后利用BIOS 中断0x13 取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示“Loading system…”字符串。
- 把磁盘上 setup 模块后面的system 模块加载到内存0x10000 开始的地方。随后确定根文件系统的设备号。若没有指定,则根据所保存的引导盘的每磁道扇区数判别出盘的类型和种类(是 1.44M A 盘吗?),并保存其设备号于 root_dev (引导块的 508 地址处)中。
- 长跳转到setup 程序开始处(0x90200)去执行
- 首先把从磁盘第 2 个扇区开始的 4 个扇区的 setup 模块(由
- 该程序作用:
setup.S
程序- 该程序作用:
- 利用ROM BIOS 中断读取机器系统数据,并将这些数据保存到 0x90000 开始的位置(覆盖掉了
bootsect
程序所在的地方)。所取得的参数和保留的内存位置见表所示。这些参数将被内核中相关程序使用,例如字符设备驱动程序集中的console.c
和tty_io.c
程序等。
- 然后setup 程序将system 模块从0x10000-0x8ffff 整块向下移动到内存绝对地址 0x00000 处(当时认为内核系统模块 system 的长度不会超过此值:512KB)。接下来加载中断描述符表寄存器(IDTR)和全局描述符表寄存器(GDTR),开启 A20 地址线,重新设置两个中断控制芯片 8259A,将硬件中断号重新设置为 0x20 - 0x2f。
- 设置CPU 的控制寄存器CR0(也称机器状态字),进入32 位保护模式运行,并跳转到位于 system 模块最前面部分的
head.s
程序继续运行。
- 利用ROM BIOS 中断读取机器系统数据,并将这些数据保存到 0x90000 开始的位置(覆盖掉了
- 该程序作用:
head.s
程序
二、实验
1.bootsect显示正确。es:bp
是显示字符串的地址:ES设#SETUPSEG
是内存中存放setup.s
开始的地方,BP表示存放#MSG2的偏移地址。
我没设es,没加inf_loop死循环。没改.org(! 表示下面语句从地址 506(0x1FA)开始,所以 root_dev 在启动扇区的第 508 开始的 2 个字节中。)! 首先读入光标位置mov ah,#0x03 xor bh,bhint 0x10! 显示字符串 “Hello OS world, my name is LZJ”
! 要显示的字符串长度mov cx,#36 !大一些没关系mov bx,#0x0007 mov bp,#msg1
! es:bp 是显示字符串的地址mov ax,#0x1301 int 0x10
- 实验结果如图:(偷偷暗示我名字是YYF)
2.setup.s
显示文字,并载入bootsect.s
! setup.s (从bootsect.s复制而来,换掉了msg1和start,并加上了死循环)
entry _start
_start:mov ah,#0x03 xor bh,bhint 0x10mov cx,#25 mov bx,#0x0007 mov bp,#msg2mov ax,csmov es,axmov ax,#0x1301 int 0x10
inf_loop:jmp inf_loop
msg2:.byte 13,10 .ascii "NOW we are in SETUP".byte 13,10,13,10
boot_flag:.word 0xAA55 ! bootsect.s (仅仅改了SETUPLEN而已)
SETUPLEN=2
entry _start
_start:mov ah,#0x03 xor bh,bhint 0x10mov cx,#36 mov bx,#0x0007 mov bp,#msg1mov ax,#0x07c0mov es,axmov ax,#0x1301 int 0x10
load_setup:
! 设置驱动器和磁头(drive 0, head 0): 软盘 0 磁头mov dx,#0x0000
! 设置扇区号和磁道(sector 2, track 0): 0 磁头、0 磁道、2 扇区mov cx,#0x0002
! 设置读入的内存地址:BOOTSEG+address = 512,偏移512字节 mov bx,#0x0200
! 设置读入的扇区个数(service 2, nr of sectors),
! SETUPLEN是读入的扇区个数,Linux 0.11 设置的是 4,
! 我们不需要那么多,我们设置为 2(因此还需要添加变量 SETUPLEN=2)mov ax,#0x0200+SETUPLEN
! 应用 0x13 号 BIOS 中断读入 2 个 setup.s扇区 int 0x13
! 读入成功,跳转到 ok_load_setup: ok - continue jnc ok_load_setup
! 软驱、软盘有问题才会执行到这里。我们的镜像文件比它们可靠多了 mov dx,#0x0000
! 否则复位软驱 reset the diskette mov ax,#0x0000 int 0x13
! 重新循环,再次尝试读取jmp load_setup
ok_load_setup:
! 接下来要干什么?当然是跳到 setup 执行。
! 要注意:我们没有将 bootsect 移到 0x9000,因此跳转后的段地址应该是 0x7ce0
! 即我们要设置 SETUPSEG=0x07e0jmpi 0,SETUPSEG
! 注意将上一个实验的jmp inf_loop代码删掉!!
实验结果:
3.修改setup.s
- 显示数字的代码要看懂。其中用到的BIOS中断为INT 0x10,功能号0x0E(显示一个字符),即AH=0x0E,AL=要显示字符的ASCII码。但AL实际是由栈
bp
指向的字符赋值来的,那么其实显示的是ss:bp
的字符 - 注意与上面区别。
MOV AX,#0X1301 + INT 0x10
是显示es:bp下的
字符串 - 因此本题将
ss
设为#0x9000,es
设为setup代码段基址#0x9020。再不断改变bp
显示字符串即可
!以16进制方式打印栈顶的16位数print_hex:mov cx,#4 ! 4个十六进制数字mov dx,(bp) ! 将(bp)所指的值放入dx中,如果bp是指向栈顶的话print_digit:rol dx,#4 ! 循环以使低4比特用上 !! 取dx的高4比特移到低4比特处。mov ax,#0xe0f ! ah = 请求的功能值,al = 半字节(4个比特)掩码。and al,dl ! 取dl的低4比特值。add al,#0x30 ! 给al数字加上十六进制0x30cmp al,#0x3ajl outp !是一个不大于十的数字add al,#0x07 !是a~f,要多加7outp: int 0x10loop print_digit !cx--ret!setup.s关键代码
! Be Ready to Printmov ax,#SETUPSEG ! init es = 0x9020mov es,ax mov ax,#INITSEG ! init ss:sp.put stack at 0x90000.mov ss,axsub sp,sp! Print "Now we are in SETUP"mov ah,#0x03 ! read cursor posxor bh,bhint 0x10mov cx,#25mov bx,#0x0007 ! page 0, attribute 7 (normal)mov bp,#msg2mov ax,#0x1301 ! write string, move cursorint 0x10! Get Paramsmov ax,#INITSEG mov ds,axmov ah,#0x03 xor bh,bhint 0x10 mov [0],dx mov ah,#0x88int 0x15mov [2],axmov ax,#0x0000mov ds,axlds si,[4*0x41]mov ax,#INITSEGmov es,axmov di,#0x0004mov cx,#0x10repmovsb! Be Ready to Printmov ax,#SETUPSEG ! init es = 0x9020mov es,ax ! Cursor Position mov ah,#0x03 xor bh,bhint 0x10mov cx,#18mov bx,#0x0007 mov bp,#msg_cursormov ax,#0x1301 int 0x10 mov bp,#0x00call print_hex ! Memory Sizemov ah,#0x03 xor bh,bhint 0x10mov cx,#14mov bx,#0x0007 mov bp,#msg_memorymov ax,#0x1301 int 0x10 mov bp,#0x02call print_hex (后续代码如磁盘信息或许同上)
实验结果如图:
最后补番外链接:
1.实验楼(操作系统原理与实践)
https://www.shiyanlou.com/courses/115
2.网易云课堂:哈尔滨工业大学,国家级精品课程,操作系统
https://mooc.study.163.com/course/1000002004#/info
3.推荐markdown神器,本文由此写成
https://typora.io/
(完)
(浓缩+精华)哈工大-操作系统-MOOC-李治军教授-实验1-操作系统的引导相关推荐
- 哈工大操作系统实验一——操作系统的引导
写在前面 哈尔滨工业大学李治军老师的<操作系统>课程实验,相关资源: 哈工大操作系统实验手册 实验资源与参考 不配环境懒人福利:实验楼 在线课程:操作系统,李治军,哈工大(网易云课堂) 参 ...
- 操作系统(李治军) L9多进程图像-操作系统最重要的图像
@[TOC]操作系统 解决一个任务即开启一个进程 PCB(process control block)进程控制块 'W'设置成阻塞态 Schedule():切换函数 pCur:当前进程 pNew:新进 ...
- 操作系统(李治军) L8 CPU管理的直观想法
@[TOC]操作系统 CPU的 取指执行 给了cpu初地址自动的取值执行 给地址在内存中取出来执行 50:mov ax,[100] 51:mov bx,[101] - - 依次向下顺序执行 管理CPU ...
- 操作系统(李治军) L12内核级线程的实现
只有支持了进程才可以管理CPU 图:五段论 整个过程:从用户栈->内核栈->TCB->TCB完成切换(TCB用switch_to完成TCB的切换完成内核栈的切换)->内核栈切换 ...
- 操作系统(李治军) L11内核级线程
**用户级和核心级的区别:根据TCB切换一个栈还是一套栈** 进入内核要用中断 INT和IRET压栈来使寄存器的状态指令从用户栈和内核栈来回切换 ESP:系统分区 cur,next当前和下一个线程的T ...
- 操作系统(李治军) L10用户级线程
进程更大,线程更小 进程切换=指令切换+资源(内存)(映射表)切换[分治思想] 线程切换:避免了进程切换代价:不需要切换资源(映射表) 这是多个线程 这是因为进程的地址是分离的,所以是线程 buffe ...
- 操作系统实验一到实验九合集(哈工大李治军)
操作系统实验 作者寄语 操作系统实验的学习是一个循序渐进的过程,初次看linux-0.11中的代码,看着满屏的汇编语言,确实头疼.但通过学习赵炯博士的Linux内核0.11完全注释,结合着王爽老师的汇 ...
- 哈工大操作系统实验总结
实验地址, https://www.lanqiao.cn/courses/115/learning/?id=374, 在现做实验, 好处是环境提前都配好了, 不足之处是敲代码有网络延迟, 环境无法保存 ...
- Linux0.11操作系统(哈工大李治军老师)实验楼实验1-引导
Linux0.11操作系统(哈工大李治军老师)实验楼实验1-引导 实验源地址: https://www.lanqiao.cn/courses/115/learning/ 1.完成bootsect.s屏 ...
最新文章
- 把文档放到PNG图片中
- python直方图均衡化
- php编程实现单入口,apache配置php实现单一入口方法
- QT4使用HDF5 类型错误
- Java 用接口实现加减乘除计算器
- 建武28a对讲机最大距离_小米对讲机再出新品:不但价格低,还能一键写频
- 异步电机matlab仿真 推荐 辅导书,异步电机模型Matlab仿真
- 五、ELK设置用户密码登陆
- 厘米和磅的转换程序python_在Python中如何将磅转换成公斤
- CODEVS 1069 关押罪犯
- EOS区块链的通信模型
- YOLOv3目标检测算法——通俗易懂的解析
- SpringBoot 中定时执行注解(@Scheduled、@EnableScheduling)
- 接口与抽象类的区别,为什么要用接口,抽象类不香吗?
- 【基础入门题072】转置矩阵
- JUC详解 | JUC Lock
- 【计算机网络】HTTP协议中Get与Post的区别
- ERROR in Cannot find module ‘node-sass‘和Error:Node Sass version 5.0.0 is incompatible with ^4.0.0解决
- JAVA热部署神器,JRebel破解版,JRebel免费实用插件
- 1.Docker学习之基础知识