免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
123下一页
最近访问板块 发新帖
查看: 11211 | 回复: 24
打印 上一主题 下一主题

简单的说说学习引导的动力! [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2005-12-16 17:15 |只看该作者 |倒序浏览
首先要说的就是!这个是我写给我的一个业余的小组的新组员的,如果有什么不对的地方希望大家多多指点!因为是菜鸟,可能会有很多不对的地方!前辈们不要笑偶,指点指点,谢谢!



正文:

首先说一说如何对计算机接近硬件层进行学习!首先要有一种好问的思想,也就是说要经常问为什么!比如我们写一段代码:

  1. #include<stdio.h>
  2. int main(void)
  3. {
  4.         printf(“hello world!”);
  5. }
复制代码

不要看上面是一个简简单单的hello world!的输出语句!如果仔细的朋友,会发现,就这么简单的一句hello world会站用我们的1k的空间!为什么会这样呢?这么几行就站用了1k的空间。
因为我们调用了一个头文件<stdio.h>里的一个函数printf。也许有的人学了很久的c语言,用了数以万次的printf函数!但是这个printf函数是怎么来的呢?能否自己写出来一个printf函数呢?那么printf函数里面会不会有去调用别的函数了呢?这个应该很少有人去问了,因为目前大多数写代码的人都是因为写代码赚钱多才加入这个行列的!很少有人愿意去想这些了,只要有现成的东西,拿来用就是了,这种精神,不适合学底层的开发!因为想要把底层学好,是必须要知道很多的!就比如printf函数!在操作系统诞生不久后,当时还没有一个编译器呢,那时候有printf函数?就像是我们的dos里面常用的中断int 21h一样!我们在dos里的中断号是21h那么在Linux里呢?应该不是21h了吧?那如果没有操作系统时,会不会还是21h呢?答案是肯定不会是21的,是intel写好的,而intel公司开发的芯片是硬件,不在我们的研究之内,就像是我们的操作系统为什么开机上电,自检后会把引导加载在内存的07c00处呢?这个是开发硬件的时候规定的!非我们可以改变的!这种硬件是怎么被开发出来的呢?当然是数字电路,就我所知道的数字电路设计的语言,有一个叫VHDL的语言!这个语言可以设计出一个像CPU一样的芯片!想在以后开发硬件的朋友可以看一看!
要以敢兴趣的态度去学习,不应该被钱所迷惑!是!做软件开发赚钱,但是再赚钱也没有去中关村当妓男或者当妓女赚钱,为什么不去当妓男或者妓女呢?既然做了,就应该喜欢他,就应该对他敢兴趣。比如我,我之所以想去做底层开发,完全是因为我对这个感兴趣!在两年前我用VB写软件的时候,记得当时我根本不知道button是怎么被做出来的,于是不久后我慢慢的就开始去对button产生好奇感,想知道他是怎么来的,后来听说用c语言可以画出来,那怎么画呢?在Turbo C里有一个头文件叫graphics.h,这个头文件里有很多作图的函数,比如circle();是用来画圆的,画出来一个红色的圆之后很开心,后来又试着用C语言编写一个动态的可以流动的字体,也很轻松的做出来了,用的是delay();函数和printf函数和几个颜色的枚举变量,这样,我就先告落了一段时间。当然学习是没有止境的,对于喜欢问为什么的我,这点小成就哪能满足我?我开始问自己,问别人,delay函数是怎么来的呢?printf函数是怎么来的呢?我就不断的去琢磨这么几个函数,经过一段时间的学习,和朋友的不断的提醒下,我知道printf函数是怎么来的了,原来printf函数也是通过调用几个函数来实现的,代码如下:
  1. #include <stddef.h>
  2. #include <stdarg.h>
  3. static char printbuf[1024];
  4. static int printf(const char *fmt, ...)
  5. {
  6.         va_list args;
  7.         int i;
  8.         va_start(args, fmt);
  9.         write(1,printbuf,i=vsprintf(printbuf, fmt, args));
  10.         va_end(args);
  11.         return i;
  12. }
复制代码

这样就把printf函数给写出来了,那么可以看到,printf函数里调用了两个函数,一个vsprintf函数,一个write函数,其实write函数是一个系统调用函数,vsprintf函数代码如下:
  1. int vsprintf(char *buf, const char *fmt, va_list args)
  2. {
  3.         int len;
  4.         int i;
  5.         char * str;
  6.         char *s;
  7.         int *ip;

  8.         int flags;                /* flags to number() */

  9.         int field_width;        /* width of output field */
  10.         int precision;                /* min. # of digits for integers; max
  11.                                    number of chars for from string */
  12.         int qualifier;                /* 'h', 'l', or 'L' for integer fields */

  13.         for (str=buf ; *fmt ; ++fmt) {
  14.                 if (*fmt != '%') {
  15.                         *str++ = *fmt;
  16.                         continue;
  17.                 }
  18.                        
  19.                 /* process flags */
  20.                 flags = 0;
  21.                 repeat:
  22.                         ++fmt;                /* this also skips first '%' */
  23.                         switch (*fmt) {
  24.                                 case '-': flags |= LEFT; goto repeat;
  25.                                 case '+': flags |= PLUS; goto repeat;
  26.                                 case ' ': flags |= SPACE; goto repeat;
  27.                                 case '#': flags |= SPECIAL; goto repeat;
  28.                                 case '0': flags |= ZEROPAD; goto repeat;
  29.                                 }
  30.                
  31.                 /* get field width */
  32.                 field_width = -1;
  33.                 if (is_digit(*fmt))
  34.                         field_width = skip_atoi(&fmt);
  35.                 else if (*fmt == '*') {
  36.                         /* it's the next argument */
  37.                         field_width = va_arg(args, int);
  38.                         if (field_width < 0) {
  39.                                 field_width = -field_width;
  40.                                 flags |= LEFT;
  41.                         }
  42.                 }

  43.                 /* get the precision */
  44.                 precision = -1;
  45.                 if (*fmt == '.') {
  46.                         ++fmt;       
  47.                         if (is_digit(*fmt))
  48.                                 precision = skip_atoi(&fmt);
  49.                         else if (*fmt == '*') {
  50.                                 /* it's the next argument */
  51.                                 precision = va_arg(args, int);
  52.                         }
  53.                         if (precision < 0)
  54.                                 precision = 0;
  55.                 }

  56.                 /* get the conversion qualifier */
  57.                 qualifier = -1;
  58.                 if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L') {
  59.                         qualifier = *fmt;
  60.                         ++fmt;
  61.                 }

  62.                 switch (*fmt) {
  63.                 case 'c':
  64.                         if (!(flags & LEFT))
  65.                                 while (--field_width > 0)
  66.                                         *str++ = ' ';
  67.                         *str++ = (unsigned char) va_arg(args, int);
  68.                         while (--field_width > 0)
  69.                                 *str++ = ' ';
  70.                         break;

  71.                 case 's':
  72.                         s = va_arg(args, char *);
  73.                         len = strlen(s);
  74.                         if (precision < 0)
  75.                                 precision = len;
  76.                         else if (len > precision)
  77.                                 len = precision;

  78.                         if (!(flags & LEFT))
  79.                                 while (len < field_width--)
  80.                                         *str++ = ' ';
  81.                         for (i = 0; i < len; ++i)
  82.                                 *str++ = *s++;
  83.                         while (len < field_width--)
  84.                                 *str++ = ' ';
  85.                         break;

  86.                 case 'o':
  87.                         str = number(str, va_arg(args, unsigned long), 8,
  88.                                 field_width, precision, flags);
  89.                         break;

  90.                 case 'p':
  91.                         if (field_width == -1) {
  92.                                 field_width = 8;
  93.                                 flags |= ZEROPAD;
  94.                         }
  95.                         str = number(str,
  96.                                 (unsigned long) va_arg(args, void *), 16,
  97.                                 field_width, precision, flags);
  98.                         break;

  99.                 case 'x':
  100.                         flags |= SMALL;
  101.                 case 'X':
  102.                         str = number(str, va_arg(args, unsigned long), 16,
  103.                                 field_width, precision, flags);
  104.                         break;

  105.                 case 'd':
  106.                 case 'i':
  107.                         flags |= SIGN;
  108.                 case 'u':
  109.                         str = number(str, va_arg(args, unsigned long), 10,
  110.                                 field_width, precision, flags);
  111.                         break;

  112.                 case 'n':
  113.                         ip = va_arg(args, int *);
  114.                         *ip = (str - buf);
  115.                         break;

  116.                 default:
  117.                         if (*fmt != '%')
  118.                                 *str++ = '%';
  119.                         if (*fmt)
  120.                                 *str++ = *fmt;
  121.                         else
  122.                                 --fmt;
  123.                         break;
  124.                 }
  125.         }
  126.         *str = '\0';
  127.         return str-buf;
  128. }
