操作系统-哈工大笔记1

【操作系统基础笔记】(哈工大)



前言

笔记中的参考资料是哈工大OS慕课课程 这是关于操作系统的第一份笔记 相关资料也参考了网上其他人的写法 主要目的就是未来学习笔记所用 主要讲了操作系统内核启动中的bootset.s 希望大家批评指正


一、什么是操作系统

操作系统是底层计算机硬件与上层应用软件之间的一个软件,计算机的一切活动都是通过cpu、内存、显卡、显示器等硬件设备来实现的。
在这里插入图片描述
在这里插入图片描述
这里介绍一下相关概念:
中央处理器(CPU),是电子计算机的主要设备之一,电脑中的核心配件。其功能主要是解释计算机指令以及处理计算机软件中的数据。
CPU在执行指令时,通过代码寄存器CS和指令指针寄存器IP(instruction Pointer)来确定要执行的下一条指令的内存地址。 CS:IP 两个寄存器指示了CPU当前要赌气的指令地址,计算方式一般为CS左移4位然后加上IP寄存器,作为地址去取内容。
在这里插入图片描述
计算机的工作就是从磁盘取指令到内存,然后执行指令;即“取指执行”。

开机的一瞬间CS和IP的值是多少这个问题是由硬件决定的,对于X86的PC机来说,开机时, CS=0xFFFF; IP=0x0000;因此地址为0xFFFF0(ROM BIOS映射区),刚开机时,内存里面只有这个地方有数据,这部分程序的功能是:检查RAM、键盘、显示器等硬件(这部分数据是固化在内存里面的,只能读不能写)。然后将磁盘0磁道0扇区(一个扇区是512个字节)内容读入0x7c00处,磁盘的0磁道0扇区存储的就是操作系统的引导程序(即bootsect.s);同时设置CS=0x07c0,ip=0x0000,即开始执行操作系统。

二、操作系统流程

在这里插入图片描述
从机器加电开始执行顺序如上图所示
bootsect.s 和setup.s是实时模式下运行的16位代码程序,采用近似Intel语法,而head.s使用GUN汇编格式(AT&T),并且运行到保护模式下。

刚开机时候,CPU自动进入实模式,并从地址0XFFFF0开始执行程序代码,这个地址通常是ROM-BIOS中的地址,PC机的BIOS将执行某些系统检测,并在物理地址0处开始初始化中断向量。然后,它将可以启动设备的第一个扇区(磁盘引导扇区,512byte)读入内存绝对地址0x7C00处,并跳转到这个地方,启动设备通常是软驱或者硬盘。

Linux最前面部分(boot/bootsect.s),它将由BIOS读入内存绝对地址0x7C00处,当它被执行时就会把自己移动到内存绝对地址0X90000处,并把启动设备中后2kb字节代码(boot/setup.s)读入到内存0x90200处,而内核的其他部分(system模块)则被读入到内存地址0x10000开始处

setup.s将会把system模块移动到物理内存起始位置处,这样system模块中代码的地址就等于实际的物理地址,便于对内核代码和数据操作。
在这里插入图片描述
整个系统从地址0x10000移至0x0000处,进入保护模式并跳转至系统的余下部分(在0x0000chu)。此时所有的32位运行方式的设置启动被完成:IDT,GDT和LDT被加载,处理器和协处理器也确认,分页工作也设置完成。

最终调用init/main.c中main()程序

三、内核启动

1.bootsect.s

引导扇区代码:bootsect.s
操作系统引导程序文件名是:bootsect.s,为什么不是bootsect.c呢?.s说明是汇编程序,.c是c程序,操作系统在刚刚启动的时候每一条指令都是严格要求的,不能有任何的出入,汇编程序和机器指令是一一对应的;但是c程序就不一样,比如:int a;a这个变量的地址就是随机的,所以不能是.c。
bootsect.s代码是磁盘引导块程序,驻留在磁盘的第一个扇区中(引导扇区,0磁道(柱面),0磁头,第一个扇区)
在这里插入图片描述

在PC机加电ROM BIOS自检后,ROM BIOS会把引导扇区代码bootsect加载到内存地址0x7C00开始处并执行之。在bootsect代码执行期间,它会将自己移动到内存绝对地址0x90000开始处并继续执行。

该程序的主要作用是首先把从磁盘第2个扇区开始的4个扇区的setup模块(由 setupo.s编译而成)加载到内存紧接着bootsect后面位置处(0x90200),然后利用BIOS中断 0x13 ,取磁盘参数表中当前启动引导盘的参数,接着在屏幕上显示“Loading system.”字符串。

再把磁盘上setup模块后面的system模块加载到内存0x10000开始的地方。随后确定根文件系统的设备号,若没有指定,则根据所保存的引导盘的每磁道扇区数判别出盘的类型和种类并保存其设备号于 root_dev(
引导块的508地址处),最后长跳转到setup程序的开始处(0x00200)执行sctup程序。

BOOTSEG = 0x07c0
INITSEG = 0x9000
SETUPSEG = 0x9020
 ; bootsect启动程序将它自身从内容0x07c00(BOOTSEG)处复制至内存0x9000(INITSEG)处
