计算机启动过程2

本文详细解析了操作系统启动的全过程,从BIOS加载启动扇区到CPU执行内存中的代码。首先,BIOS将硬盘启动区的代码复制到内存0x7c00处执行,然后通过汇编指令将数据复制到0x90000处,进行段寄存器设置,最后跳转到新位置继续执行。整个过程中涉及到了内存寻址、段寄存器的作用以及代码的自我移动。
摘要由CSDN通过智能技术生成

明确:

1、编译器将程序翻译成了机器指令,CPU执行的是机器指令。

2、操作系统本身也是个程序,执行之后会生成一大堆机器指令。

回顾:当按下开机键的那一刻,在主板上提前写死的固件程序 BIOS 会将硬盘中启动区的 512 字节的数据,原封不动复制到内存中的 0x7c00 这个位置,并跳转到那个位置进行执行。(只要硬盘中的 0 盘 0 道 1 扇区的 512 个字节的最后两个字节分别是 0x55 和 0xaa,那么 BIOS 就会认为它是个启动区。)所以作为操作系统的开发人员,仅需要把操作系统最开始的那段代码,编译并存储在硬盘的 0 盘 0 道 1 扇区即可。之后搬运工BIOS就会把它放到内存去跳转执行。

 Linux-0.11 的最开始的代码,就是这个用汇编语言写的 bootsect.s,位于 boot 文件夹下。通过编译,这个 bootsect.s 会被编译成二进制文件,存放在启动区的第一扇区。

 随后就会由 BIOS 搬运到内存的 0x7c00 这个位置,而 CPU 也会从这个位置开始,不断往后一条一条语句无脑地执行下去。之后的一切将从这两行代码开始:

1

2

mov ax,0x07c0

mov ds,ax

  这段代码是用汇编语言写的,含义是把 0x07c0 这个值复制到 ax 寄存器里,再将 ax 寄存器里的值复制到 ds 寄存器里。那其实这一番折腾的结果就是,让 ds 这个寄存器里的值变成了 0x07c0。

 当我们写一段汇编语言时,实际上仅仅写了偏移地址,比如:

1

mov ax, [0x0001]

  相当于

1

mov ax, [ds:0x0001]

  ds是一个16位的段寄存器,具体表示数据段寄存器,在内存寻址时充当段基址的作用。ds 是默认加上的,表示在 ds 这个段基址处,往后再偏移 0x0001 单位,将这个位置的内存数据,复制到 ax 寄存器中。

        这个 ds 被赋值为了 0x07c0,由于 x86 为了让自己在 16 位这个实模式下能访问到 20 位的地址线这个历史因素,所以段基址要先左移四位。那 0x07c0 左移四位就是 0x7c00,那这就刚好和这段代码被 BIOS 加载到的内存地址 0x7c00 一样了。也就是说,之后再写的代码,里面访问的数据的内存地址,都先默认加上 0x7c00,再去内存中寻址。

因为BIOD规定死了把操作系统代码加载到内存 0x7c00,所以里面的各种数据都被偏移了这么多,所以把数据段寄存器ds设置为这个值,方便了之后访问内存时利用这个段基址进行寻址。

 之后的代码:

1

2

3

4

5

6

7

8

mov ax,0x07c0

mov ds,ax

mov ax,0x9000

mov es,ax

mov cx,#256

sub si,si

sub di,di

rep movw

  sub si,si意思位si=si - si,si是寄存器,这个举动将寄存器里的值清零。此时几个寄存器分别被赋初值

赋值为了执行:

1

rep movw

 意思是     “重复执行后面的指令    字(16位)",执行cx=256次,从 ds:si 处复制到 es:di 处,一次复制两个字节。这条命令就是为了将内存地址 0x7c00 处开始往后的 512 字节的数据,原封不动复制到 0x90000 处。

 后面接一个跳转指令

1

2

3

4

jmpi go,0x9000

go:

  mov ax,cs

  mov ds,ax

  jmpi 是一个段间跳转指令,表示跳转到 0x9000:go 处执行。go 是一个标签,最终编译成机器码的时候会被翻译成一个值,这个值就是 go 这个标签在文件内的偏移地址。这个偏移地址再加上 0x90000,就刚好是 go 标签后面那段代码 mov ax,cs 此时所在的内存地址了。

那假如 mov ax,cx 这行代码位于最终编译好后的二进制文件的 0x08 处,那 go 就等于 0x08,而最终 CPU 跳转到的地址就是 0x90008 处。

总结:一段 512 字节的代码和数据,从硬盘的启动区先是被移动到了内存 0x7c00 处,然后又立刻被移动到 0x90000 处,并且跳转到此处往后再稍稍偏移 go 这个标签所代表的偏移地址处,也就是 mov ax,cs 这行指令的位置。简称”自己给自己挪地方“  为甚末跳转?

这些指令都是cpu中的

1

2

3

4

5

go: mov ax,cs

    mov ds,ax

    mov es,ax

    mov ss,ax

    mov sp,#0xFF00

  这段代码的直意思就是把 cs 寄存器的值分别复制给 dses 和 ss 寄存器,然后又把 0xFF00 给了 sp 寄存器。cs 寄存器表示代码段寄存器,CPU 当前正在执行的代码在内存中的位置,就是由 cs:ip 这组寄存器配合指向的,其中 cs 是基址,ip 是偏移地址。

其实操作系统在做的事情,就是给如何访问代码,如何访问数据,如何访问栈进行了一下内存的初步规划。其中访问代码和访问数据的规划方式就是设置了一个基址而已,访问栈就是把栈顶指针指向了一个远离代码位置的地方而已。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值