复制代码

这里vsprintf函数也调用了不少的函数,总而言之,最后都是那么短短的几句汇编语言来实现的。
如果想知道更多的函数是怎么来的,这个就需要去阅读操作系统的源代码!比如linux 的源代码。其实想学习系统内核的编写也不是需要看大量的操作系统书籍,只要会c语言和汇编语言就应该差不多了,当然还学要有一个很好的思维。这些都是在不断的学习中积累起来的。有很多初学者对C语言的评价是做不了什么!那是因为没有看到C语言强的一部分,C语言可以写出来一个操作系统,也就是说,只要学得好,完全可以自己去设计出一个简单的内核,除了一些极端的技术需要用到汇编,其他的时候用C语言就完全可以实现。相信大多数人都应该知道.net了,那么.net是怎么来的呢?他应该是用c/c++开发出来的吧?那么C/C++是怎么来的呢?这个是我观察和学习得出的结论也许并不对,我发现c/c++和汇编语言有着很大的关联,比如goto 某个标志处,就和jmp某个标志处很相似,这个就是高级语言和汇编语言的关联之处,很多地方还是相同的,那么汇编语言是什么呢?汇编语言实际上是机器语言的助记符,例如nop的机器码是90,那么90这个机器码就不用再问怎么来的了吧?90应该是2进制转换成十六进制后得到的结果,这个是我理解的,也许有问题,如果发现有问题请指正!
在不断的问这些函数是怎么来的同时我还有一个疑问,那就是操作系统是怎么被引导起来的呢?写出一个操作系统一定很有意思。后来有位朋友告诉我,写一个内核绝对不是去用别人printf函数,绝对不是去用dos的int 21,而是自己去写printf函数,是自己去实现int 21一样的中断,这就是写操作系统,没有文件系统,自己写文件系统,没有内存管理,自己写内存管理,有了以上的条件,那么接下来想用这个内核怎么办?这个时候就要自己实现,编写键盘驱动,鼠标驱动等等,还有进程,要知道一个单任务的系统是基本上没有人愿意用的,就连自己用都不爽,那么就要学习如何设计多任务的内核,如何实现多现成!自己写函数来实现。这个就是学习底层开发的必备的心理和条件!
那么说一说想实现一个简单的嵌入式系统都需要什么样的环境:
  1. 1.        要有一颗爱问为什么和这个是怎么来的的心
  2. 2.        手头要有一个虚拟机。如(vmware)
  3. 3.        手头要有一个好的编译器,如(nasm)
  4. 4.        要学会一点汇编语言。
  5. 5.        要学一点C语言
