了解操作系统

分类: 操作系统

计算机是如何开机的

cpu的由来,硬件运行原理,从上电到加载bios

从白纸到图灵机

图灵计算机是一种模拟人工作流程的机器,就是模拟人算数,把输入,计算,再输出这过程用一个自动化设备模拟出来。

从图灵剂到通用图灵机

图灵机就像只会做一道菜的厨师,给他材料他就按逻辑给你结果。

而通用图灵机像是一个会看菜谱的厨师,你给他格式化的菜谱和材料他可以对着做给你结果。

看懂菜谱的过程其实是更复杂的一套更复杂的逻辑。把这个过程抽象就是通用图灵机。

通用图灵机的控制器(厨师)脑袋里本身是空白的,是一套通用的结构。

我们的菜谱其实包含控制器动作 - 控制器状态 - 数据对象,这个厨师按照我们菜谱的内容来,而这个菜谱的格式规范了,就实现通用了。

这个过程中的核心就是这个菜谱,这个菜谱的编码,这个菜谱就是程序

引出---

冯诺伊曼储存程序猜想

​ 将程序和数据存放在计算机内部的存储器中,计算机在程序的控制下一步一步进行处理

​ 计算机由五大部分组成,输入设备,输出设备,存储器,运算器,控制器。

把程序载入内存里,用一条指令指针指向他(相当于开始运行),然后取指执行,

指令指针 (IP/PC): 在 CPU 内部有一个特殊的寄存器,叫作指令指针(Instruction Pointer,在某些架构中也叫程序计数器 PC)。 它的用处是告诉 CPU 下一步该去内存的哪个地方抓取指令

取指 (Fetch): CPU 根据指令指针指向的内存地址,把那里的指令抓取到自己的寄存器里。

译码 (Decode): CPU 内部的译码器分析这条指令要做什么(是要加法?还是要跳转?还是要搬运数据?)。

执行 (Execute): CPU 对应的功能部件(如算术逻辑单元 ALU)完成该操作。

更新指针: 执行完后,指令指针会自动指向下一条指令的地址,周而复始。

引出---

打开电源之后计算机执行的第一句指令是什么

对于x86结构,每次上电后内存中有一部分是固化的(固化在0xffff0),就是rom bios映射区。每当上电时,所以开机时硬件自动设置好cs=0xffff,ip=0x0000,所以开机自动跳到0xffff0(涉及汇编)。

就这样,这段bios程序就开始执行了,这段程序负责初始化硬件。检测硬件过后bios就要从磁盘的0磁道0扇区(操作系统的引导扇区)读出数据放到0x7c00处。之后再设置cs=0x07c0, ip=0x0000。

就这样,bios从现在bios跳到你的引导扇区执行了。这个内存地址存放的代码就是你的引导扇区,就是你启动设备的第一个扇区,引导扇区的那512个字节。 --引导扇区代码bootsect.s (汇编代码):

.globl _start               ! 定义全局入口符号
.text                       ! 代码段开始

BOOTSEG  = 0x07c0           ! BIOS 加载 Bootloader 的原始内存地址
INITSEG  = 0x9000           ! 我们打算把代码搬往的新地址(避开后续内核空间)

_start:
    ! 1. 设置源地址段寄存器 (DS = 0x07c0)
    mov ax, #BOOTSEG
    mov ds, ax

    ! 2. 设置目标地址段寄存器 (ES = 0x9000)
    mov ax, #INITSEG
    mov es, ax

    ! 3. 设置计数器 (CX = 256 字 = 512 字节)
    mov cx, #256

    ! 4. 清零源偏移 (SI) 和目标偏移 (DI)
    sub si, si              ! 源地址指向 0x07c0:0
    sub di, di              ! 目标地址指向 0x9000:0

    ! 5. 执行重复移动指令
    ! rep 表示重复 cx 次,movw 表示每次移动一个字 (Word, 2字节)
    rep
    movw

    ! 6. 间接长跳转 (Inter-segment Jump)
    ! 这行代码最关键:它让 CPU 跳转到新地址 (0x9000) 处的 go 标签继续执行
    jmpi go, INITSEG

go:
    ! (后续代码将从这里在 0x9000 段内继续运行)



这段引导扇区的核心代码其实是内存搬运的“起止点”,把处于“临时地址”的启动程序搬运到“永久办公地址”,为后续加载巨大的操作系统内核腾出空间。

下一主要部分

bootsect.s 的任务已经完成了一大半,它接下来要做两件事:通知用户(打印信息)加载内核主体(System 模块)

ok_load_setup:
    ! 1. 获取当前光标位置
    ! 调用 BIOS 中断 0x10,功能号 AH=03
    mov ah,#0x03
    xor bh,bh               ! bh 是页号,通常为 0
    int 0x10                ! 返回值:dx 中包含当前光标的行列信息

    ! 2. 准备打印字符串 "Loading system..."
    mov cx,#24              ! 字符串的长度(包括换行符)
    mov bx,#0x0007          ! 页号 0,属性 7(正常显示,黑底白字)
    mov bp,#msg1            ! 指向字符串的内存地址
    mov ax,#0x1301          ! AH=13 (写字符串), AL=01 (光标跟随移动)
    int 0x10                ! 调用 BIOS 视频服务

    ! 3. 开始加载 system 模块
    mov ax,#SYSSEG          ! SYSSEG = 0x1000
    mov es,ax               ! 设置 ES 为目标段地址
    call read_it            ! 调用复杂的磁盘读取函数,把内核读入 0x10000 处
    call kill_motor         ! 读取完毕,关闭软驱马达(节省电力和硬件寿命)

    ! 4. 最终跳转
    jmpi 0,SETUPSEG         ! 跳转到 0x9020:0 处,正式进入 setup.s 执行

这就是boot流程。最后设置p c指针(修改cs和ip)跳转到setup