骆驼空间站

简单就是美,不受任何商业的驱使,我们有自己的圈子

博客园 首页 新随笔 联系 订阅 管理
参考:
http://www.oldlinux.org (对老版本 Linux 的研究,站长的 <Linux 内核完全注释> 一书很有帮助)
http://www.kernel.org ( Linux 内核源代码各个版本和一些工具、文档下载的官网)
http://www.gnu.org (下面用到的 GNU 的工具系列的手册,可以在这找到的)
http://ftp.gnu.org/gnu ( GNU 的工具下载 URL)  
http://bochs.sourceforge.net (一种虚拟机用他来运行编出来的 Linux)
http://www.google.com  (TMD 再不行就问他了)
 
以下为 Linux 0.11 版本的源代码下载 URL:
 
编译环境的准备:
首先需要建立编译环境,会用到的主要工具基本有:
 1. as86 (Assembler for 8086..80386 processors, 8086 汇编编译器)
 2. ld86 (Linker for as86, as86 的连接器)
 3. as (portable GNU assembler, GNU 汇编编译器,区别于上面的 as86,这个要用 AT&T 汇编语法)
 4. ld (the GNU linker, GNU 连接器)
 5. gcc (GNU project C and C++ compiler, GNU 的 C/C++ 编译器)
 6. cpp (The C Preprocessor, C 语言的预编译器)
 7. ar (create, modify, and extract from archives, 归档工具)
 8. make (Makefile 文件的解释工具)
 9. dd (convert and copy a file, 文件复制的一种工具)
10. tar  (功能很多这里应该只用到了他文件打包,解包的功能)
 
源代码的修改和编译:
由于历史悠久, Linux 0.11 代码在不做修改的情况下,很难在现在的环境下这接编译通过(除非你能的到 10 几年前 Linus 用的那个版本的 gcc 什么的)。所以要对代码作少量修改(说说是少量花了好几小时的,主要是一上来不熟 gcc 的内嵌汇编)。
 
我修改后可以顺利编译的源代码 http://lexx.51.net/oldlinux/mod-linux-0.11.tar.gz
(出错不负任何责任,编译环境 gcc-3.2 as-2.13 as86-0.16 ld-2.13 ld86-0.16 ar-2.13)
 
改动主要有这几个方面:
1. Makefile 的修改, 把所有 Makefile 里的 gas 换成 as, gld 换成 ld.(as 和 ld 这两个兄弟以前叫 gas 和 gld 的)
 
2. Makefile 的修改, 把所有 Makefile 里 CFLAGS 里面的 -fcombine-regs 和 -mstring-insns (-fcombine-regs 据说是老版 gcc 特有的,至于 -mstring-insns 更牛 Linus 为某种目的为 gcc 加出来的,实在是佩服的五体投地)
 
3. Makefile 的修改, 把所有 Makefile 里 "$(AS) -c -o $*.o $<" 这句中的 -c 去掉 (现代版的 as 已经不要 -c 这个选项了)
 
4. 8086 汇编代码修改, 把所有用 as86 编译的 .s 文件中的 C 语言注释,换成 ! (感叹号)方式的,汇编注释方式. (因为现在的 as86 不兼容 C 风格注释了)
 
5. 汇编代码修改, 把所有 .align 语句后面的数字变成以他为幂的 2 的次方.比如原来 .align 3 就应该变为 .align 8 (因为语法变了,以前写的是 2 的次方,现在直接写几了)
 
6. 汇编代码修改, 把所有在汇编中调用 C 函数或者变量的前导下划线去掉.同时把汇编中输出给 C 函数使用的变量和函数的前导下划线去掉.(举例说以前 C 里面有一个函数叫 strcpy 如果在以前汇编里面要调用就要写成 call _strcpy,但现在则可以写成 call strcpy 了)
 
7. 内嵌汇编代码修改,主要是要去掉人工 cpu 寄存器的修改.这部分工作量比较大.这个很难说明,举两个例子
   1) register int __res __asm__("ax"); /* 原来的内嵌需要人工制定用那个寄存器 */
       register int __res;               /* 现在的编译器不用了所以就去掉 */
 
   2) __asm__("cld\n\t"                      /* 原来的最后有对修改寄存器的说明 */
                    "rep\n\t"
                    "stosb"
                    ::"a" (c),"D" (s),"c" (count)
                    :"cx","di");
 
       __asm__("cld\n\t"                      /* 现在的编译器不用了所以就去掉 */
                    "rep\n\t"
                    "stosb"
                    ::"a" (c),"D" (s),"c" (count));
 
一些疑惑的地方修改(为了编译同过我改了,不过不知道为什么):
1. panic 函数的声明. panic 函数在两处有声明分别是 include/linux/sched.h 里声明为 extern void panic(const char * str);. 另一处 include/linux/kernel.h 里声明为 volatile void panic(const char * str);. kernel.h 里多了 volatile 描述符,所以我的编译器提醒我类型冲突.后来在 sched.h 里同样添加 volatile 描述符才通过.
 
2. kernel/chr_drv/keyboard.S 的 47 行,为:
      xorl %al,%al  /* %eax is scan code */
可是按照语法来说明显是 xorb %al,%al. (会有这么明显得错误吗?一直搞不懂)
 
3. include/string.h 里面的 memcpy 函数无论如何修改 (去掉修改寄存器的说明,去掉 inline 描述符等)在调用出都会编译错误,后来把 memcpy 的实现直接放到了调用出(总共 4 个地方)才得以通过,不过心有余悸好像会错的.
 
4. tools/build.c 的修改,在最后的 build 工具中有一段对 system 文件的验证,就是指 build.c 的第 158 行,在我这永远通不过,我想可能是因为 gcc 版本变了的原因,暂时把它去掉了,不过心有余悸好像会错的.
 
5. build 参数的修改,build 参数的最后一个指定一个根设备,我把它改成了空使 build 工具使用默认的设备号,不过心有余悸好像会错的.

如果一切都顺利修改完后再 make 一遍就应该得到 Image 文件了
 
节外生枝的问题:
1号问题: AT&T 汇编语法,由于以前学校教的是 Intel 汇编所以 AT&T 和 GCC 内嵌的 AT&T 看得真是头晕
2号问题: 就是我之前描述的一些心有余悸的修改
最大问题: 把我现在的 Image 再虚拟机(决定是 Bochs)上运行出来
posted on 2006-11-15 13:39  骆驼SPACE  阅读(2980)  评论(1编辑  收藏  举报