复制代码

有了以上的条件就足够了,也就是说,写一个嵌入式的计算器是没有问题!只要计算器写得不超过512个字节就什么问题都没有的。而计算器与引导加起来草不到1K。而且还是实模式下的。至于什么是实模式,就要看intel公司提供的ia-32手册,这种手册是可以向intel公司order的!intel公司是支持我们对他们的产品进行学习的。IA32手册order的地址,当你填完了表之后大约一个星期左右就会有联邦快递公司给你打电话叫你去提取或者他会通过ems发到你指定的地点,order的地址是:http://www.intel.com/design/pentium4/manuals/index2.htm
当看完intel Architecture手册之后,对于intel的结构就会有一个大概的了解了,ia-32手册的第3卷讲得也很详细,相信大多数的操作系统教程会从该卷中摘抄点东西的!而想学习汇编语言可以不去买大量的汇编语言书籍,只要把IA32手册的第2卷从头到尾看一遍就会有很大的提高的,因为大多数的汇编语言教程的书中讲得不太详细,而且讲得操作指令也不全面,毕竟是intel指令嘛!他公司自己写的能少了嘛,占了两本书呢,很厚的啊!以上也就是我想要说的了。还有就是有问题多在google里找找,如果是在win下做嵌入就多看看msdn如果是在linux或unix下开发就多看看man,很有好处的,会学习才是最重要的!

