linux操作系统学习1-bootsect引导

本文介绍了Linux操作系统的启动过程,重点讨论了BIOS的作用和功能,以及bootsect.s在启动流程中的关键角色。通过学习,我们可以更深入地了解计算机硬件与操作系统的交互方式,为理解操作系统原理打下基础。
linux操作系统学习-bootsect引导

操作系统是什么?恰如其名。

早期的计算机需要人为的更换"程序",后来换成了从队列中取用程序,但是有些程序执行时需要很多IO操作,浪费了宝贵的CPU计算资源,后来又实现了多进程……

人类精益求精(嫌麻烦)的心态促进了计算机的发展,如果没有操作系统,我们要让一个程序在计算机上运行,小点的程序尚可接受,但想开发运行大型程序,真是难以想象那种场景。

操作系统方便我们,很多框架也在方便我们,以至于我觉得自己可以用计算机做成很多事,但问题来了,我真的知道程序在做什么、如何运转起来的吗?仔细想来,对我来讲,自己写的程序就像是开了99%幸运的外挂一样,主要是因为幸运,绝大多数时间才都是正常的,额……

如果对操作系统感兴趣,建议看 哈工大操作系统 视频,可以配套《linux内核完全注释》食用

bios

BIOS是个人电脑启动时加载的第一个软件,复制下百度百科对BIOS的解释:

BIOS是英文"Basic Input Output System"的缩略词,直译过来后中文名称就是"基本输入输出系统"。在IBM PC兼容系统上,是一种业界标准的固件接口。

其实,它是一组固化到计算机内主板上一个ROM芯片上的程序,它保存着计算机最重要的基本输入输出的程序开机后自检程序和系统自启动程序,它可从CMOS中读写系统设置的具体信息。 其主要功能是为计算机提供最底层的、最直接的硬件设置和控制。此外,BIOS还向作业系统提供一些系统参数。系统硬件的变化是由BIOS隐藏,程序使用BIOS功能而不是直接控制硬件。现代作业系统会忽略BIOS提供的抽象层并直接控制硬件组件。

安装过操作系统的话会对BIOS比较熟悉,为什么提到BIOS,是因为它是绝大多数操作系统的前提。目前的计算机是没有自主能力的,所以必须明确通电后做什么,不然就是个空壳子。

BIOS不是计算机启动后正常运行的必要条件,有需要的话完全可以通电后直接运行个完善的操作系统,看需要和硬件支撑吧。

下面是《linux内核完全注释》关于个人电脑通电后的执行流程的介绍:

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

总结依赖如下:硬件支撑(芯片 内置BIOS) <— linux操作系统(windows等)

bootsect.s

感谢《linux内核完全注释》,讲的真细致。

在这里插入图片描述

注:该系统的硬盘扇区的大小是512字节

主体代码: 注释主要参照《linux内核完全注释》

SETUPLEN = 4				! nr of setup-sectors(setup程序扇区数)
BOOTSEG  = 0x07c0			! original address of boot-sector
INITSEG  = 0x9000			! we move boot here - out of the way
SETUPSEG = 0x9020			! setup starts here
SYSSEG   = 0x1000			! system loaded at 0x10000 (65536,64KB).
ENDSEG   = SYSSEG + SYSSIZE		! where to stop loading

! ROOT_DEV:	0x000 - same type of floppy as boot.
!			0x301 - first partition on first drive etc
ROOT_DEV = 0x306 			!设备号0x306指定根文件系统设备是第2个硬盘的第1个分区,可根据自己系统的实际位置更改

entry _start
_start:
	mov	ax,#BOOTSEG
	mov	ds,ax
	mov	ax,#INITSEG
	mov	es,ax
	mov	cx,#256				!注:该场景该模式下,都是16位操作,每次循环转移16位(2字节),实际转移512字节,即bootsect全部内容
	sub	si,si
	sub	di,di
	rep
	movw					!将bootsect自己移动到0x90000处
	jmpi	go,INITSEG		!段间跳转,已经开始跳到0x9000段执行
go:	mov	ax,cs
	mov	ds,ax
	mov	es,ax
