一、实验主要内容
1.制作真正的IPL:
关键代码如下:
重点内容:
- JC指令是“jump if carry”的缩写,常用来判断是否产生进位,如果产生进位,则标志位置为1同时跳转到指定地址,否则标志位为0。
- INT 0x13是调用BIOS的0x13号函数,该函数负责磁盘读写方面的工作。不同寄存器对应的功能如下:
AH = 0x02;//读盘模式
AH = 0x03;//写盘模式
AH = 0x04;//校验
AH = 0x0c;//寻道
AL = 处理对象的扇区数,意思就是当前读取的柱面的扇区数,但只能处理连续的扇区。
CH = 柱面号 & 0xff 记录当前读取的柱面号。
CL = 扇区号(0-5位)| (柱面号 & 0x300)>>2;记录当前读取的扇区号。
DH = 磁头号,记录当前磁头的编号。
DL = 驱动区号,用于指定从哪个驱动区软盘读取数据。
ES:BX = 缓冲地址,计算公式如下:ES x 16 + BX
FLACS.CF 状态寄存器,用于记录软盘读取过程中是否发生错误,出现错误则置为1,同时错误号码存入AH寄存器中,否则该状态寄存器为0。
- 进位标志是一个只能存储1位信息的寄存器,若产生进位则值为1,否则为0,可用于判断BIOS调用函数是否出错等等。
- 软盘的结构:软盘由磁头、柱面、扇区构成。其中磁头分为磁头0、磁头1,读取软盘正反面,共有80个柱面,从0开始编号到79。每个柱面包含18个扇区,扇区从1开始编号到18,其中每个扇区的大小为512个字节。读取或写入数据的流程:确定磁头号--->确定柱面号--->锁定扇区号--->读取或写入数据。
- 缓冲地址:表明从磁盘读取出来的数据放在内存中的位置。常用ES:BX的方式来表示地址,在内存中的位置由ES x 16 +BX计算得到,这样可以获得更大的地址空间。
- 段寄存器,当指定内存中的某一个地址时,都必须要指定段寄存器。一般默认将“DS:”作为段寄存器。因此MOV CX,[1234] 其实就是 MOV CX,[DX:1234]。关于段寄存器的一些扩展:
A) 代码段寄存器CS:存放当前正在运行的程序代码所在段的段基值,表示当前使用的指令代码可以从该段寄存器指定的存储器段中取得,相应的偏移值则由IP提供。
B) 数据段寄存器DS:指出当前程序使用的数据所存放段的最低地址,即存放数据段的段基值。
C) 堆栈段寄存器SS:指出当前堆栈的底部地址,即存放堆栈段的段基值。
D)附加段寄存器ES:指出当前程序使用附加数据段的段基址,该段是串操作指令中目的串所在的段。
- DS在使用的时候务必预先指定值为0,否则被指定的地址的值需要加上DS的16倍,否则就会读写到其它地方,如图:
2.试错
关键代码:
重点内容:
- JNC是“jump if not carry”的简写,更前面出现的JC指令相反,JNC是不产生进位的时候则跳转。
- 由于软盘容易出错,因此重新读盘之前都要进行复位处理。也就是上面代码开头的第一部分。
3.读入18个扇区
关键代码:
重点内容:
- 为什么CL从2开始读呢?因为第一个扇区已经作为启动区了。
- JBE指令是“jump if below or equal”的简写,意思就是小于等于则跳转。
- 读入下一个扇区只需要给CL加一即可,SI寄存器用于记录软盘读取出错的次数,大 于5次时调到erro处。
- 一个扇区数512字节,每读取一个扇区则内存地址往后面移动512/16 = 0x20个位置。
4.读入10个柱面
关键代码:
重点内容:
- 读取柱面比读取扇区的代码多了判断柱面数,当柱面数达到十个则停止读取,否则一直循环读取。
- JB指令是“jump if below”,意思是小于的时候跳转。
- CYLS EQU 10 是预先定义CYLS的值为10,就相当于c语言的#define声明一个常量。
5.着手开发操作系统
重点内容:
(1)当向一个软盘保存文件时:文件名会写在0x002600以后的地方,文件的内容会写在0x004200以后的地方。
6.从驱动区执行操作系统
重点内容:程序从启动区开始,把磁盘内容装载到内存的0x8000号地址,那么软盘0x4200处的内容应该位于内存0x8000+0x4200 = 0xc200号地址。
7.确认操作系统执行情况
关键代码:
重点内容:
- ORG指明程序被装载到内存的地址。
显卡中断函数不同的设置对应功能如下:(该函数无返回值)
AH = 0x00;//初始化
AL = 模式:
0x03 :16色字符模式,80x25;
0x12:VGA图形模式,640x480x4位彩色模式,独特的4面存储模式;
0x13:VGA图形模式,320x200x8位彩色模式,调色板模式;
0x6a:扩展VGA图形模式,800x60044位彩色模式,独特的4面存储模式。部分显卡不支持该模式。
本段代码选用的是第三种显示模式。
- 运行结果:make run
成功出现黑屏。
8.32位模式前期准备
关键代码:
重点内容:
- CPU有16位和32位两种模式,16位模式的机器语言只能在16位模式下运行,32位也是如此。
- 32位模式的cpu可以使用的内存容量远远大于1MB,且cpu的自我保护功能可以在32位模式下使用。
- 32位模式下不能调用之前的BIOS功能了,因为它基于16位模式写的。解决办法:切换系统模式。
- 上面的程序在设置画面模式之后,会将画面模式的信息保存在内存中,留起来备用。
- VRAM指的是显卡内存,它的每个地址上都存放了对应画面的每一个像素,利用这个机制可以在画面上绘制五彩缤纷的图案。
- VRAM分布在内存好几个不同的地方,不同的画面模式的像素数也一样。
9.开始导入c语言
关键代码:
重点内容:
- goto指令相当于汇编中的JMP;
- C语言编程机器语言的过程:
- cc1是C编译器,可以将C语言编译成汇编语言。
- gas2nask.exe将gas文件编译成nask文件;
- nask.exe将nask文件编译成obj目标文件;
- obj2bim将obj文件编译成二进制文件,同理其它。
- 一个完整的img文件由多个部分链接而成。
10.实现HLT
关键代码:
重点内容:
- 为了与bootpack.obj链接,该段代码需要编译成二进制文件,因此设置输出模式为:WCOFF模式,同时设定成32位模式。
- 制作nask目标文件,必须设定文件名信息,最后声明函数名,但是需要在函数名前面加上”_”,否则就不能很好地与c语言函数链接。用GLOBAL声明需要链接的函数。
- 最终的c语言程序如图:
二、遇到的问题及解决方法
无。(部分同学可能会出现报Windows ....255号Erro,出现这样的原因是由于最近Windows的更新引起的,解决办法重新替换实验文件就好了)
三、程序设计创新点
尝试着想让黑屏显示一点东西,黑屏的显示通过VRAM,因此向VRAM写入东西,应该就可以显示。尝试过程:首先修改写入VRAM的数据
行后发现仍然是黑屏!
后面查找到第四天有相关内容。在naskfuncs.nas加入以下内容:
原理是将原来的黑像素点变成白的。
同时c语言加入以下内容:
运行结果如图:
示其他的内容,对c语言下的:
这部分内容进行修改即可。