《操作系统真象还原》BIOS
以下是读本书第二章的收获。
记得我大学学习操作系统的时候会遇到一些奇奇怪怪的问题,因为觉得问题太奇怪了,所以羞于问老师。诸如ROM到底是个什么东西;如果用内存映射的方式访问外部设备,是不是内存条里专门有块内存空间来用于访问供外部设备,是不是先访问内存条这个地址,然后就直接跳到访问这个设备了等等。幸运的是,这本书都给我一一解答了。
实际上,ROM是下图这样的一种只读存储器(取自百度百科),是一种即使没有通电,也能保存信息的存储器。ROM其实是既可以读也可以写,只不过由于历史原因统称只读存储器。ROM种类不少,我们常用的固态硬盘就是基于闪存(一种ROM)的存储器。
我们下面将要说的BIOS正是存储在ROM设备中的程序,为什么BIOS放在ROM上?个人觉得,BIOS每次通电开机时都要运行,所以是不适合RAM这种断电即丢失信息的存储器了;至于磁盘也不太适合了,我们知道CPU能够直接访问的只有寄存器和内存,不包括磁盘这种外围设备。所以要执行在磁盘中程序的话,首先要将代码加载到内存里,再让CPU从内存取指令出来执行,但因为此时还未执行BIOS程序,换句话说,我们还没有对硬件IO操作的功能,所以将代码从磁盘里加载出来的功能还不能使用。这样的话,磁盘程序放不出BIOS,BIOS也执行不了初始化操作,将BIOS放在硬盘估计就是让BIOS和硬盘俩对着对方干瞪眼,所以硬盘并不适合。而ROM正适合放那些一成不变的程序,那么放在主板上的一块ROM芯片理所当然地承载着BIOS这段程序了。
接着引出一个问题,访问ROM中BIOS是不是要先加载到内存里面在让CPU访问呢?不是的,其实ROM也是内存的一部分,是可以被CPU直接访问的。因此,我们插在主板上的内存条并不是我们眼里的所有内存,内存除了刚才所说的ROM和内存条外还包括外设,如显存,硬盘控制器等等,这些都是能够被CPU直接访问的。比如CPU访问0xC8000-0xEFFFF这块地址,并不是访问我们的内存条,而是直接访问到我们的硬件适配器的ROM或者内存映射的I/O。 下图解释了CPU访问内存各部分的流程:
解释完上面两个问题,我们正式进入主题。
BIOS
BIOS,Base Input & Output System,基本输入输出系统,它的主要工作是初始化硬件,硬件里有初始化的功能供BIOS调用;除此之外,BIOS还建立了中断向量表,建立之后,我们就可以通过int 中断号来对硬件进行IO操作,当然,BIOS也仅仅是初始化重要的硬件IO操作来保证计算机的运行,并不会面面俱到,在保护模式会对更多硬件做支持,但在实模式下保证基本的就够了,所以才说是“基本”输入输出系统。
加载BIOS的流程
开机时,BIOS不可能自己加载自己,必然时被硬件所加载的。上面说到存储BIOS的ROM是块内存,是可以被CPU直接访问的。这ROM被映射到了地址0Xf0000~0xfffff处,入口地址,即程序开始执行的地址是0xffff0。所以我们只需将CPU的cs:ip值设置到0xffff0即可,cs:ip组合成0xffff0的方式有很多,不过根据过去的做法,是将CPU的cs:ip寄存器强制初始化为0xf000:0xfff0。这样,在开机的瞬间,CPU就会执行0xffff0下的代码。
BIOS----->MBR
BIOS检测外设信息和初始化硬件,建立中断向量表后,BIOS就已经完成它的任务,最后就是将任务交给MBR了。BIOS最后会校验启动盘中的0盘0道1扇区,如过该上去末尾的两个字节是0x55和0xaa即说明这个扇区存储着MBR程序,于是就加载该扇区到物理地址0x7c00,执行jmp 0 :0x7c00跳到该扇区,继续执行MBR程序。
编写MBR
在写代码之前,先简单介绍几个nasm标号: $代表当前行地址。$$代表当前section的地址。section可以命名某段代码。如果section有vstart修饰,$和$$都是基于vstart顺延的值。这样说的有点简单粗暴,下面看个例子。
某个文件代码如下:
section data vstart=0x500
jmp $
jmp $$
Jmp $中的$实际就是0x500
Jmp $$中的$$实际就是0x500
如果想获得文件中真实的地址,就用section.节名.start,如section.data.start = 0
接下来直接给出MBR代码:
;主引导程序
;------------------------------------------------------------
SECTION MBR vstart=0x7c00
mov ax,cs
mov ds,ax
mov es,ax
mov ss,ax
mov fs,ax
mov sp,0x7c00 ; 清屏 利用0x06号功能,上卷全部行,则可清屏。
; -----------------------------------------------------------
;INT 0x10 功能号:0x06 功能描述:上卷窗口
;------------------------------------------------------
;输入:
;AH 功能号= 0x06
;AL = 上卷的行数(如果为0,表示全部)
;BH = 上卷行属性
;(CL,CH) = 窗口左上角的(X,Y)位置
;(DL,DH) = 窗口右下角的(X,Y)位置
;无返回值:
mov ax, 0x600
mov bx, 0x700
mov cx, ; 左上角: (0, 0)
mov dx, 0x184f ; 右下角: (80,25),
; VGA文本模式中,一行只能容纳80个字符,共25行。
; 下标从0开始,所以0x18=24,0x4f=79
int 0x10 ; int 0x10 ;;;;;;;;; 下面这三行代码是获取光标位置 ;;;;;;;;;
;.get_cursor获取当前光标位置,在光标位置处打印字符.
mov ah, ; 输入: 3号子功能是获取光标位置,需要存入ah寄存器
mov bh, ; bh寄存器存储的是待获取光标的页号 int 0x10 ; 输出: ch=光标开始行,cl=光标结束行
; dh=光标所在行号,dl=光标所在列号 ;;;;;;;;; 获取光标位置结束 ;;;;;;;;;;;;;;;; ;;;;;;;;; 打印字符串 ;;;;;;;;;;;
;还是用10h中断,不过这次是调用13号子功能打印字符串
mov ax, message
mov bp, ax ; es:bp 为串首地址, es此时同cs一致,
; 开头时已经为sreg初始化 ; 光标位置要用到dx寄存器中内容,cx中的光标位置可忽略
mov cx, ; cx 为串长度,不包括结束符0的字符个数
mov ax, 0x1301 ; 子功能号13是显示字符及属性,要存入ah寄存器,
; al设置写字符方式 ah=01: 显示字符串,光标跟随移动
mov bx, 0x2 ; bh存储要显示的页号,此处是第0页,
; bl中是字符属性, 属性黑底绿字(bl = 02h)
int 0x10 ; 执行BIOS 0x10 号中断
;;;;;;;;; 打字字符串结束 ;;;;;;;;;;;;;;; jmp $ ; 使程序悬停在此 message db "1 MBR"
times -($-$$) db
db 0x55,0xaa
这个MBR的功能就是在屏幕上打印字符串”1 MBR”,背景色为黑色,前景色为绿色。根据注释看看代码意思,不需要太深入理解,后面还会讲到。
将代码文件命名为mbr.S,进入该文件所在位置,输入下面的指令:
nasm -o mbr.bin mbr.S
就会看到当前目录生成了mbr.bin:
然后我们需要将该可执行文件放入启动盘,具体来说是0盘0道1扇区中。
输入下列指令,将mbr.bin写入hd60M.img,hd60M.img是上一节安装bochs那里生成的。
dd if=/your_path/mbr.bin of= /your_path /hd60M.img bs= count= conv=notrunc
进入bochs安装目录,输入bin/bochs -f bochsrc.disk:
bin/bochs -f bochsrc.disk
回车后,输入c继续运行,显示结果如下图:
至此简单的MBR功能就完成了。
《操作系统真象还原》BIOS的更多相关文章
- 戴尔灵越15-5000/3558等系列修改BIOS设置U盘启动
今天在电脑群遇到一个群友的机型是戴尔灵越15-5000,他问我这款机器怎么设置U盘启动. 看到它的BIOS界面之后,我来了点兴趣.. 本文供图:辽宁沈阳-打老虎(921407164) 电脑群:电脑爱好 ...
- Win8换成Win7系统问题小结(修改主板BIOS方法)
问题描述: 笔记本电脑W8系统使用不习惯,想要换成W7系统,但不管是用光盘安装亦或是用U盘安装,在设置系统启动项的时候,选择从光盘启动或从U盘启动,但是回车点了之后没反应. 下面就说说问题的原因及解决 ...
- 获取Linux主机的CPU、内存、主板、BIOS的信息(Centos)
#!/usr/bin/env python #coding:utf-8 import subprocess import re def Cmd_Exec(cmd): ''' 执行获取信息命令 :par ...
- Android Studio :enable vt-x in your bios security,已经打开还是报错的解决方法
quote: For Windows 10: First of all, install the intelhaxm-android.exe located in the folder SDK\ext ...
- Vmware虚拟机进入BIOS方法
在VMware里面如何进入BIOS是个头疼的问题,因为启动界面一闪而过(下面两个图如果不设置bios.bootDelay,基本上很难抓到),即使你狂按F2或ESC键(ESC: 调整启动顺序;F2: 进 ...
- BIOS设置和CMOS设置的区别与联系
BIOS是主板上的一块EPROM或EEPROM芯片,里面装有系统的重要信息和设置系统参数的设置程序(BIOS Setup程序): CMOS是主板上的一块可读写的RAM 芯片,里面装的是关于系统配置的具 ...
- samsung bios configuration怎么设置U盘启动
1.用第三方U盘制作软件制作U盘启动盘,并下载正版系统镜像或纯净版镜像,下载后缀为ISO的镜像文件拷贝到U盘根目录.2.开机按F2键进入BIOS设置.选择BOOT选项—Secure Boot设置为“D ...
- Android Studio的配置问题——Intel HAXM is required to run this AVD,VT-x is disabled in BIOS;
Intel HAXM is required to run this AVD,VT-x is disabled in BIOS;Enable VT-x in your BIOS security se ...
- python在windows下获取cpu、硬盘、bios、主板序列号
测试 此处使用的是wmi库,可以去google里面搜索“python wmi” import os, sysimport timeimport wmi,zlib def get_cpu_info() ...
- BIOS MCSDK 2.0 学习笔记(一)
MCSDK简介 BIOS MCSDK是为TI的高性能多核DSP提供的一套组件,包括: SYS/BIOS实时操作系统 Chip support libraries, drivers, and basic ...
随机推荐
- Centos 下设置静态ip地址
今天小编遇到了需要设置centos(6.4) 下静态ip地址,下面把详细步骤记录下来. 1> 首先打开这个 vi /etc/sysconfig/network-scripts/ifcfg- ...
- qt creator源码全方面分析(2-5)
目录 Creating Wizards in Code 介绍 相关类 IWizardFactory的设置器和获取器 Creating Wizards in Code 介绍 如果基于模板的自定义向导提供 ...
- typeof和类型转换
编程形式 ① 面向过程 ② 面向对象 ③ Js既面向过程又面向对象 typeof(数据) 1)typeof(数据)返回该数据是什么类型的 2)写法: ① typeof(数据) ② typeof 数据 ...
- 实训第八天 有关python orm 的学习记录 常用方法01
沿用第七天的数据库,数据库现在是这样的: 配置好主路由include子路由 子路由引入views 在views页面定义test测试请求如下: def test(request): # 1.all()方 ...
- mysql必知必会--联 结 表
联结 SQL最强大的功能之一就是能在数据检索查询的执行中联结(join) 表.联结是利用SQL的 SELECT 能执行的最重要的操作,很好地理解联结 及其语法是学习SQL的一个极为重要的组成部分 外键 ...
- 消息队列(三)Apache ActiveMQ
在Ubuntu上安装ActiveMQ 系统初始化 $ sudo apt update $ sudo apt dist-upgrade $ sudo apt autoremove $ sudo apt ...
- vue-cli中配置vuex流程和注意事项
本文目录 vue-cli下新建站 配置路由更改HelloWorld.vue组件到新建Home.vue组件 安装vuex 测试是否安装成功vuex一:vue-cli下新建站 a)新建文件夹vuexStu ...
- MySql优化之主从复制
第一步: 配置节点信息(配置完毕重启mysql) 找到my.cnf配置文件,这个文件在etc目录下使用命令修改my.cnf文件 vi /etc/my.cnf 主节点配置: server-id =55 ...
- 8maven配置多个项目之间的依赖
首先创建两个项目进行测试依赖 创建一个HelloWorld2项目,一个HelloWorld类里面有一个sayHello的方法 然后再创建一个HelloWorldTime项目,一个SayHelloWor ...
- char、vchar、nvarchar 的区别
Unicode字符集就是为了解决字符集这种不兼容的问题而产生的,它所有的字符都用两个字节表示,即英文字符也是用两个字节表示 如果还为了这个纠结,就直接看看后面的解说,做决定吧. 一般如果用到中文或者其 ...