论坛徽章:
0
2 [报告]
发表于 2005-12-16 17:36 |只看该作者
很有指导意义,支持!

论坛徽章:
0
3 [报告]
发表于 2005-12-16 20:32 |只看该作者
建议把楼主的贴加为精华,确实很好的!受用了;谢谢!!!

论坛徽章:
0
4 [报告]
发表于 2005-12-17 09:08 |只看该作者
确实是很有意义

论坛徽章:
0
5 [报告]
发表于 2005-12-17 21:00 |只看该作者
对新成员来说,上面的指导有点太难,可能难以起大的作用。
对于从大学刚出来的成员,理论知识也有一点,真正理解的可能也不多,现在去深入理解那晦涩难懂的汇编和系统内核,可能难以坚持,也难以有真正的有效成果。
在实践中同前辈们开发过系统程序和内核驱动后,回转头再去深入理解汇编和系统内核,效果可能更好。

论坛徽章:
0
6 [报告]
发表于 2005-12-18 08:06 |只看该作者
原帖由 A-Liang 于 2005-12-17 21:00 发表
对新成员来说,上面的指导有点太难,可能难以起大的作用。
对于从大学刚出来的成员,理论知识也有一点,真正理解的可能也不多,现在去深入理解那晦涩难懂的汇编和系统内核,可能难以坚持,也难以有真正的有效成果 ...



我觉得基础最重要!不染学校也不会开那么多的课程了!
请给本文多提见意见!


其实勤能补拙!这句话说得不假!单单是引导部分我看到现在还没看怎么样呢,很是郁闷,仅仅是读扇区,在帖子中也说了,其实只要向intel 公司order一份手册就可以了!说得也很详细,intel公司是支持我们对他的产品进行学习的。都是入门的问题,就因为学习写一个引导我被我的朋友说了,因为他说引导基本上没什么可以让前辈们停留的,比如al*前辈他们,都去学习进程调度和资源管理了,但是我的兴趣不在那里,而是引导。oldlinux 的lgr前辈也说过,当我真正的学到了某种境界,兴趣也就和al*他们一样了,不是在引导上了,但是目前我只是想知道引导怎么把内核引导起来,暂时不想通过别人的说明,我想自己一点一点的去理解,这样才会深刻。
还有,我是一个学生,刚刚步入一所民办大学不到两年的学生,我相信一般大学毕业的学长应该能写出一个不错的内核,引导就更不用说了,学习嘛!学就要学会,否则就等于没有学。如果觉得帖子里缺少什么请多多指点啊!我好加啊


呵呵
多谢后面的朋友批评
改了一下

[ 本帖最后由 1jjk 于 2006-10-23 22:05 编辑 ]

论坛徽章:
0
7 [报告]
发表于 2005-12-18 12:57 |只看该作者
刚参加工作,但现在好像没有什么学习的动力了,向楼主学习,还要努力去学习更多的知识

论坛徽章:
0
8 [报告]
发表于 2005-12-18 21:07 |只看该作者
向楼主学习

论坛徽章:
0
9 [报告]
发表于 2005-12-18 22:50 |只看该作者
真nnd由学习的动力

论坛徽章:
0
10 [报告]
发表于 2005-12-19 13:35 |只看该作者
楼主,好样的!!!
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP