看了数次的大灰狼之后,终于可以将之与orange's联系起来了,大感兴奋。可惜在兴奋之中写的博客被自己不小心手贱放弃掉了。。。只得半个月后再来撰写。
由于之前盲目跟着orange‘s果断换了linux后,其中的很多程序实现的debug又在无数次度娘帮助下完善解决,因此涉及解决问题的部分较少,主要还是理论的学习笔记总结。之后应该及时写下技术的debug过程,并持之以恒。
一、计算机加电过程
要学习启动程序,首先要了解计算机的启动过程,大灰狼讲得非常之清楚,计算机的加电过程如下:
Step1:按下开机按钮后,电信号传送至BIOS。
Step2:BIOS获得电信号后启动自动检查程序,检查周边设备是否通电完毕。
Step3:检查后自检程序将控制权交还BIOS,BIOS读取引导驱动器中的启动程序。
而系统中的启动程序也就是存放在内存中的,BIOS在最初对内存就有一个分配,其分配情况如下:
0x00000-0x003FF 终端向量表
0x00400-0x004FF BIOS数据区
0x00500-0x07BFF 自由内存区(内存空白,无分配)
0x07C00-0x07DFF 引导程序加载区(512字节)
0x07E00-0x9FFFF 自由内存区
0xA0000-0xBFFFF 显示内存区(显示屏幕上出现的字符)
0xC0000-0xFFFFF 中断处理程序(BIOS自己的中断)
在系统加电的最初,这1MB内存就在BIOS准备好。
二、引导程序
BIOS将检查启动磁盘的第一个扇区512字节载入内存,放在内存的0x07C00-0x07DFF处
若第一扇区最后两个字节是55AA(计算机硬件规定),那么它就是一个引导程序。
因此,计算机引导程序有如下特点:1,大小为512字节
2,结尾必须是55AA
3,在启动磁盘的第一扇区
而启动磁盘呢,也就是BIOS界面需要我们选择的启动区。
三、引导程序
ORG 07c00h
MOV AX,CS
MOV DS,AX
MOV ES,AX
CALL DispStr
JMP $
ORG:将程序加载到07C00处。
2、3、4行使得DS和ES两个段寄存器指向与CS相同的段,从而实现正确的数据与代码的关联。
DispStr是显示字符串的子程序。
而$则是当前指令的指令地址,一直跳转到当前指令也就是一直在此进行循环,也就是此处进行无线循环。
DispStr:
MOV AX,BootMessege
MOV BP,AX
MOV CX,16
MOV AX,01301h
MOV BX,000ch
MOV DL,0
INT 10h
RET
将字符串的内容拷贝到BP。
CX中存放的则是循环变量,由于"Hello, OS world!"共有16个字符,因此晕换变量为16。
AX中存放的则是中断程序下的子程序内容,查找BIOS功能调用表得知。
而BX则存放的是显示的页号00和字符串属性0Ch。
最后调用10号中断进行字符串显示,也就是说,10号中断会自动读取AX的内容获取中端子程序,确定要执行的是字符串显示的子程序。然后再读取BX和BP寄存器获取要显示的内容和属性。将其显示到屏幕上。
BootMessege: DB "Hello, OS world!"
times 510-($-$$) DB 0
DW 0xaa55
最后是字符串的初始化。
而$$则表示的是指令所在的开始位置。由于总共我们需要写入的为512字节,而程序执行到这一行时偏移地址是$,因此$-$$也就是之前所有的程序所占用的前面的空间,因此剩下的空间大小为512-($-$$)。但是由于最后我们还需要写入2个字节的内容,因此我们需要填充为0的空间为510-($-$$)。
最后用字填充语句将AA55填充至最后两个字节,完成启动程序的编写。
在虚拟机的执行结果如下: