1-操作系统启动前的工作

Posted PacosonSWJTU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1-操作系统启动前的工作相关的知识,希望对你有一定的参考价值。

【README】

1.本文总结自B站《操作系统(哈工大李治军老师)》的视频讲解,非常棒,墙裂推荐;


【1】计算机上电  

1)    问题: 这神秘的黑色背后发生了什么 ?计算机是怎么工作的?


【2】从白纸到图灵机

计算3+2的加法:

  • 控制器从纸带上读取已经写好的3 2 +;读取后,执行加法逻辑得到5,并把5再次送入到纸带上;但问题是,这个控制器只会做加法,不能做其他,这就是问题所在了

【3】从图灵机到通用图灵机

如果一个控制器,像一个只会做饼的厨师那样,就显得很低级,不灵活,没法扩展了;
我们需要的是能够看懂菜谱的厨师一样的控制器;能够灵活与扩展,不仅仅只会做加法,还会做其他算术或逻辑运算;

厨师读到菜谱1,可以做菜品1;

厨师读到菜谱2,可以做菜品2;

控制器也一样:

先预先设置控制器动作逻辑;

然后读取数据对象,根据预设动作进行相应的计算;

 通用图灵机:能够设置控制器动作逻辑的控制机;其中控制器动作逻辑就是应用程序;


【4】从通用图灵机到计算机

冯诺依曼存储程序思想,在1946年提出 :
4.1)存储程序的主要思想:将程序和数据存放到计算机内部的存储器中,计算机在程序的控制下一步步处理;

把程序或指令存储到内存(主存)里,然后用一条指令指针(IP或PC)指向某条指令;把该指令载入到控制器(取指),从而形成控制逻辑,即指令描述了控制器如何工作,接着控制器根据指令进行相应操作(执行);

 小结:计算机怎么工作的呢? 取指+执行;  

4.2)冯诺依曼计算机由5大部件组成:

  • 输入设备;
  • 输出设备;
  • 存储器;
  • 运算器;
  • 控制器;

那windows系统启动的黑色背景如何产生的

  • 经过刚刚的分析,控制器是在指令下工作的,指令是由PC或IP的指向得到的;那计算机启动时,PC或IP指向的第一条指令是什么?

【5】打开电源,计算机执行的第一句指令是什么?

 【问题】打开电源,计算机执行的第一句指令是什么?

1)Bios:Basic Input Output System, 基本输入输出系统;(开机时,唯一有程序的地方)
开机执行步骤:

  • 步骤1:开机后,CS=0xFFFF, IP=0x0000 ;CS-Code Segment-代码段寄存器;IP=Instruction Point=指令指针寄存器;
  • 步骤2:读取CS和IP的值,并把CS的地址左移4位与IP寄存器的地址相加,得到BIOS程序所在地址 0xFFFF0 ;
  • 步骤3:从只读存储器ROM中 CS:IP地址上读取BIOS程序到控制器,控制器根据BIOS程序进行相应操作;
  • 步骤4:BIOS程序首先检查 ram,主板,键盘,显示器,软硬磁盘;
  • 步骤5:接着BIOS程序把磁盘的0磁道0扇区(即第1个扇区512字节)的数据读取到以0x7c00为首地址的内存单元中;其中0磁盘0扇区即第1个扇区就是操作系统的引导程序所在扇区(又称引导扇区),1个扇区512k;
  • 步骤6:设置cs=0x07c0,ip=0x0000;所以可以得到内存地址0x7c00;

接下来,控制器就会执行内存地址0x7c00保存的程序,即操作系统引导扇区的程序


【5.1】0x7c00存放的代码是什么 ?

 

1)引导扇区代码示例 :

Bootsect.s 中的 .s 指的是 汇编代码assembly;其中bootsect指的是引导扇区,boot sector;
所以引导扇区代码,是一段汇编代码;

2)为什么要用汇编代码? 而不用C呢?

  • C语言无法控制某个变量在内存中的哪个位置上存储;
  • 而因为汇编的每一条指令都转为了机器指令,汇编可以控制变量存储的内存地址
  • 又引导扇区需要对程序进行完整控制,包括变量存储的内存地址;

3)Bootsect.s 引导扇区的代码要做什么事情呢?

引导扇区程序(0x7c00处存放的代码)的汇编指令执行步骤:

表1 引导扇区汇编程序bootsect执行步骤

步骤

指令

描述

1

mov ax,#BOOTSEG

#BOOTSEG=0x07c0;

2

mov ds,ax

把 0x07c0送入ds寄存器;

3

Mov ax,#INITSEG

#INITSEG=0x9000;

4

Mov es,ax

把 0x9000送入es寄存器

5

Mov cs,#256

把256赋值给cs寄存器;

6

Sub si si

把0x0000送入si寄存器;

7

Sub di di

把0x0000送入di寄存器;

8

Rep movw

重复移动256个字=512字节;

源地址:ds:si=0x07c0:0x0000;即0x7c00;

目标地址:es:di=0x9000:0x0000;即0x90000;

即把0x7c00的代码拷贝到0x90000内存地址

9

jmpi go, INITSEG

jump intersegment-段间跳转:

目标地址=cs:ip=INITSEG:go=0x9000:go;

