先说几句
这么长时间没写文章了,这段时间一直在研究汇编和DOS系统。
自己做了一个系统(不完全是)的MBR,打算把代码发出来。1
什么是最小操作系统
什么是最小的计算机操作系统?先不提“操作系统”这个高大上的概念,我的理解它就是能让一台裸机“跑”起来的程序集合。现在给你一台最新的64bit个人计算机,没有安装任何的系统或软件,你能用什么方法让它跑起来?这个就必须从计算机的启动过程开始谈起:
-
BIOS: 按下计算机的开关之后,硬件设备会将寄存器CS设置为0xF000,寄存器IP设置为0xFFF0,这样计算机就从地址0xFFFF0 (CS*10H+IP)开始执行程序,这就是BIOS程序。BIOS程序会进行硬件自检即POST过程,如果没有问题屏幕会显示内存,硬盘,CPU等配置信息。这个过程完成之后,BIOS就会去读取下一个设备的程序来启动计算机,那么下一个设备是什么?你应该记得以前每次重新安装操作系统的时候,都会有一个“Boot Device Priority”的选项,这个选项有软盘、光盘、U盘等存储介质,这个选项就决定了你想让计算机从哪个设备上启动。
-
主引导记录(MBR):无论你上面选择的是哪一种介质,计算机接下来要做的事情都是一样的:计算机要读取这个设备的第一个扇区共512个字节的数据。如果这个扇区的最后两个字节内容是0x55和0xAA,OK,那就表明这就是用户想用它来启动计算机的设备。否则BIOS会把控制权交给启动顺序中第二个设备,而这512个字节也叫作主引导记录(Master Boot Record)。找到启动设备之后,接下来就有一个很重要的规矩:那就是计算机要把这512个字节读取到内存的0x7C00这个地址,并从这个地址开始逐条运行程序。
对,你没有看错,现在你的计算机就已经启动起来了。既然裸机已经跑起来了,那么这个512字节的主引导记录(MBR)就可以叫做—最小操作系统。
- 为什么是0x7C00?
显然0x7C00是计算机的第一个重要魔数,BIOS为什么会将MBR装载到这个内存地址?这就必须从计算机制造者IBM说起。
0x7C00的前身其实是0x200,当时操作系统是在1980年出现的SCP的"86-DOS"。为什么是0x200?因为这个系统是从0x400开始放置的,而内存空间0x200-0x3FF处于中断向量的区0x00-0x3FF的末端保留空间并没有用到,所以就刚好利用了这个512B的“缝隙”地址。
0x7cC0的出现是在1981年的IBM PC机5150上,一个叫“大卫XX”的开发团队成员定下的,这个事情和INTEL公司以及微软公司没有任何关系。
那怎么定下是0x7C00这个值的呢?那是为了尽量让最多的连续内存空间分配给操作系统,选择把MBR放在内存的最高端方向、另外还需要预留512B的堆栈/数据空间,因此从内存的最高处倒数过来,就计算出了MBR的存放位置:
0x7FFF(5150机器总内存空间32KB)-512B(堆栈/数据空间)-0x7FFF(5150机器总内存空间32KB)-512B(堆栈/数据空间)-512B(MBR空间)=0x7C00。
看一下最终的内存分布图就更清楚明白:
+--------------------- 0x0
| Interrupts vectors
+--------------------- 0x400
| BIOS data area
+--------------------- 0x5??
| OS load area
+--------------------- 0x7C00
| Boot sector
+--------------------- 0x7E00
| Boot data/stack
+--------------------- 0x7FFF
| (not used)
+--------------------- (...)
同时还指出:一旦计算机启动起来之后,MBR区、堆栈/数据区就不再需要了,因此我们完全还可以再次回收利用:0x7C00—0x7FFF之间处于32KB最后的1024B空间,这样无疑为操作系统又扩充了可用空间。这就更加说明MBR需要放置在内存高端方向的原因:因为如果放在内存的低端方向,这部分回收的空间就很难再利用起来,原因在于程序一般都是往内存地址的增长方向向上发展的。难以想象在计算机硬件匮乏的年代,那些设计者大师真是绞尽了脑汁。
代码
代码注释用的是英文,并且是我自己写的2
;+---------------------------------------------+
;| The Smallest System's Code |
;| Version 1.00 |
;| By Robert Ryan |
;+---------------------------------------------+
;----------------------REV----------------------
;0.30
;Split string and '$'.
;0.20b
;Standardized the code.
;0.20a
;Added 'JMP START' command.
;0.10
;Added ORG command and standardized the code.
;-----------------------------------------------
[ORG 7C00H] ;the master boot record is start at 0x7C00
JMP START
MSG: DB 'Hello world!', '$' ;define the message
START:
MOV AX, 7C00H
MOV DS, AX
MOV SI, MSG ;move the message into the SI register
CALL BOOT ;display string
JMP $ ;block the code
BOOT:
MOV AL, [SI]
CMP AL, '$'
JE DONE
MOV AH, 0Eh
INT 10h
INC SI
JMP BOOT
DONE:
RET
TIMES 510-($-$$) DB 0 ;fill 00
DB 55H, AAH ;The last two bytes of the MBR must be 55 AA
魔改
可以改成这样:
;+---------------------------------------------+
;| The Smallest System's Code |
;| Version 1.00 |
;| By Robert Ryan |
;+---------------------------------------------+
;----------------------REV----------------------
;0.30
;Split string and '$'.
;0.20b
;Standardized the code.
;0.20a
;Added 'JMP START' command.
;0.10
;Added ORG command and standardized the code.
;-----------------------------------------------
[ORG 7C00H] ;the master boot record is start at 0x7C00
JMP START
MSG: DB 'Please wait...', '$' ;define the message
START:
MOV AX, 7C00H
MOV DS, AX
MOV SI, MSG ;move the message into the SI register
CALL BOOT ;display string
JMP $ ;block the code
BOOT:
MOV AL, [SI]
CMP AL, '$'
JE DONE
MOV AH, 0Eh
INT 10h
INC SI
JMP BOOT
DONE:
RET
TIMES 510-($-$$) DB 0 ;fill 00
DB 55H, AAH ;The last two bytes of the MBR must be 55 AA
看明白了没?
这个代码运行后屏幕上会显示Please wait...
,让你等,可是你就是等100年也启动不了系统,非常适合整蛊朋友
总结
我们通过一步步的引导,就已经完成计算机最小操作系统的制作。可以看出,每一步都在进步,它其实就是一个离计算机底层越来越远,而离用户越来越近的过程,这就是汇编语言的发明初衷。按这样的方向走下去,用户就一定能很好的控制计算机来实现自己的应用目标。