1.4.2 Hello China的开发环境
操作系统的开发涉及各种各样的功能模块,比如引导功能模块、初始化功能模块、硬件驱动功能模块及系统核心等,这些功能模块很难使用同一个开发环境进行代码的编译和编写,因此,在Hello China的开发过程中,针对不同的功能模块,使用了不同的开发环境,主要有:
● 针对引导功能和硬件驱动程序(比如键盘驱动程序和字符显示驱动程序)采用汇编语言编写,使用NASM编译器编译;
● 针对操作系统核心,为了提高移植性和开发效率,采用C语言编写,采用Microsoft Visual C++作为代码的编译和编写环境;
● 由于上述开发环境最终形成的目标格式有时与预期的格式不一致,于是采用Microsoft Visual C++编写了目标处理工具,这套工具对上述编译器形成的目标文件进行进一步处理,形成计算机可以直接加载并运行的二进制模块。
Hello China在开发过程中涉及的开发环境和开发工具比较多,但该操作系统的核心代码,却完全是使用C语言编写的,具备良好的可移植性,其他非C语言编写的代码数量非常少,相对来说是微不足道的,根据粗略统计,非C语言编写的代码数量是总体代码数量的5%左右。
1.开发环境的搭建
在Hello China的开发过程中,采用NASM和Visual C++6.0等工具完成了不同操作系统模块的开发和编译、连接。其中,NASM完成汇编语言实现的模块的编译和连接,其他由C语言完成的模块,则由VC编译和连接。
(1)NASM的使用
在当前版本的Hello China的实现中,汇编语言实现的模块都按照纯二进制格式进行编译,即编译的可执行映像的结果与汇编语言源文件的逻辑完全一致,没有任何编译器附加的头信息。这样的纯二进制模块,可通过下列步骤开发完成:
① 采用任何一个文本编辑器(比如DOS操作系统下的edit)编辑汇编语言源程序,并保存为.ASM文件;
② 采用NASM程序编译上述文件,格式为:nasm-f bin xxx.asm-o xxx.bin ,其中xxx.asm是待编译的汇编语言源文件,xxx.bin是编译的结果文件。
(2)Visual C++的使用
Hello China的绝大部分核心功能是采用C语言编写完成的,采用Visual C++6.0作为编译连接工具。下列步骤描述了Hello China开发过程中开发环境的搭建。
① 创建一个DLL工程。
一般情况下,VC可以生成PE格式的可执行文件、DLL文件等文件类型,但可执行文件不太适合OS映像,因为编译器在编译的时候,会自动在映像文件中加入一些其他代码,比如C运行期库的初始化代码等,这样会导致映像文件的体积变大。而DLL格式的文件则不会有这个问题,因此,建议从DLL开始来建立OS映像。
在Microsoft Visual C++中,按照图1-5所示创建一个DLL工程。
图1-5 创建一个DLL工程
② 设置项目编译与连接选项:
一般情况下,需要对创建的工程设定如下编译连接选项:
● 对齐方式,在项目选项中,添加/ALIGN:XXXX选项,告诉连接器如何处理目标文件映像在内存中的对齐方式,一般情况下,需要设置为跟目标文件在磁盘存储时的对齐方式一致,根据经验设置为16是可以正常工作的;
● 设置基址选项,修改默认情况下的加载地址,比如目标文件在我们自己的操作系统中从0x00100000(1MB)处开始加载,则在连接工程选项里面添加/BASE:0x00100000选项;
● 设置入口地址,如果不设置入口地址,编译器会选择默认的函数作为入口,比如针对可执行文件是WinMain或main,针对动态链接库是DllMain或EntryPoint,等等,采用默认的入口地址,有时候不能正确地控制映像文件的行为,还可能导致映像文件尺寸变大,因为编译器可能在映像文件中插入一些其他的代码。因此,建议手工设置入口地址。比如,假设我们的操作系统映像的入口地址是__init函数,则需要设定如下选项:/entry:?__init@@YAXXZ,其中,?__init@@YAXXZ是__init函数被处理后的内部标号,因为Visual C++采用了C++的名字处理模式,而C++支持重载机制,所以编译器可能把原始的函数名变换成内部唯一的标号表示形式。关于如何确定一个函数的内部标号表示,请参考附录A。
上述所有的设置,请参考图1-6所示。
图1-6 设置编译、链接选项
在Visual C++6.0中,上述对话框可以从“project->setting…”打开,需要注意的是,打开时,是针对DEBUG版本设定的,请一定选择Release版本进行设定(图中圆圈中注明的地方)。
上述步骤完成之后,集成开发环境就设置完毕了,剩下的工作就是直接在该工程中添加C语言源文件。
2.编译后模块的进一步处理
上述开发环境搭建完毕之后,就可以在该开发环境下进行操作系统的开发工作了。其中,由NASM编译的二进制映像直接可以加载到内存中运行。但由Visual C++编译的二进制模块却是一个Windows操作系统下的DLL文件,是无法直接加载到内存中运行的,这时候需要对其进行一个预处理。预处理的目的以及预处理方法的实现机制,请参考附录A,下面仅给出预处理的操作步骤:
① 把Visual C++编译连接而成的目标文件(Release版本的DLL文件)复制到与process.exe相同的目录下,其中,process.exe就是预处理程序;
② 直接运行process.exe程序修改上述DLL文件,修改之后,上述DLL模块就可以直接加载到内存中运行了。