entry start            ;关键字entry告诉链接器"程序入口"
start:
	mov	ax,#BOOTSEG    ;BOOTSEG = 0x7c00 赋值给ax,
	mov	ds,ax          ;源地址
	mov	ax,#INITSEG    ;INITSEG = 0x9000 赋值给bx
	mov	es,ax		   ;目标地址
	mov	cx,#256        ;循环次数,每次循环完次数减一
	sub	si,si          ;清零
	sub	di,di          ;清零
	rep		movw		   ;  表示移动字,移动的个数是cx=256,也就是512个字节,也就是说这段代码的作用就是将从0x07c00地址处开始的512个字节移动到0x90000处
	 
	jmpi	go,INITSEG ;  这条指令是间接跳转,go->ip,INITSEG->CS,前面已经说了INITSEG就是0x9000,go是一个标号,go表示的是距离start的偏移,现在因为已经将0x07c00处的512个字节移动到了0x90000处,所以go相较于start的偏移其实也就是相较于INITSEG的偏移,所以也就是顺序执行。
 

; 从这里开始cpu已经跳到内存0x90000去执行,
; BIOS把引导扇区加载到0x7c00处并把执行权交给引导程序,(ss=0x00,sp=0xfffe)
; 将ds,es,ss,都设置成移动后代码所在段(0x9000)
go:	mov	ax,cs          ;ax = cs = INITSEG = 0x9000
	mov	ds,ax          ;数据段地址
	mov	es,ax          ;附加段地址


! put stack at 0x9ff00. ;将堆栈指针sp指向0x9fff00(0x9000:0xff00)
	mov	ss,ax           ;栈段地址
; 保证栈指针sp只要指向远大于512byte字节偏移(即地址0x90200)
; 因为在0x90200后要存放setup程序,大约为4个扇区 sp指向大于(0x200+0x200*4+堆栈大小)
	mov	sp,#0xFF00		! arbitrary value >>512  

! load the setup-sectors directly after the bootblock.
; 在bootsect程序紧跟着加载setup程序
! Note that 'es' is already set up.
; es在移动代码时设置好了指向目的地址0x9000
;0x13是BIOS读磁盘扇区的中断: ah=0x02(读磁盘),al=扇区数量(SETUPLEN=4)ch=柱面号,cl=开始扇区,dh=磁头号,dl=驱动器号,es:bx=内存地址
load_setup: //载入setup模块
    mov dx,#0x0000 mov cx,#0x0002 mov bx,#0x0200
    mov ax,#0x0200+SETUPLEN int 0x13 //BIOS中断
    jnc ok_load_setup
    mov dx,#0x0000
    mov ax,#0x0000 //复位
    int 0x13
    j load_setup //重读

在这里插入图片描述
到目前为止,只有bootsect.s的一个扇区被读进内存了,其他的还没有读进去,因此其他内容使用
int 0x13 号中断读进去。
开始扇区cl:02;扇区数:al:4;就是说从第二个扇区开始读4个扇区到内存,
ip的值为 es:bx ;es:0x9000;bx:0x0200;也就是说从0x90200开始;对的,因为bootsect是512个字节。512用十六进制表示就是200。所以,load_setup: 的功能就是将setup读进内存,紧接着bootsect后面

ok_load_setup:

! Get disk drive parameters, specifically nr of sectors/track
; 取磁盘驱动器的参数,特别是每道的扇区数量
; 取磁盘驱动器的参数 INT 0x13调用格式和返回信息:
; 调用格式:
; ah = 0x08        dl = 驱动器号(如果是硬盘则位7要置位)
; 返回信息:
; 如果出错,则CF值位,并且ah = 状态码
; ah = 0, al = 0  bl = 驱动器类型(AT/PS2)
; ch = 磁道(柱面)号低8; cl = 开始扇区(0-5),磁道号高两位(6-7)	
; dh = 最大磁头数 ,   dl = 驱动器数量
; es:di--->软驱磁盘参数表
	mov	dl,#0x00
	mov	ax,#0x0800		! AH=8 is get drive parameters
	int	0x13
	mov	ch,#0x00

; 这条指令表示下一条指令的操作数在cs段寄存器所指的段中
	seg cs
; 保持每磁道扇区数 (cx = 每磁道扇区数)
	mov	sectors,cx
	mov	ax,#INITSEG
; 由于上面取磁道参数中断改掉了es的值,这里重新复制, 	
	mov	es,ax
 msg1:.byte 13,10
        .ascii “Loading system....byte 13,10,13,10

因此就是在屏幕上显示 “loading system…”, cx 是表示显示的字符数量(字节),bx 是显示属性。具体这些东西可以自己百度。

后面的 read_it 还是读操作系统到内存里面。然后bootsect.s结束。因此bootsect.s的功能就是将操作系统读入内存。
并且显示logo:”loading system…”。bootsect到此结束。

在这里插入图片描述
在这里插入图片描述

bootsect.s的小总结

bootsect.s是操作系统的最开始部分,共512个字节,在磁盘的0磁道0扇区位置,首先内存里面肯定是有代码的,具体存在哪个位置是由硬件决定的,然后从那个位置开始读入操作系统,首先读入的是操作系统的bootsect部分,对于x86PC来说,bootsect读进来是放在0x07c00这个位置,然后将其转移到0x90000这个位置,并继续执行;利用int 0x13中断,将操作系统的setup读入到0x90200开始的内存处,setup在磁盘上是第二到第五个扇区,第一个是bootsect扇区;读入setup之后,bootsect继续执行,在屏幕上显示开机logo “loading system…”。然后进入 read_it 继续读操作系统模块,然后将控制权转移到setup中,执行setup中的内容。


  • 2
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

依嘫_吃代码

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值