《操作系统真象还原》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 ...
随机推荐
- WebAPI 微信小程序的授权登录以及实现
这个星期最开始 ,老大扔了2个任务过来,这个是其中之一.下面直接说步骤: 1. 查阅微信开发文档 https://developers.weixin.qq.com/miniprogram/dev/ ...
- D语言-随机数游戏
由于不会D语言的随机数,干脆core.stdc.stdlib调用stdlib.h 这里mark一下,类型转换是cast(D语言类型) NULL不能用,要用null import std.stdio; ...
- Transformer 详解
感谢:https://www.jianshu.com/p/04b6dd396d62 Transformer模型由<Attention is all your need>论文中提出,在seq ...
- ps查看资源消耗
- light oj 1095 - Arrange the Numbers排列组合(错排列)
1095 - Arrange the Numbers Consider this sequence {1, 2, 3 ... N}, as an initial sequence of first N ...
- (数据科学学习手札78)基于geopandas的空间数据分析——基础可视化
本文对应代码和数据已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 通过前面的文章,我们已经对geopanda ...
- 初识matlab
1 matlab概貌 MATLAB是MATrix LABoratory(矩阵实验室)的缩写,是一款由美国The MathWorks公司出品的商业数学软件.matlab是一种用于算法开发.数据可视化.数 ...
- 7.Android-压力测试、单元测试、日志猫使用
1.压力测试monkey 通过cmd输入下面命令: adb shell monkey -p com.example.phonecall --ignore-crashes --ignore-timeou ...
- jni和线程
JNI官方规范中文版——在程序中集成JVM需要注意的JNI特征 翻译 我们已经讨论了JNI在写本地代码和向本地应用程序中集成JVM时的特征.本章接下来的部分分介绍其它的JNI特征. 8.1 JNI和线 ...
- .netcore 3.1高性能微服务架构:封装调用外部服务的接口方法--HttpClient客户端思路分析
众所周知,微服务架构是由一众微服务组成,项目中调用其他微服务接口更是常见的操作.为了便于调用外部接口,我们的常用思路一般都是封装一个外部接口的客户端,使用时候直接调用相应的方法.webservice或 ...