! put stack at 0x9ff00.
	mov	ss,ax
	mov	sp,#0xFF00		! arbitrary value >>512,0x90000-0x90200是bootsect自己,紧接着放setup,这里的栈指针要大于bootsect+setup程序

! load the setup-sectors directly after the bootblock.(开始加载setup程序)
! Note that 'es' is already set up.(上面已经置成0x9000)
! load_setup,从磁盘第2个扇区开始读[SETUPLEN]个扇区到数据缓冲区es:bx,即0x90200
load_setup:
	mov	dx,#0x0000		! drive 0, head 0
	mov	cx,#0x0002		! sector 2, track 0
	mov	bx,#0x0200		! address = 512, in INITSEG
	mov	ax,#0x0200+SETUPLEN	! service 2, nr of sectors
	int	0x13			! read it
	jnc	ok_load_setup		! ok - continue
	mov	dx,#0x0000
	mov	ax,#0x0000		! reset the diskette
	int	0x13
	j	load_setup

ok_load_setup:
! Get disk drive parameters, specifically nr of sectors/track
! 通过0x13中断获取磁盘参数,尤其是每道的扇区数量,具体参数意义可看原书
	mov	dl,#0x00
	mov	ax,#0x0800		! AH=8 is get drive parameters
	int	0x13
	mov	ch,#0x00
	seg cs
	mov	sectors,cx
	mov	ax,#INITSEG
	mov	es,ax

! Print some inane message,输出信息(Loading system ...,后面定义的,本文没复制)
! 通过0x10中断进行屏幕输出
	mov	ah,#0x03		! read cursor pos
	xor	bh,bh
	int	0x10
	
	mov	cx,#24
	mov	bx,#0x0007		! page 0, attribute 7 (normal)
	mov	bp,#msg1
	mov	ax,#0x1301		! write string, move cursor
	int	0x10

! ok, we've written the message, now
! we want to load the system (at 0x10000)

	mov	ax,#SYSSEG
	mov	es,ax		! segment of 0x010000
	call	read_it
	call	kill_motor

! After that we check which root-device to use. If the device is
! defined (!= 0), nothing is done and the given device is used.
! Otherwise, either /dev/PS0 (2,28) or /dev/at0 (2,8), depending
! on the number of sectors that the BIOS reports currently.
! 检查使用那个根文件系统设备

	seg cs
	mov	ax,root_dev
	cmp	ax,#0
	jne	root_defined
	seg cs
	mov	bx,sectors		! ok_load_setup获取磁盘参数时赋值的
	mov	ax,#0x0208		! /dev/ps0 - 1.2Mb
	cmp	bx,#15
	je	root_defined
	mov	ax,#0x021c		! /dev/PS0 - 1.44Mb
	cmp	bx,#18
	je	root_defined
undef_root:
	jmp undef_root
root_defined:
	seg cs
	mov	root_dev,ax

! after that (everyting loaded), we jump to
! the setup-routine loaded directly after
! the bootblock:

	jmpi	0,SETUPSEG	! 开始执行setup程序

汇编已经基本相当机器码了,linux0.11的bootsect.s比较短,好像还可以接受,饶是如此,看的也非常吃力(也缺个好的ide给变量和寄存器溯源,看着看着就忘了对应的值是啥了)。

总结一下吧
  1. 目前的计算机还离不开取指执行、顺序执行(逻辑判断也是顺序的),巧妙的是,怎么设计的让简单的取指执行能做到很复杂的事?
  2. 这一通汇编需要开发者明确每条指令,顺序进行,假设硬盘里存了100个待执行的程序,如果直接跑,那么就需要在每个待执行的程序末尾指明下一个程序所在位置、载入内存、CS IP指过去,或者由一个主程序按顺序运行100个任务程序,有的任务程序可能耗时很短就能完成,却排到最后执行,有的程序可能有大量IO操作,期间CPU干呆着。由于各种各样类似的实际问题,有了进程调度、操作系统等等,话说回来,现在都有啥实际问题呢?我找茬的钛合金双眼哪去了?
  3. 待续
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值