(浓缩+精华)哈工大-操作系统-MOOC-李治军教授-实验1-操作系统的引导

操作系统实验1:引导


实验基本内容:

  1. 阅读《Linux 内核完全注释》的第 6 章,对计算机和 Linux 0.11 的引导过程进行初步的了解;
  2. 更改bootsect.s引导程序的开机显示文字,并能完成setup.s的载入
  3. 更改setup.s接管硬件程序的开机显示文字,并将基本硬件参数显示在硬盘上
  4. 有时,继承传统意味着别手蹩脚。x86 计算机为了向下兼容,导致启动过程比较复杂。请找出 x86 计算机启动过程中,被硬件强制,软件必须遵守的两个“多此一举”的步骤(多找几个也无妨),说说它们为什么多此一举,并设计更简洁的替代方案。

一.阅读linux内核完全注释:了解引导 P205
  1. 引导启动程序:boot/目录
    1. 启动引导时内核在内存中的位置和移动后的位置情况。(bootsect.s移位后引导其他扇区,setup.s:探测+os移位+临时建表进入保护模式)在这里插入图片描述
    2. ROOT_DEV:根文件系统所在的默认块-设备号。交换设备号SWAP_DEV:用作虚拟存储交换空间的外部设备号
  2. bootsect.S程序
    1. 该程序作用:
      1. 首先把从磁盘第 2 个扇区开始的 4 个扇区的 setup 模块(由 setup.s 编译而成)加载到内存紧接着bootsect 后面位置处(0x90200)
      2. 然后利用BIOS 中断0x13 取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示“Loading system…”字符串。
      3. 把磁盘上 setup 模块后面的system 模块加载到内存0x10000 开始的地方。随后确定根文件系统的设备号。若没有指定,则根据所保存的引导盘的每磁道扇区数判别出盘的类型和种类(是 1.44M A 盘吗?),并保存其设备号于 root_dev (引导块的 508 地址处)中。
      4. 长跳转到setup 程序开始处(0x90200)去执行
  3. setup.S程序
    1. 该程序作用:
      1. 利用ROM BIOS 中断读取机器系统数据,并将这些数据保存到 0x90000 开始的位置(覆盖掉了 bootsect 程序所在的地方)。所取得的参数和保留的内存位置见表所示。这些参数将被内核中相关程序使用,例如字符设备驱动程序集中的console.ctty_io.c程序等。 在这里插入图片描述
        在这里插入图片描述
      2. 然后setup 程序将system 模块从0x10000-0x8ffff 整块向下移动到内存绝对地址 0x00000 处(当时认为内核系统模块 system 的长度不会超过此值:512KB)。接下来加载中断描述符表寄存器(IDTR)和全局描述符表寄存器(GDTR),开启 A20 地址线,重新设置两个中断控制芯片 8259A,将硬件中断号重新设置为 0x20 - 0x2f。
      3. 设置CPU 的控制寄存器CR0(也称机器状态字),进入32 位保护模式运行,并跳转到位于 system 模块最前面部分的 head.s程序继续运行。
  4. 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,bh
    int 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,bh
    int 0x10
    mov cx,#25            
    mov bx,#0x0007     
    mov bp,#msg2
    mov ax,cs
    mov es,ax
    mov 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,bh
    int 0x10
    mov cx,#36            
    mov bx,#0x0007     
    mov bp,#msg1
    mov ax,#0x07c0
    mov es,ax
    mov 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=0x07e0
	jmpi    0,SETUPSEG
! 注意将上一个实验的jmp inf_loop代码删掉!!

实验结果:

在这里插入图片描述

3.修改setup.s

  1. 显示数字的代码要看懂。其中用到的BIOS中断为INT 0x10,功能号0x0E(显示一个字符),即AH=0x0E,AL=要显示字符的ASCII码。但AL实际是由栈bp指向的字符赋值来的,那么其实显示的是ss:bp的字符
  2. 注意与上面区别。MOV AX,#0X1301 + INT 0x10是显示es:bp下的字符串
  3. 因此本题将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数字加上十六进制0x30
        cmp    al,#0x3a
        jl    outp          !是一个不大于十的数字
        add    al,#0x07      !是a~f,要多加7
    outp: 
        int    0x10
        loop    print_digit	!cx--
        ret

!setup.s关键代码
! Be Ready to Print
    mov 	ax,#SETUPSEG	! init es = 0x9020
    mov 	es,ax			
    mov 	ax,#INITSEG     	! init ss:sp.put stack at 0x90000.
    mov 	ss,ax
    sub		sp,sp

! Print "Now we are in SETUP"
	mov		ah,#0x03		! read cursor pos
	xor		bh,bh
	int		0x10
	mov		cx,#25
	mov		bx,#0x0007		! page 0, attribute 7 (normal)
	mov		bp,#msg2
	mov		ax,#0x1301		! write string, move cursor
	int		0x10

! Get Params
	mov 	ax,#INITSEG 
	mov 	ds,ax
	mov 	ah,#0x03  
    xor 	bh,bh
	int 	0x10      
	mov 	[0],dx    
	mov 	ah,#0x88
	int 	0x15
	mov 	[2],ax
	mov 	ax,#0x0000
	mov 	ds,ax
	lds 	si,[4*0x41]
	mov 	ax,#INITSEG
	mov 	es,ax
	mov 	di,#0x0004
	mov 	cx,#0x10
	rep
	movsb

! Be Ready to Print
    mov 	ax,#SETUPSEG	! init es = 0x9020
    mov 	es,ax			

! Cursor Position 
    mov 	ah,#0x03   
    xor 	bh,bh
    int 	0x10
    mov 	cx,#18
    mov 	bx,#0x0007     
    mov 	bp,#msg_cursor
    mov 	ax,#0x1301   
    int 	0x10 

    mov		bp,#0x00
    call    print_hex 

! Memory Size
    mov 	ah,#0x03      
    xor 	bh,bh
    int 	0x10
    mov 	cx,#14
    mov 	bx,#0x0007      
    mov 	bp,#msg_memory
    mov 	ax,#0x1301      
    int 	0x10 

    mov		bp,#0x02
    call    print_hex 

(后续代码如磁盘信息或许同上)

实验结果如图:

在这里插入图片描述
最后补番外链接:
1.实验楼(操作系统原理与实践)
https://www.shiyanlou.com/courses/115
2.网易云课堂:哈尔滨工业大学,国家级精品课程,操作系统
https://mooc.study.163.com/course/1000002004#/info
3.推荐markdown神器,本文由此写成
https://typora.io/
(完)

  • 14
    点赞
  • 54
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值