> 文章列表 > 引导程序、BIOS中断、检测内存容量、实模式切换到保护模式

引导程序、BIOS中断、检测内存容量、实模式切换到保护模式

引导程序、BIOS中断、检测内存容量、实模式切换到保护模式

初始化引导程序

基本概念

 BIOS会将磁盘的第0个扇区(大小为512字节),加载到0x7c00处。

引导程序负责操作系统的加载,主要用于为操作系统运行提供初始化环境,并运行加载操作系统。

BIOS只加载磁盘的第0个扇区(512字节)到内存中,次程序无法做很多事情。

因此,我们可以采取以下两种方式种的任意一种。

 X86在上电后,自动进入实模式,目的是为了兼容早期的应用程序。

 X86与编程相关的主要内核寄存器

 AX BX CX DX 是32位寄存器,在实模式的情况下,只能使用低16位寄存器。高16位寄存器是要留给切换到保护模式的。

CS DS SS ES FS GS 为段寄存器,为访问特定内存地址,需要采用段寄存器:偏移的形式。

8086 CPU 在实模式工作的情况下,内存映射。只能够访问1M的内存空间,如下图所示:

 工程实战

进入start 示例工程

在source/boot/start.S 添加如下代码。

先build,然后F5启动调试,可以看到各个段寄存器都为 0X0。

按下F11进行单步进行调试。

可以看到进行单步调试前,esp寄存器为:0x6f00

单步调试到27行,esp寄存器就变为:0x7c00

使用BIOS中断显示字符

BIOS提供了一组服务,可以方便地帮助我们操作硬件,避免与硬件细节打交道。

当触发软中断的时,会自动从中断向量表中取相应的地址执行,参数通过寄存器传递。

使用BIOS中断读取字符

将引导程序分成2部分:

1.Boot只是做一些简单的工作,它的程序容量比较小,不超过512字节。

2.把更多的工作放在loader里面做。

BIOS提供了磁盘读取的接口,方便我们从磁盘上读取loader。

 BIOS只加载磁盘的第0扇区(512字节)到内存中,此部分程序无法做很多事情。

INT13磁盘读取

然后build,

 打开disk1.img磁盘镜像文件,可以看到 55 AA后面,是 E9 0E 开始。

 -exec x /20bx 0x8000  ==> 20代表20个字节 b代表byte x代表十六进制

可以看到0x8000地址处的数据为 0xe9 0x0e 0x03 ... 和磁盘中的数据是一样的。说明磁盘的读取是成功的。

进入C语言环境并跳到loader

如果生成loader并写入磁盘映像?怎么样从boot跳转到loader执行呢?

主要流程为如下所示:

第一步:从汇编到C

在source/boot/start.S 目录下添加如下代码,加上断点调试可以进入 boot.c文件中的 这个函数boot_entry 。

然后在source/boot/ 目录下,新增loader文件夹,在loader文件夹下面添加start.S汇编文件,汇编文件的内容如下所示:

添加loader.h loader_16.c(16位实模式) loader_32.c(32位模式)

 

第二步:添加工程配置文件

首先在顶层的CMakeLists.txt 进行 add_subdirectory

第三步:添加函数指针进行跳转

利用内嵌汇编显示字符串

BIOS提供了一组服务,可以方便地帮助我们操作硬件,避免与硬件细节打交道。

在loader_16.c文件中,添加 show_msg 字符串显示函数,在17行加上断点,编译运行,可以看到:

 

为了防止汇编器对汇编代码进行优化,通常使用 __asm__ __volatile__

检测内存容量(1)

参考:检测内存容量 · 语雀

首先在source目录下新建comm文件夹,然后分别新建2个文件 types.h和 boot_info.h,这两个文件的内容分别如下所示:

 

 

在loader文件夹下的 loader.h 文件,添加对应的文件。

 

在loader目录下的 loader_16.c文件下,添加一个全局的 boot_info_t 变量。

 

检测内存容量(2)

未完待续....

切换进程保护模式(1)

 

CPU上电复位后默认进入实模式,这种模式下没有保护机制,但提供了BIOS服务。(相当于单片机)

 

与此同时,实模式下可以使用BIOS提供的各种服务接口。

 

保护模式为后面增加的功能,为操作系统以及应用程序的运行添加很多支持。

 

从实模式切换到保护模式,需要遵循一定的流程。

 

CPU流水线

 

切换进程保护模式(2)