使用的软件与环境:
1、Intel CPU
2、Windows XP
3、NSAM-2.09RC1
4、VMWare 6.5
启动过程概述:
电脑启动时首先运行的是 BIOS 中的固化代码,比如:上电自检等。如果这部分代码没有问题,BIOS 就会按照去寻找启动设备(软盘、硬盘、光驱等),设备的寻找顺序是由用户在 BIOS 中定义的。这块有个小问题,如何判断一个设备是启动设备?在安装系统时,我们将系统盘放入光驱,可以进行引导,但不是每张光盘都可以引导系统。BIOS 判断一个设备是否具有引导功能的依据是:设备的第 1 Sector 的最后两个字节是 0xAA55;如果满足上述条件 BIOS 就会将第一个 Sector 内的数据(512K)加载到内存的 0x7C00,然后从这个位置开始执行。注意:这是还是在 16 位的实模式下。
电脑上电后控制权的转移顺序为:BIOS –>0x7C00 处代码。
上面描述的 BIOS 定义的一种机制,我没有去寻找具体的原因,感兴趣的同学可以 Google 下原因。
Hello Word:
在了解了上述过程后我们来写一段小的汇编程序(floppy.asm):
[BITS 16];指定位模式 [ORG 0x7C00];指定加载的起始地址 ;定义一个字符串 MsgString db 'Hello World!', 13, 10, 0 ;无条件跳转 JMP _start _start: ;将 AX 清零 XOR AX, AX ;将 DS 清零,下面要用到 SI,SI 寻址的基址为 DS MOV DS, AX ;将字符串的起始地址加载到 SI 中便于后面循环输出 MOV SI, MsgString CALL next_character JMP $ ;调用 BIOS 中断进行字符输出,中断就相当于 Windows 的 API,参数放在寄存器中,关于中断调用的具体信息可以查阅相关文档,BIOS 中断号:0x10 PrintCharacter: MOV AH, 0x0E MOV BH, 0x00 MOV BL, 0x07 INT 0x10 RET PrintString: next_character: ;SI 类似于 C 中的指针,[SI] 类似于 *SI MOV AL, [SI] INC SI ;或运算,影响 0 标志位,或运算的结果为假的条件是:两个操作数都为 0,此处是为了判断是否到了字符串结尾 OR AL, AL JZ exit_function CALL PrintCharacter JMP next_character exit_function: RET ;填充其它空间,$ 代表当前位置的偏移量 $$代表程序起始位置的偏移量,510 + 0xAA + 0x55 = 512 TIMES 510 - ($ - $$) db 0 DW 0xAA55
然后用 NASM 编译上述程序:
nasm floppy.asm -f bin -o floppy.img
PS:
为了便于 NASM 的使用我是这样设置的:
创建一个启动 NASM 的批处理文件:
d: cd D:/nasm-2.09rc1 PATH=PATH;D:/nasm-2.09rc1 cls
然后仿照 VS 命令行的启动方式启动它:创建一个快捷方式,目标为:C:/WINDOWS/system32/cmd.exe /E:ON /K D:/nasm-2.09rc1/setup.bat,起始位置为:D:/nasm-2.09rc1
在 VMWare 中使用程序:
创建一个 DOS 虚拟机:
1、开始新建虚拟机向导:
2、暂不安装系统:
3、选择其它系统:
4、设置名称与选择存储位置:
5、将硬盘的大小修改为最少:
6、在这个界面上点击配置硬件:
7、卸载掉光驱:
8、 加载软驱(指定从镜像文件加载,选择上面生成的 floppy.img):
9、卸载网络:
10、卸载声卡:
11、虚拟机配置结果:
12、启动引导程序运行结果:
进一步:
如果想进一步做实验的话,可以试着用 BIOS 中断,将引导程序写入硬盘,然后用硬盘启动输出 “Hello World!”