下面进入到go为标号(锚点)的汇编指令执行

 补充,寄存器列表:

  • 1.    AX――累加器(Accumulator),使用频度最高
  • 2.    BX――基址寄存器(Base Register),常存放存储器地址
  • 3.    CX――计数器(Count Register),常作为计数器
  • 4.    DX――数据寄存器(Data Register),存放数据
  • 5.    SI――源变址寄存器(Source Index),常保存存储单元地址
  • 6.    DI――目的变址寄存器(Destination Index),常保存存储单元地址
  • 7.    BP――基址指针寄存器(Base Pointer),表示堆栈区域中的基地址
  • 8.    SP――堆栈指针寄存器(Stack Pointer),指示堆栈区域的栈顶地址
  • 9.    IP――指令指针寄存器(Instruction Pointer),指示要执行指令所在存储单元的地址。IP寄存器是一个专用寄存器。

4)为什么要把0x7c00的引导扇区程序拷贝到0x90000呢?
为了腾出空间,腾出空间干什么呢 ?

5)jmpi go, INITSEG 是什么作用(引导扇区代码最后一条指令)?

jump intersegment-段间跳转:

目标地址=cs:ip=INITSEG:go;

图 1 启动盘结构图

表1中的步骤9 执行了 jmpi go, INITSEG;意思是跳转到目标地址=cs:ip=INITSEG:go=0x9000:go 去执行;所以接着执行上图的 go标号的汇编指令,步骤如下:

步骤

指令

描述

go标号

1

Mov ax,cs

把cs=0x9000赋值给ax

2

Mov ds,ax

把值0x9000赋值给ds

3

Mov es,ax

把值0x9000赋值给es

4

Mov ss,ax

把值0x9000赋值给ss

5

Mov sp,#0xff00

把值0xff00赋值给sp

load_setup标号

载入setup模块

7

Mov dx,#0x0000

8

Mov cx,#0x0002

ch=0x00 cl=0x02

9

Mov bx,#0x0200

0x0200赋值给bx

10

Mov ax,#0x0200+SETUPLEN

//SETUPLEN=4; 把0x0204赋值给ax;

ah=0x02 al=0x04

11

Int 0x13

//BIOS中断,读取磁盘数据

12

Jnc ok_load_setup

//跳转到 ok_load_setup标号(锚点)

13

Mov dx,#0x0000

14

Mov ax,#0x0000

// 复位

15

Int 0x13

16

J load_setup

// 重读

 最重要的指令是 int 0x13,这是一个BIOS中断;这个中断从磁盘读取数据,磁盘寻址如下:
从ch:cl(柱面号:开始扇区=0x00:0x02)开始读取磁盘数据,共计读取ah:al(0x02:0x04读磁盘:扇区数量)个扇区到内存地址es:bx(0x9000:0x0200);
即从第2个扇区读取4个扇区的数据(setup数据)到内存0x90200,因为第1个扇区存储了引导扇区程序

6)接着,读入setup模块后,执行 ok_load_setup 锚点

Int 0x10 表示 一种BIOS中断,用于显示字符;显示的字符为 #msg1 即bp寄存器;
ok_load_setup标号的程序执行步骤如下:
      表3 ok_load_setup汇编程序执行过程

步骤

指令

描述

ok_load_setup标号

// 载入setup模块

1

Mov dl,#0x00

把0x00赋值给dl

2

Mov ax,#0x0800

把0x0800赋值给ax,即ah:al=08:00

3

Int ox13

//BIOS中断,读取磁盘数据

4

Mov ch,#0x00

把0x00赋值给ch

5

Mov sectors,cx

把cx赋值给sectors

Mov ah,#0x03

把0x03赋值给ah

7

Xor bh,bh

异或运算,把0x00赋值给bh

8

Int 0x10

//BIOS中断,读光标

9

Mov cx,#24

把24赋值给cx,表示要输出24个字符;

10

Mov bx,#0x0007

0x0007赋值给bx;其中0007是显示属性;

11

Mov bp,#msg1

把msg1赋值给bp;bp存储要显示的字符;

msg1是偏移;就是把 Loading system字符串打到屏幕上的光标位置

其中byte13,10 分别是换行和回车ascii码

12

Mov ax,#1301

把1301赋值给ax

13

int 0x10

//BIOS中断,显示字符

14

Mov ax,#SYSSEG

//SYSSEG=0x1000

15

Mov es,ax

把ax赋值给es;

16

Call read_it

//读取system模块

read_it 仍然是13号中断,把操作系统后面的代码读入到内存;读完之后,bootsect汇编文件执行完成;

Jmpi 0,SETUPSEG

// SETUPSEG=0x9020

jump intersegment-段间跳转:

目标地址=cs:ip=SETUPSEG:0=SETUPSEG:0;

即下面跳转到SETUPSEG为标号(锚点)的汇编指令执行;

 如果我们要把 Loading System字符串修改为 diyos is loading字符串(长度15)在屏幕上显示的话,还需要把第9条汇编指令修改为 mov cx,#15;

小结:

  • bootsect.s 文件中的汇编代码干的事情就是,把操作系统读入到内存,打出一个logo或字符串(diyos is loading);

Bootsect.s 汇编程序执行完成后,就需要把控制权交给下一个程序执行,即setup程序;
如何跳转到setup程序呢?

  • 执行 jmpi 0, SETUPSEG 即可;根据图1,我们知道SETUPSEG 的汇编程序在启动盘的第2~5个扇区;


【总结】计算机启动过程 

以上是关于1-操作系统启动前的工作的主要内容,如果未能解决你的问题,请参考以下文章

mongoDB启动前的系统设置,解决部分Warning问题

Linux 0.11-操作系统启动完结篇-40

Linux 0.11-操作系统启动完结篇-40

请解释这句sql!关于去重的,从语法角度详细解释: x,over,partition!特别是where前的x!

主窗口前的PyQt5启动画面[重复]

工作中的“厨师”,生活上的诗人,其实也是架构师