前言
BIOS(basic input/output system)是计算机启动后执行的第一个功能代码,BIOS的功能简单的总结就是,提供基本的输入/输出功能,引导操作系统,其中基本输入、输出功能比如键盘、显示器、硬盘的操作。这些功能的是如何实现,之前一直会有些困惑,本文简单的做个分析总结。
疑问
我们知道BIOS的设计体量是尽可能小的,但是功能却一点都不简单,因为涉及到很多外围硬件的功能调用,注意,这里说的是功能调用,并没有特制硬件初始化。在做单片机程序开发时,也有很多的外围操作,针对外围设备的操作,一般是要程序员编写外围设备驱动、然后再编写外围功能的调用函数(API),这部分工作有两个特点:
(1)外围硬件有很多种,即便是相同功能的外围硬件也会有不同的厂家。不同厂家的外围驱动也是有些细节不同的,BIOS的体量本身是很小的,肯定不能像“驱动精灵”一样,包罗万象的把所有硬件厂家的外围驱动都做了。
(2)外围的功能API代码也是很复杂的,比如最常见的 显示屏操作,我们知道显示器的操作时一件非常复杂、繁琐的工作。
综上,最大的疑问是:BIOS代码体量很小,它是如何适配多种厂家的外围接口驱动和功能呢?
答案
BIOS只会为一些简单的外围设备(内存、蜂鸣器等)提供初始化代码和简单的功能调用代码,并填写中断向量表,其他有很多功能是由外部设备接口自己创建的。
- 首先:每个外围设备接口,包括各种板卡,如网卡、显卡、键盘接口电路、硬件控制器等,都是有自己的只读存储器(ROM),类似BIOS芯片,这些ROM中提供了它自己的功能调用例程,以及本设备的初始化代码,按照规范约定,前两个单元的内容是 0x55 和 0xAA,第三个单元是本 ROM 中以 512 字节为单位的代码长度;从第四个单元开始,就是实际的 ROM 代码。
- 其次:从内存屋里地址A0000开始,到FFFFF结束,有相当一部分空间是留给外围设备的,如果外围设备存在,那么,它自带的ROM会映射到分配给她的地址范围内。
- 在计算机启动期间,BIOS 程序会以 2KB 为单位搜索内存地址 C0000~E0000 之间的区域。当
它发现某个区域的头两个字节是 0x55 和 0xAA 时,那意味着该区域有 ROM 代码存在,是有效的。
接着,它对该区域做累加和检查,看结果是否和第三个单元相符。如果相符,就从第四个单元进入。
这时,处理器执行的是硬件自带的程序指令,这些指令初始化外部设备的相关寄存器和工作状态,
最后,填写相关的中断向量表,使它们指向自带的中断处理过程。- 应用程序通过中断指令int调用BIOS的功能服务。
总结
BIOS自己本身,并不会包括所有外围设备的初始化和功能调用代码,这些功能都是外围设备厂商自己编写,然后存放到他们自己的ROM中,因为有地址映射的约定,BIOS可以直接将服务的调用,指向外围硬件的功能服务代码出,这样就实现了,BIOS不需要包罗万象,体积可以很小,就能实现功能多样。