1.1准备工作
- 硬件
- 计算机Windows
- 一张空白软盘
- 软件
- 汇编编译器NASM。最新版此链接http://sourceforge.net/projects/nasm
- (为啥NASM,而不MASM或TASM?这一点后面有解释。)
- 软盘绝对扇区读写工具
- 如本书附赠光盘中的FloppyWriter.exe
- Floppy Disk是PC中最早用的可移介质。
- 软盘的读写通过软盘驱动器完成
- 软盘驱动器设计能接收可移动式软盘,
- 常用:容量为1.44MB的3.5英寸
- 如本书附赠光盘中的FloppyWriter.exe
1.2 10分钟完成的OS
- 一个“OS”只有20行
org 07c00h ;高速编译器程序加载到7c00处
mov ax, cs
mov ds, ax
mov es, ax
call DispStr ;调用显示字符串例程
jmp $ ;无线循环
DispStr:
mov ax, BootMessage
mov bp, ax
mov cx, 16
mov ax, 01301h; ah=13,a1 = 01h
mov bx, 000ch ; 页号为0(bh = 0) 黑底红字 (b1 = 0Ch,高亮)
mov dl, 0
int 10h ; 10h号中断
ret
BootMessage: db "Hello, OS world!"
times 510-($-$$) db 0;填充剩下的空间。使生成的二进制代码恰好为512字节
dw 0xaa55 ;结束标志
我估计第一个7c00,第二个是7c02…
- 用NASM编译下
- nasm boot.asm -o boot.bin
- 得到一个512B的boot.bin
- 用软盘绝对扇区读写工具将这个文件写到空白软盘的第一个扇区
- 第一个OS已完成
- 这张软盘已是一张引导盘
- 把它放到你的软驱中重新启动计算机,从软盘引导,你看到了什么?
- 计算机显示出红色的“ Hello, OS world!”,你的“操作系统”在运行
- 如果用 Virtual PC的话(下文中将会有关于 Virtual PC的详细介绍),你应该能看到图1-1
- 你已经制作了一个可以引导的软盘了!
1.3 Boot Sector
- 你刚刚所完成的并不是一个完整的OS,
- 仅是一个最最简单的引导扇区( Boot Sector)。
- 它是直接在裸机上运行的,不依赖于任何其他软件,
- 这和我们平时所编写的应用软件有本质区别。
- 它不是操作系统,但已经具备了操作系统的一个特性
- 计算机电源打开时,它会先加电自检(POST),然后寻找启动盘
- 如果是选择从软盘启动,
- 计算机就检查软盘的0面0磁道1扇区
- 如果发现它以0xAA55(把此扇区看做字符数组sector,相当于sector[510]=0x55,且 sector[511]=0xAA)结束,则BIOS认为它是一个引导扇区,也就是Boot Sector。
- 一个正确的Boot Sector除了以OxAA55结束外,
- 还应包含一段少于512B的执行码
- 一且BIOS发现了Boot Sector,就会将这512B的内容装载到内存的0000:7c00处,然后跳到0000:7c00处将控制权彻底交给这段引导代码
- 到此计算机不再由BIOS中固有的程序来控制,
- 而变成由操作系统的一部分来控制
- 第一行会出现org 07c00
- 这行代码就是告诉编译器,
- 这段程序要被加载到内存偏移地址7c00处
1.4代码解释
- 主体框架只有5行(从第2行到第6行),调用了一个显示字符串的子程序。
- 2、3、4行是3个mov指令,使ds和es两个段寄存器指向与cs相同的段,以便在以后数据操作时能定位到正确的位置。
- 第5行调用子程序显示字符串,然后jmp $让程序无限循环
-
NASM中,
-
不被方括号括起来的标签或变量名都被认为是地址,
-
访问标签中的内容必须使用[]。
-
mov ax, Bootmessage
-
把“ Hello, OS world!”这个字符串的首地址传给ax。
-
如果有:
foo dw 1 -
mov ax,foo将把foo的地址传给ax,
-
mov bx,[foo]将把bx的值赋为1。
-
NASM中,变量和标签是一样的
- foo dw 1foo: dw 1
- Offset这个关键字在NASM也是不需要的。
- 不加方括号时表示的就是 Offset
- 这是NASM的一大优点,要地址就不加方括号,也不必额外地用什么 Offset
- 想要访问地址中的内容就必须加方括号。
- $表示当前行被汇编后的地址。
- 把刚刚生成的二进制代码文件反汇编
- 打开 disboot.asm,
- 发现
00007C09 EBFE jmp short 0x7c09 - $原来就是0x7c09
- $$表示
- 一个(secton)的开始处被汇编后的地址。
- 我们的程序只有1个节,所以,实际上就表示程序被编译后的开始地址,也就是0x7c00。
- $-$$表示本行距离程序开始处的相对距离。
- times 510-($-$$) db 0表示将0这个字节重复遍
- 也就是在剩下的空间中不停地填充0,直到程序有510B
1.5水画下的冰山
- Boot Sector为例,想一个办法,让它调试起来容易
- 只要把一行改成“org 0100h”就可编译成一个.COM让它在DOS下运行
- nasm boot.asm -o boot.com
- 一个易于执行和调试的Boot Sector就制作完毕
- 调试COM文件可能让你仿佛一下子回到20世纪
- Turbo Debugger是不错的调试工具,“图形化”界面,全屏操作,用起来感觉和一个“严重”精简后的 Windows差不多
- NASM给我们提供了预编译宏,
- 把原来的“org 07c00h”一行变成许多行
- 如果想要调试,就让第一行有效,想要做 Boot Sector时,将它注释掉就可