﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-天衣有缝</title><link>http://www.cppblog.com/jinglexy/</link><description>冠盖满京华，斯人独憔悴～</description><language>zh-cn</language><lastBuildDate>Sat, 04 Apr 2026 17:18:28 GMT</lastBuildDate><pubDate>Sat, 04 Apr 2026 17:18:28 GMT</pubDate><ttl>60</ttl><item><title>发布精简版cygwin-2009.iso</title><link>http://www.cppblog.com/jinglexy/archive/2009/01/06/71371.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 06 Jan 2009 11:46:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2009/01/06/71371.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/71371.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2009/01/06/71371.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/71371.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/71371.html</trackback:ping><description><![CDATA[下载地址：http://jinix.sf.net<br><br>(1)cygwin 2009：集成gcc-4.3.2，rxvt，非常适合一般的编程开发，集成iso仅58M<br>(2)i686-elf的cygwin toolchain，工具链版本：gcc-4.3.2, binutils-2.19, glibc-2.7，测试正常工作<br>以此工具链编译最新的linux内核2.6.28工作正常，kernel打一些补丁：<br>&nbsp;&nbsp;&nbsp; cd linux-2.6.28<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_32/1/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_PC32/2/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_ARM_ABS32/2/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_ARM_PC24/1/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_MIPS_HI16/5/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_MIPS_LO16/6/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_MIPS_26/4/' ./scripts/mod/modpost.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_MIPS_32/2/' ./scripts/mod/modpost.c<br><br>&nbsp;&nbsp;&nbsp; sed -i 's/STT_COMMON/5/g' ./arch/x86/boot/compressed/relocs.c<br><br>&nbsp;&nbsp;&nbsp; sed -i 's/STV_DEFAULT/0/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/STV_INTERNAL/1/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/STV_HIDDEN/2/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/STV_PROTECTED/3/g' ./arch/x86/boot/compressed/relocs.c<br><br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_NONE/0/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_32/1/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_PC32/2/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_GOT32/3/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_PLT32/4/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_COPY/5/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_GLOB_DAT/6/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_JMP_SLOT/7/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_RELATIVE/8/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_GOTOFF/9/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_GOTPC/10/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/R_386_NUM/11/g' ./arch/x86/boot/compressed/relocs.c<br><br>&nbsp;&nbsp;&nbsp; sed -i 's/ELF32_ST_VISIBILITY(sym-&gt;st_other)/sym-&gt;st_other \&amp; 0x03/g' ./arch/x86/boot/compressed/relocs.c<br>&nbsp;&nbsp;&nbsp; sed -i 's/else rm -f $(@D)\/.tmp_$(@F); exit 1;/else mv -f $(@D)\/.tmp_$(@F) $@;/' ./arch/x86/vdso/Makefile<br><br>menuconfig中把netfilter去掉，里面有一些文件名一样（大小写不一样），ipv6也去掉，编译的elf文件正常。<br><br>上海漕河泾<br>2009.01.06<br><br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/71371.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2009-01-06 19:46 <a href="http://www.cppblog.com/jinglexy/archive/2009/01/06/71371.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>博客迁移：http://jinglexy.cublog.cn</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Sun, 25 May 2008 04:48:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/51024.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/51024.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/51024.html</trackback:ping><description><![CDATA[订阅rss的朋友请更换到http://jinglexy.cublog.cn吧<br>cu职业程序员较多，这里大多是学生，也没有linux&amp;开源气氛。<br>感谢cppblog<br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/51024.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-25 12:48 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/25/51024.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>c++普通成员函数转换成c函数指针的执行（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 16 May 2008 12:37:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/50087.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/50087.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/50087.html</trackback:ping><description><![CDATA[<br>&nbsp; 1 #include &lt;unistd.h&gt;<br>&nbsp; 2 #include &lt;stdlib.h&gt;<br>&nbsp; 3 #include &lt;stdio.h&gt;<br>&nbsp; 4 #include &lt;string.h&gt;<br>&nbsp; 5 <br>&nbsp; 6 typedef void (*func_type)(void * obj, int num);<br>&nbsp; 7 class test_t<br>&nbsp; 8 {<br>&nbsp; 9 public:<br>&nbsp;10&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void test_func(int num)<br>&nbsp;11&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;12&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("num is %d\n", num);<br>&nbsp;13&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>&nbsp;14 <br>&nbsp;15&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int a;<br>&nbsp;16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int b;<br>&nbsp;17 <br>&nbsp;18 };<br>&nbsp;19 <br>&nbsp;20 <br>&nbsp;21 int main(int argc, char* argv[])<br>&nbsp;22 {<br>&nbsp;23&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; test_t obj;<br>&nbsp;24&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; func_type p = &amp;test_t::test_func;<br>&nbsp;25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 100; i &lt; 104; i++)<br>&nbsp;26&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p(&amp;obj, i);<br>&nbsp;27 <br>&nbsp;28&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>&nbsp;29 }<br>&nbsp;30 <br><br>程序比较简单，注意它的编译参数：<br>g++&nbsp; -Wno-pmf-conversions&nbsp;&nbsp; -O hello.cpp &amp;&amp; ./a.out<br>否则编译不能通过。<br><br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/50087.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-16 20:37 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/16/50087.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>执行c++构造函数（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 14 May 2008 10:00:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/49845.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/49845.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/49845.html</trackback:ping><description><![CDATA[对于全局对象，特殊情况下构造函数不会执行。如c++写的os。<br><br>链接器把构造函数放在start_ctors和end_ctors之间，所以我们可以这样做：<br>&nbsp;&nbsp;&nbsp; for (i = &amp;start_ctors; i &lt; &amp;end_ctors; i++) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; foo = (CONSTRUCTOR_FUNC)*i;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; foo();&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* 构造函数不能用 cout对象，这个时候控制台还没有初始化 */<br>&nbsp;&nbsp;&nbsp; }<br><br>引出一个特殊需求，全局对象按顺序构造，我们显然无法预知start_ctors表顺序。<br>一个可行的方法使用重载new，并用模板函数封装其执行：<br><br>#include &lt;unistd.h&gt;<br>#include &lt;stdlib.h&gt;<br>#include &lt;stdio.h&gt;<br>#include &lt;string.h&gt;<br><br>struct test_t<br>{<br>public:<br>&nbsp;&nbsp;&nbsp; test_t()<br>&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; printf("construct of test_t()\n");<br>&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp; int a;<br>&nbsp;&nbsp;&nbsp; int b;<br><br>};<br><br><br>void * operator new (size_t size, void * place)<br>{<br>&nbsp;&nbsp;&nbsp; return place;<br>}<br><br>/* call the default constructor */<br>template &lt;class object_t&gt; void construct(object_t * ptr)<br>{<br>&nbsp;&nbsp;&nbsp; new (ptr) object_t();<br>}<br><br><br>test_t t;<br>int main(int argc, char* argv[])<br>{<br>&nbsp;&nbsp;&nbsp; construct(&amp;t);<br><br>&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br><br><br><br><img src ="http://www.cppblog.com/jinglexy/aggbug/49845.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-14 18:00 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/14/49845.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一款好用的pim工具：essentialpim（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 07 May 2008 07:50:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/49132.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/49132.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/49132.html</trackback:ping><description><![CDATA[ms-project2002实在是太大了，一点也不轻量级。<br>一直都在找一款好用的pim(personal info manager)/gtd(get things done)工具，<br>测试了10几个之后，锁定到essentialpim-2.50了。<br>（个人任务最好用最强大的是am-notebook了，网上有人号称自己pj了，<br>下载下来一看，只是从pro版切换到lite版，反正我是没）<br>发个图看看吧，呵呵：<br>要是有更好用的pim/gtd软件，欢迎大家提出<br><br><img alt=""  src="http://www.cppblog.com/images/cppblog_com/jinglexy/4600/o_essentialpim.PNG" height="770" width="990"><br><img src ="http://www.cppblog.com/jinglexy/aggbug/49132.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-07 15:50 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/07/49132.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>how to read file in kernel(原创)</title><link>http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Sun, 04 May 2008 13:21:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/48822.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/48822.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/48822.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: simple example of vfs call&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/48822.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2008-05-04 21:21 <a href="http://www.cppblog.com/jinglexy/archive/2008/05/04/48822.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>mm(use slab arithmetic)  for jinix-1.2.1（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 21 Nov 2007 12:23:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/37103.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/37103.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/37103.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: jinix-1.2.1 will be a useful os later, written by c++. now memory finished, with buddy and slab arithmetic.&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/37103.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-11-21 20:23 <a href="http://www.cppblog.com/jinglexy/archive/2007/11/21/37103.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jinix内核项目：http://jinix.sourceforge.net（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 24 Jul 2007 12:52:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/28723.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html#Feedback</comments><slash:comments>17</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/28723.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/28723.html</trackback:ping><description><![CDATA[上周四在sf申请的project，周一晚上就批下来了。现在亢哧亢哧的做着，结果究竟如何是个不知数，闲着找点事做吧，免得自己慢慢失去了动力。花了一晚上看sf管理站点方法，顺便做了个简单web，挺丑的。试了好几款sftp工具，可能是内网firewall原因，只有ws_ftp可以联上。<br><br>大致介绍一下：linux环境，gcc编译器，c++语言，混合式内核（现在还只是单内核），目前目标平台i386/arm。刚刚完成了MM部分，都是移的linux算法（buddy，slab等），整个MM就一个类，彻底荤菜，呵呵。如果找些人讨论讨论c++倒是好事（当然不是那种无里头的，得先看书），但是我c++超菜鸟，又不善组织，希望冥冥中得遇大老指点一二。<br><br>不知道sf大家访问有没有问题，贴一些主要内容：<br>
版本历史：<br>
<font color="red">3.1.1版：代号：</font><br>
<font color="#3366ff">总体目标/功能：xx</font><br><br>
<font color="red">3.0.0版：代号：</font><br>
<font color="#3366ff">总体目标/功能：（发布稳定系统）</font><br><br>
<font color="red">2.1.1版：代号：</font><br>
<font color="#3366ff">总体目标/功能：单元测试，bug修复</font><br><br>
<font color="red">2.0.0版：代号：</font><br>
<font color="#3366ff">总体目标/功能：（完成系统核心，封锁版本）</font><br><br>
<font color="red">1.7.1版：代号：</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第8章节</font><br><br>
<font color="red">1.6.1版：代号：xx（</font><font color="green">2008-02-05 ~ 2008-05-05</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第7章节（tcp/ip）</font><br><br>
<font color="red">1.5.1版：代号：xx（</font><font color="green">2008-01-01 ~ 2008-02-04</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第6章节（文件系统）</font><br><br>
<font color="red">1.4.1版：代号：xx（</font><font color="green">2007-10-25 ~ 2007-12-24</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第5章节（设备驱动）</font><br><br>
<font color="red">1.3.1版：代号：xx（</font><font color="green">2007-10-10 ~ 2007-10-24</font><font color="red">）</font><br>
<font color="#3366ff">总体目标/功能：单元测试，bug修复</font><br><br>
<font color="red">1.2.1版：代号：一帘忧梦（</font><font color="green">2007-07-01 ~ 2007-09-24</font><font color="red">正在进行中）</font><br>
<font color="#3366ff">总体目标/功能：完成计划的第1，2，3，4章节</font><br>
(4).jinix-1.2.1.2007-07-19_09.18.22.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;完成slab算法调研及编写<br>
&nbsp;&nbsp;&nbsp;&nbsp;内核初始化流程完善，及相关部分接口/框架<br><br>
(3).jinix-1.2.1.2007-07-15_16.36.41.tar<br>
&nbsp;&nbsp;&nbsp;&nbsp;textio类重载&lt;&lt;运算符以支持cout &lt;&lt; __func__;<br>
&nbsp;&nbsp;&nbsp;&nbsp;内存管理初始化及buddy算法完成, 内核对象完善（启动流程）<br><br>
(2).jinix-1.2.1.2007-07-12_18.49.44.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;内核对象编写，boot.S-&gt;head.S，初始化汇编文件中全局变量移入bootdata.cpp中<br>
&nbsp;&nbsp;&nbsp;&nbsp;内存管理类接口编写，以及使用到的相关数据结构从linux中移植<br><br>
(1).jinix-1.2.1.2007-07-03_21.07.57.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;某些初始化过的全局变量被编译到bss节去了，被boot.S文件清空，<br>
&nbsp;&nbsp;&nbsp;&nbsp;调整到新Makefile, 和unixlite相似<br>
&nbsp;&nbsp;&nbsp;&nbsp;使用__attribute__((section(...强制链接到.data<br><br>
(0).jinix-1.2.1.2007-06-30_17.50.21.tar.bz2<br>
&nbsp;&nbsp;&nbsp;&nbsp;控制台显示部分调试完成, textio和ostream调试完成<br><br><br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="572">1.系统初始化</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">内核启动</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">i86硬件初始化（分页）</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">时钟初始化</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">中断及异常初始化</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">reboot/halt/poweroff</td>
            <td valign="top" width="190">完成</td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">acpi/apm</td>
            <td valign="top" width="190"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="52">&nbsp;</td>
            <td valign="top" width="330">fpu/mmx/sse/sse2</td>
            <td valign="top" width="190"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">2.支撑型数据结构和算法</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">hash</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">队列</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">链表</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">fifo/lifo</td>
            <td valign="top" width="189">完成</td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">3.内存管理子系统</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">buddy算法</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">slab分配器</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">页异常处理</td>
            <td valign="top" width="189">完成</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">cow（copy on write）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">demand paging</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">守护线程（swap，页面冲洗）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">4.进程及任务调度</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">任务切换</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">fork()</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">调度算法</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">内核线程</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">idle线程</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">用户线程</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">同步机制：内核锁和原子操作</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">5.设备驱动</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">中断机制</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">驱动框架及对外接口考虑</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">字符设备驱动框架</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">块设备驱动框架</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">网络设备驱动框架</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">控制台驱动（显卡，键盘，鼠标）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">dma驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">pci驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">8029/8139, ne2000网卡驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">usb驱动</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">6.文件系统</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">proc</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">ramdisk</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">ext2</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">ext3</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">vfat</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">可执行文件elf加载</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">动态链接库和内核模块</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">7.TCP/IP网络模块</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">数据链路层（Layer 2）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">IP层（Layer 3）</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">icmp, arp, ip, 路由协议</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">tcp, udp</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">socket接口</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">8.进程间通信IPC</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">共享内存</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">信号量</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">消息队列</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">9.posix支持及其他</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">susv3调研</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">lsb调研</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">posix兼容及测试</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">linux-abi兼容</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">shell及常用application</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">arm体系架构调研</td>
            <td valign="top" width="189"><strong><em>未完成</em></strong></td>
        </tr>
    </tbody>
</table>
<br>
<table class="thin" border="0" cellpadding="0" cellspacing="1">
    <tbody>
        <tr>
            <td colspan="3" align="center" valign="top" width="568">10.保留</td>
        </tr>
        <tr>
            <td valign="top" width="55">&nbsp;</td>
            <td valign="top" width="324">&nbsp;</td>
            <td valign="top" width="189">&nbsp;</td>
        </tr>
    </tbody>
</table>
<br><img src ="http://www.cppblog.com/jinglexy/aggbug/28723.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-07-24 20:52 <a href="http://www.cppblog.com/jinglexy/archive/2007/07/24/28723.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>流程图绘制软件dia介绍（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 17 Jul 2007 05:03:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/28186.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/28186.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/28186.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span lang="EN-US">Dia</span><span style="font-family: 宋体;">是一个用于绘制各类图表的工具软件，它从</span><span lang="EN-US">Windows Visio</span><span style="font-family: 宋体;">中借鉴了不少特性。对于各类流程图，网络布局，</span><span lang="EN-US">UML</span><span style="font-family: 宋体;">图等，表现非常良好。以前使用的如</span><span lang="EN-US">Ration Rose</span><span style="font-family: 宋体;">，</span><span lang="EN-US">Windows Visio</span><span style="font-family: 宋体;">，</span><span lang="EN-US">SmartDraw</span><span style="font-family: 宋体;">，</span><span lang="EN-US">DD</span><span style="font-family: 宋体;">等，一直都不顺手，用了一段时间</span><span lang="EN-US">dia</span><span style="font-family: 宋体;">后觉得很不错。这是个跨平台开源的软件，在</span><span lang="EN-US">Win/Linux</span><span style="font-family: 宋体;">上都可以使用。最新的版本是</span><span lang="EN-US">0.96.1</span><span style="font-family: 宋体;">。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">可以在</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><a href="http://www.gnome.org/projects/dia/">http://www.gnome.org/projects/dia</a></span><span style="font-size: 12pt; font-family: 宋体;">上找到它的下载和<span lang="EN-US">screenshot</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;">这个软件基本上不需要学习，使用界面非常简单。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">下面是示例图：</span></p>
<img alt="" src="http://www.cppblog.com/images/cppblog_com/jinglexy/4600/o_dia.PNG">
<p class="MsoNormal"><span lang="EN-US"><br></span></p>
<p class="MsoNormal"><span lang="EN-US">Dia</span><span style="font-family: 宋体;">对各类图形的支持是插件形式提供，很容易扩展。如果支持图形间超级链接就更好了。不过程序发生异常的情况较多，最严重的是有时候异常了原来的图形文件打不开。等到</span><span lang="EN-US">1.x</span><span style="font-family: 宋体;">版本出来的时候可能会好些吧。</span></p>
<p class="MsoNormal"><span style="font-family: 宋体;"><br></span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/28186.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-07-17 13:03 <a href="http://www.cppblog.com/jinglexy/archive/2007/07/17/28186.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>jinix内核虚拟控制台实现（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 10 Jul 2007 12:15:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/27828.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/27828.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/27828.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: jinix是小弟正在实现的一个c++kernel，因为调试缘故，所以早早的把控制台部分调出来了，以便于后来的调试。代码使用c++写的，如果使用c写内核也很容易移植过去。转载请保留原 创：http://www.cppblog.com/jinglexy，mail &amp; msn: jinglexy at yahoo dot com dot cn。这部分代码是在内存管理之前实现的，所以没有做到任...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/27828.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-07-10 20:15 <a href="http://www.cppblog.com/jinglexy/archive/2007/07/10/27828.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>OS调试相关的工具（附图，原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Thu, 28 Jun 2007 03:02:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/27133.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/27133.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/27133.html</trackback:ping><description><![CDATA[部分观点可能过于激进，读者自行取舍。尽管我认为程序是写出来的，不是调出来的（和市场上的观点正好相反），优质的程序应该在模块设计和实现时应保证不出现什么bug。这当然只是理想情况，还得取决于个人水平。程序应在实现阶段得到最大保证，而不是过度依赖调试器。一个彻底的反调试派，据说真正的高手会在cpu旁放一颗爆米花：）转载请保留原创：http://www.cppblog.com/jinglexy，MSN &amp; Email：jinglexy at yahoo dot com dot cn<br><br>如果系统处于仿真的初期节点，例如操作系统的初始化，调试还是很有必要的。这里是我在linux环境调试操作系统的相关工具，os开发者可参考，欢迎指正：）<br>（1）工具安装：<br>linux安装：bochs-2.3，insight-6.6，gcc-3.4（使用g++和as（binutils包中））<br>windows安装：Xmanager Enterprise2.1<br>因为网管没有lotus和clearcase在linux系统下的支持，所以只好用两个操作系统了。这样也比较好，一个用于program，一个用于调试，毕竟bochs挺耗cpu的，就让她干活好了。<br>bochs安装：./configure --with-all-libs --enable-vbe --enable-gdb-stub &amp;&amp; make &amp;&amp; make install<br>insight-6.6安装：包含了tck/tk，gdb-6.6，bfd等工具，使用insight时最好这样设置环境变量：<br>export LC_ALL=en_US<br>否则运行时可能会报错：<br>Tcl_Init failed: can't read "env(TCL_LIBRARY)": no such variable<br>配置xserver用于远程访问Linux图形界面，这样可以在windows上通过ssh执行linux的图形界面程序。<br><br><br>（2）相关文件：<br>bochs配置文件添加如下节：<br>gdbstub: enabled=1, port=1234, text_base=0, data_base=0, bss_base=0<br><br>gdb调试脚本：<br>gdb的命令集可以写入到一个文件中去，这样避免了在启动时输入一大堆命令，100%鼠标操作？faint<br>保存所有命令到一个文件，每行一个命令，如下：<br>file ./vmjinix<br>target remote 127.0.0.1:1234<br>dir&nbsp; ./arch/i386<br>dir&nbsp; ./init<br>dir&nbsp; ./kernel<br>dir&nbsp; ./drivers<br>dir&nbsp; ./drivers/video<br>dir&nbsp; ./drivers/video/console<br>show dir<br>break start_kernel<br>continue<br>list 0<br>gdb和gdb前端执行如下：<br>gdb -q -x gdb.command<br>insight -q -x gdb.command<br><br>其他脚本（磁盘自动创建分区，自动安装grub，拷贝内核，及Makefile脚本），这些贴出来太长，花了好几个小时写好的，需要可以和我联系（MSN &amp; Email：jinglexy at yahoo dot com dot cn）<br><br>（3）调试方法<br>将内核（jinix-1.2.1是我正在编写的一个C++ 开源OS，欢迎参与）拷贝到linux主机，配置samba共享，这样可以在windows上开发（推荐使用slickedit 2007，哪位有linux上的2007版本可否发一个给我）。<br>使用xshell（ssh方式）登录到linux主机上，编译和调试都在这里了。<br>在ssh上执行bochs -f bochsrc.txt.linux，<br>在ssh上执行insight -q -x gdb.command<br>截图如下：<br><img alt="" src="http://www.cppblog.com/images/cppblog_com/jinglexy/4600/o_insight.png" height="768" width="1024"><br><br><br>汇编语言节点也可用使用bochs＋gdb调试，在gdb断点时候执行：<br>disassemble $pc $pc+100（从当前断点处反汇编100字节）<br>需要注意的是，在os的汇编初始化的前期阶段，分页机制往往未开启，符号和地址不能一一对应，<br>这个时候不能进行源码级汇编调试，只能用最即便的反汇编调试了。<br>bochs-2.3中好像有个bug没有解决，nexti执行和stepi在call的时候居然一样，如果要断点到指定行，可以使用物理地址断点。<br><br>（4）文章会不断更新，如有什么好的想法可以在原博客讨论：<br>http://www.cppblog.com/jinglexy<br><br>（5）整理的一份常用gdb指令<br>x&nbsp; /4wx ds:0x1234&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; x是线性地址空间<br>xp /4wx 0x1234&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; xp是物理地址空间<br>backtrace<br>print&nbsp; variable&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 打印变量值<br>print&nbsp; variable@10&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 打印变量后面的10个整数值<br>set&nbsp;&nbsp;&nbsp; variable=2&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 赋值<br>whatis variable&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示变量类型<br>ptype&nbsp; variable&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示数据结构（变量类型加强版）<br><br>断点类型：<br>break init_kernel.cpp:start_kernel&nbsp;&nbsp;&nbsp; 断点在文件的函数<br>break init_kernel.cpp:101&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 断点在文件的101行<br>break init_kernel.cpp:101 if var==100&nbsp;&nbsp;&nbsp; 条件断点<br>break *0xc0102030<br>info break&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 查看所有断点<br>delete breakpoint 3<br>delete breakpoint&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 删除所有断点<br>isable breakpoint 2<br>enable breakpoint 2<br><br><br>search string1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 搜索字符串，从list结束行开始<br>reverse-search string1&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 方向搜索<br>set history expansion on&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 使用历史命令<br>clear&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 删除刚才停止处的断点<br>continue&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 从断点开始继续执行<br>info break&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示当前断点清单，包括到达断点处的次数等<br>info files&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示被调试文件的详细信息<br>info func&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示所有的函数名称<br>info local&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示当函数中的局部变量信息<br>info prog&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示被调试程序的执行状态<br>info var&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; 显示所有的全局和静态变量名称<br>info all<br>run<br>continue<br>step, next, stepi, nexti&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i后缀表示执行一条汇编指令<br><br>/*********************************************************************************<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 格式说明&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; /<br>/*********************************************************************************<br>x&nbsp; /nuf addr检查位于线性地址addr处的内存内容，若addr不指定，则默认为下一个单元地址。<br>xp /nuf addr检查位于物理地址addr处的内存内容。<br>其中的可选参数n、u和f的分别可为：<br>n欲显示内存单元的计数值，默认值为1。<br>u表示单元大小，默认选择为'w'：<br>b （Bytes）1字节；<br>h （Halfwords）2字节；<br>w （Words）4字节；<br>g （Giantwords）8字节。<br>注意：这些缩略符与Intel的不同，主要是为了与GDB调试器的表示法一致。<br>f显示格式，默认选择为'x'：<br>x （hex）显示为十六进制数（默认选择）；<br>d （decimal）显示为十进制数；<br>u （unsigned）显示成无符号十进制数；<br>o （octal）显示成八进制数；<br>t （binary）显示成二进制数。<br>c （char）显示字节代码对应的字符。若不是可显示字符代码，就直接显示代码。<br>*********************************************************************************/<br><br>说明一下：bochs 和 insight本身单个执行就非常慢，而且insight是通过ssh方式链接远程xserver执行，所以速度巨慢，本文所述完全可以全部在linux上操作，不限于平台。<br><br><br> <img src ="http://www.cppblog.com/jinglexy/aggbug/27133.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-28 11:02 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/28/27133.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>C++写内核需要注意的一些事情（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 25 Jun 2007 13:19:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/26940.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/26940.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/26940.html</trackback:ping><description><![CDATA[内核当然可用用c++来些，但是相对c来说有许多要注意的地方，我们不得不关掉一些特性。这里只提一些gcc相关的内容，Microsoft VC我没有尝试。转载请注明原创：天衣有缝（http://www.cppblog.com/jinglexy），MSN: jinglexy at yahoo dot com dot cn<br><br>1)g++选项-nostartfiles：用户环境的在main之前调用的代码，当然不能使用了<br>2)全局对象：每种类型都有自己的构造函数，如果不自己编写代码调用，它们不会执行。<br>这包括所有全局对象和局部static对象，建议的做法是在内核栈建立后，c++运行代码执行之前<br>调用构造函数，如果构造函数没有运行（假设里面有分配内存之类的操作），后果很严重：）<br>我们可以这样做：<br>先修改gnu-ld链接脚本<br>.data : { <br>&nbsp;&nbsp;&nbsp; start_ctors = .;<br>&nbsp;&nbsp;&nbsp; *(.ctor*)<br>&nbsp;&nbsp;&nbsp; end_ctors = .;<br>&nbsp;&nbsp;&nbsp; start_dtors = .;<br>&nbsp;&nbsp;&nbsp; *(.dtor*)<br>&nbsp;&nbsp;&nbsp; end_dtors = .;<br><br>&nbsp;&nbsp;&nbsp; *(.data)<br>}<br>这样构造函数的指针就都保存在start_ctors 和end_ctors之间的内存中了，构造函数其实就是void foo(void);形式的函数，编写一个for循环<br><br>调用它即可；析构函数也是一样的。当每个构造函数调用完后，gcc会自动调用一个函数：<br>int __cxa_atexit(void (* f)(void *), void *p, void *d);<br>当内核退出时，会执行一个函数：<br>void __cxa_finalize(void *d);<br>这两个函数必须按上面格式定义，g++是这样规定的。看看下面的代码就明白了：<br>extern "C"<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int __cxa_atexit(void (*f)(void *), void *p, void *d);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void __cxa_finalize(void *d);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; };<br><br>void *__dso_handle; /*only the address of this symbol is taken by gcc*/<br><br>struct object<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void (*f)(void*);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void *d;<br>} object[32] = {0};<br>unsigned int iObject = 0;<br><br>int __cxa_atexit(void (*f)(void *), void *p, void *d)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (iObject &gt;= 32) return -1;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].f = f;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].p = p;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].d = d;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ++iObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br>}<br><br>/* This currently destroys all objects */<br>void __cxa_finalize(void *d)<br>{<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; unsigned int i = iObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for (; i &gt; 0; --i)<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; --iObject;<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; object[iObject].f(object[iObject].p);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br>}<br><br>3)new和delete：在完成内存管理后，重载类的new和delete函数<br>4)-nostdlib：把标准库禁用掉，最近有了移植stl到内核的想法<br>5)RTTI：最好是禁止它，这样不能用typeid 和 dynamic_cast了<br>6)禁用异常：-fno-exceptions，这个和操作系统太紧密了<br>7)纯虚函数，如果子类没有实现父类中的纯虚函数，链接到下面默认例程：<br>extern "C" void __cxa_pure_virtual()<br>{<br>&nbsp;&nbsp;&nbsp; // print error message<br>}<br>虽然不是为了定义纯虚类的对象，但是链接时编译器会抱怨，所以定义上面函数使编译通过。<br>8)如果一定要使用异常，rtti，new/delete，gcc中提供了静态库：libgcc/libsupc++，<br>还得写这个库的一些基础函数，觉得它应该是在上层抽象出接口，将底层实现空出来给用户实现。<br>而且代码本身非常复杂，网络上也没有任何中文资料。<br>指令：<br>readelf -a `gcc -print-libgcc-file-name`<br>里面定义了很多的函数。<br><br>   <img src ="http://www.cppblog.com/jinglexy/aggbug/26940.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-25 21:19 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/25/26940.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（pdf，chm，source下载）（20070711修订版，原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 11 Jun 2007 02:00:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/26021.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html#Feedback</comments><slash:comments>25</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/26021.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/26021.html</trackback:ping><description><![CDATA[以前一系列的文章整理在下面包中，chm格式和pdf格式，及所有源程序：<br>http://blogimg.chinaunix.net/blog/upfile2/080524213721.rar<br><br>
目录：<br>
自己动手写内核（序）......................... 3<br>
第0 课：环境需求............................. 4<br>
第1 课：引导程序............................. 5<br>
第2 课：保护模式............................. 8<br>
第3 课：辅助函数............................. 17<br>
第4 课：中断和异常1.......................... 25<br>
第5 课：中断和异常2.......................... 39<br>
第6 课：多任务............................... 45<br>
第7 课：文件系统............................. 56<br>
第8 课：内存管理............................. 70<br>
第9 课：系统调用和可执行程序................. 76<br>
一份免责声明................................. 81<br><br><br>    <img src ="http://www.cppblog.com/jinglexy/aggbug/26021.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-11 10:00 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/11/26021.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第9课：系统调用和可执行程序）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 08 Jun 2007 15:21:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/25854.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/25854.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/25854.html</trackback:ping><description><![CDATA[<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp; <o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">第<span lang=EN-US>9</span>课：系统调用和可执行程序<span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://skelix.org/download/09.rar" target=_blank><span lang=EN-US><span lang=EN-US><u><font color=#0000ff>下载源代码</font></u></span></span></a><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">声明：转载请保留：<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">译者：<span lang=EN-US>http://www.cppblog.com/jinglexy<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">原作者：<span lang=EN-US>xiaoming.mo at skelix dot org<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; LINE-HEIGHT: 150%; TEXT-ALIGN: left; mso-pagination: widow-orphan; mso-margin-top-alt: auto; mso-margin-bottom-alt: auto" align=left><span lang=EN-US style="FONT-SIZE: 12pt; LINE-HEIGHT: 150%; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">MSN &amp; Email: jinglexy at yahoo dot com dot cn<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p>&nbsp;</o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; COLOR: blue; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">目标</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">这一节中，我们来实现从磁盘加载应用程序并执行它，以及给这个应用程序系统调用的能力。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="FONT-SIZE: 12pt; COLOR: blue; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">系统调用</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">经过前面一系列的课程，我们基本上建立了一个<span lang=EN-US>OS</span>的各个简单组件，确实非常简单，没有什么复杂的算法和架构。现在再来实现一个简单的<span lang=EN-US>shell</span>控制，一般的<span lang=EN-US>shell</span>处理流程是：<span lang=EN-US>getty()</span>打印登录提示符，等待用户<span lang=EN-US>login</span>，然后执行<span lang=EN-US>bash</span>。这里，我当然不想实现一个<span lang=EN-US>shell</span>，也不想写什么<span lang=EN-US>getty</span>。这一节中，<span lang=EN-US>skelix</span>将从磁盘加载一个可执行程序并执行它，就像常用的<span lang=EN-US>*nix OS</span>一样。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">由于<span lang=EN-US>slelix</span>的虚拟内存管理部分还没有做好，所有的任务共享同一个地址空间。我们采取一个简单的方法，程序从磁盘中加载到地址<span lang=EN-US>0x100000</span>，放到<span lang=EN-US>"/"</span>根目录下面。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">要注意的是，用户任务不能访问内核地址空间，所以一些函数如<span lang=EN-US>kprintf, print_c</span>等也不能再使用了（实际上是可以的，因为我们没有实现虚拟内存管理，这里先假定不能使用它们）。大多数的操作系统都提供了一些<span lang=EN-US>API</span>或系统调用来执行这些函数。现在先添加一个系统调用：<span lang=EN-US><br><br><span style="COLOR: red">09/isr.s</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">sys_print:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pushl&nbsp;&nbsp;&nbsp; %esi&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #&nbsp;</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">背景颜色<span lang=EN-US><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl&nbsp;&nbsp;&nbsp; %edi&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #&nbsp;</span>前景颜色<span lang=EN-US><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; pushl&nbsp;&nbsp;&nbsp; %ebx&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; #&nbsp;</span>要打印的字符<span lang=EN-US><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cli&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; # </span>中断门会字节关掉<span lang=EN-US>EFLAGS </span>的<span lang=EN-US>IF</span>位，系统调用却不行<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; <span style="COLOR: blue">print_c</span><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; sti<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; addl&nbsp;&nbsp;&nbsp; $12,&nbsp;&nbsp;&nbsp; %esp<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ret<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">恨简单，不是吗？上面系统调用有三个参数，<span lang=EN-US>esi</span>是背景颜色，<span lang=EN-US>edi</span>是前景颜色，<span lang=EN-US>ebx</span>是要打印的字符。这个系统调用只打印一个字符，起始就是用户程序对内核<span lang=EN-US>print_c</span>函数的一个<span lang=EN-US>wrapper</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">理论上说，用户任务不能直接使用<span lang=EN-US>print_c</span>函数，也不应当知道有这个函数存在。唯一的方法就是使用系统调用，以此提供给用户一个可用的接口。<span lang=EN-US>DOS </span>操作系统提供了<span lang=EN-US>int 0x21</span>作为系统服务，<span lang=EN-US>linux </span>提供<span lang=EN-US>int 0x80</span>系统调用，本节中模仿<span lang=EN-US>linux</span>在<span lang=EN-US>IDT </span>中添加一个号码<span lang=EN-US>0x80 </span>的系统调用。<span lang=EN-US><br></span>现在我们只用到了<span lang=EN-US>IDT </span>中断的<span lang=EN-US>34</span>项，所以其余的项都可以拿来使用，但是我们只需要<span lang=EN-US>0x80</span>已足够。在<span lang=EN-US>IDT</span>中建立一个<span lang=EN-US>386 </span>的陷阱门就行了，陷阱门和中断门非常类似，只是<span lang=EN-US>E </span>位的类型用<span lang=EN-US>8</span>替代，并且<span lang=EN-US>DPL </span>特权级设置为<span lang=EN-US>3</span>。<span lang=EN-US><br><br><span style="COLOR: red">09/init.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">static void<br>sys_call_install(void) {<br>&nbsp;&nbsp;&nbsp; unsigned long long sys_call_entry = 0x0000ef0000080000ULL<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;| ((unsigned long long)CODE_SEL&lt;&lt;16);<br>&nbsp;&nbsp;&nbsp; sys_call_entry |= ((unsigned long long)<span style="COLOR: blue">sys_call</span>&lt;&lt;32)<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&amp; 0xffff000000000000ULL;<br>&nbsp;&nbsp;&nbsp; sys_call_entry |= ((unsigned long long)<span style="COLOR: blue">sys_call</span>) &amp; 0xffff;<br>&nbsp;&nbsp;&nbsp; idt[<span style="COLOR: blue">SYS_CALL</span>] = sys_call_entry;<br>}<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">宏<span lang=EN-US>SYS_CALL </span>值为<span lang=EN-US>0x80</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">现在我们来看下<span lang=EN-US>0x80</span>的陷阱门处理例程：<span lang=EN-US><br><span style="COLOR: red">09/isr.s</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">sys_call:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cmpl&nbsp;&nbsp;&nbsp; $1,&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; %eax<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jb&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="1" UnitName="F">1f</st1:chmetcnv><br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iret<br>1:<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; pushal<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; call&nbsp;&nbsp;&nbsp; *<span style="COLOR: blue">sys_call_table</span>(, %eax, 4)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; popal<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iret<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">我尽量做到简单，虽然很多东西没有考虑周全，这样做可以降低学习成本。该例程判断系统调用号，即存储在<span lang=EN-US>eax</span>中的值，然后查找函数表：<span lang=EN-US>sys_call_table</span>。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">函数表定义如下：<span lang=EN-US><br><span style="COLOR: red">09/syscall.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void (*sys_call_table[VALID_SYSCALL])(void) = {sys_print};<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; COLOR: blue; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">VALID_SYSCALL</span><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"> </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">宏定义为<span lang=EN-US>1, of course<br><br></span><span style="COLOR: blue">系统调用测试函数</span><span lang=EN-US><br></span>现在我们来做一个用户任务的系统调用测试函数：<span lang=EN-US><br><span style="COLOR: red">09/color.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>color(void) {<br>&nbsp;&nbsp;&nbsp; int i, j;<br>&nbsp;&nbsp;&nbsp; for (i=0; i&lt;16; ++i)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (j=0; j&lt;16; ++j)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; __asm__ ("int&nbsp;&nbsp;&nbsp; $0x80"::"S"(i),"D"(j),"b"('X'),"a"(0));<br>&nbsp;&nbsp;&nbsp; for (;;)<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ;<br>}<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">按例，最简单实现。这个函数打印一些<span lang=EN-US>&#8220;X&#8221;</span>字符，以不同的前景和背景颜色。还有一个问题，怎样把它存储在磁盘上呢，在没有<span lang=EN-US>shell</span>的情况下（否则可以用<span lang=EN-US>cp</span>来拷贝了）。解决的方法是另外写一个程序把程序直接写到磁盘上：实现一个<span lang=EN-US>ghex.c</span>程序来把<span lang=EN-US>color</span>可执行程序的内容打印出来，在内核里面再把可执行文件写到磁盘上。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">Makefile</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">也得修改一下：<span lang=EN-US><br><span style="COLOR: red">09/Makefile</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">all: final.img color<br><br>color: color.o<br>&nbsp;&nbsp;&nbsp; ${LD} --oformat binary -N -e color -Ttext 0x100000 -o color $&lt;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">上面的命令把<span lang=EN-US>color.o</span>文件生成一个二进制可执行文件，入口点在<span lang=EN-US>color</span>函数，代码段逻辑地址从<span lang=EN-US>0x100000</span>开始。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">（<span lang=EN-US>color.c</span>由主机上的<span lang=EN-US>gcc</span>编译器编译，<span lang=EN-US>ld</span>链接）<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">现在把这些二进制数据（显示命令是：<span lang=EN-US>./ghex ../color</span>）写到磁盘上：<span lang=EN-US><br><span style="COLOR: red">09/fs.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>install_color(void) {<br>&nbsp;&nbsp;&nbsp; struct SUPER_BLOCK sb;<br>&nbsp;&nbsp;&nbsp; char sect[512] = {0};<br>&nbsp;&nbsp;&nbsp; struct DIR_ENTRY *de = NULL;<br>&nbsp;&nbsp;&nbsp; int inode = -1;<br>&nbsp;&nbsp;&nbsp; struct INODE clnode;<br>&nbsp;&nbsp;&nbsp; unsigned int blk = 0;<br>&nbsp;&nbsp;&nbsp; unsigned char color[] = <br>{0x57,0x56,0x53,0x83,0xec,0x08,0xc7,0x44,0x24,0x04,0x00,0x00,<br>&nbsp;0x00,0x00,0x83,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7" UnitName="C">7c</st1:chmetcnv>,0x24,0x04,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="0" UnitName="F">0f</st1:chmetcnv>,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7" UnitName="F">7f</st1:chmetcnv>,0x2e,0xc7,0x04,0x24,<br>&nbsp;0x00,0x00,0x00,0x00,0x83,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="C">3c</st1:chmetcnv>,0x24,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="0" UnitName="F">0f</st1:chmetcnv>,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="7" UnitName="F">7f</st1:chmetcnv>,0x19,0x8b,0x74,<br>&nbsp;0x24,0x04,0x8b,0x<st1:chmetcnv w:st="on" TCSC="0" NumberType="1" Negative="False" HasSpace="False" SourceValue="3" UnitName="C">3c</st1:chmetcnv>,0x24,0xbb,0x58,0x00,0x00,0x00,0xb8,0x00,<br>&nbsp;0x00,0x00,0x00,0xcd,0x80,0x89,0xe0,0xff,0x00,0xeb,0xe1,0x8d,<br>&nbsp;0x44,0x24,0x04,0xff,0x00,0xeb,0xcb,0xeb,0xfe};<br><br>&nbsp;&nbsp;&nbsp; sb.sb_start = *(unsigned int *)(HD0_ADDR);<br>&nbsp;&nbsp;&nbsp; hd_rw(ABS_SUPER_BLK(sb), HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; memcpy(&amp;sb, sect, sizeof(struct SUPER_BLOCK));<br><br>&nbsp;&nbsp;&nbsp; inode = alloc_inode(&amp;sb);<br>&nbsp;&nbsp;&nbsp; assert(inode &gt; 0);<br>&nbsp;&nbsp;&nbsp; blk = alloc_blk(&amp;sb);<br>&nbsp;&nbsp;&nbsp; assert(blk != 0);<br>&nbsp;&nbsp;&nbsp; clnode.i_block[0] = blk;<br>&nbsp;&nbsp;&nbsp; hd_rw(blk, HD_WRITE, 1, color);<br>&nbsp;&nbsp;&nbsp; clnode.i_mode = FT_NML;<br>&nbsp;&nbsp;&nbsp; clnode.i_size = sizeof color;<br>&nbsp;&nbsp;&nbsp; iput(&amp;sb, &amp;clnode, inode);<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; // </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">为<span lang=EN-US>color</span>程序分配新的<span lang=EN-US>inode</span>节点和块<span lang=EN-US><br><br>&nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; de = &amp;((struct DIR_ENTRY *)sect)[2];<br>&nbsp;&nbsp;&nbsp; strcpy(de-&gt;de_name, "color");<br>&nbsp;&nbsp;&nbsp; de-&gt;de_inode = inode;<br>&nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_WRITE, 1, sect);<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; // </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">把<span lang=EN-US>color</span>程序放到根目录<span lang=EN-US>"/"</span>下面<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br><br>&nbsp;&nbsp;&nbsp; iget(&amp;sb, &amp;iroot, 0);<br>&nbsp;&nbsp;&nbsp; iroot.i_size = 3*sizeof(struct DIR_ENTRY);<br>&nbsp;&nbsp;&nbsp; iput(&amp;sb, &amp;iroot, 0);<br>&nbsp;&nbsp;&nbsp; // </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">搞定<span lang=EN-US><br>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">// color</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">程序已经写到磁盘上了，再把它加载到内存地址<span lang=EN-US>0x100000<br><span style="COLOR: red">09/fs.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>load_color(void) {<br>&nbsp;&nbsp;&nbsp; struct INODE inode;<br>&nbsp;&nbsp;&nbsp; struct SUPER_BLOCK sb;<br>&nbsp;&nbsp;&nbsp; char sect[512] = {0};<br><br>&nbsp;&nbsp;&nbsp; sb.sb_start = *(unsigned int *)(HD0_ADDR);<br>&nbsp;&nbsp;&nbsp; hd_rw(ABS_SUPER_BLK(sb), HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; memcpy(&amp;sb, sect, sizeof(struct SUPER_BLOCK));<br>&nbsp;&nbsp;&nbsp; iget(&amp;sb, &amp;inode, 1);<br><br>&nbsp;&nbsp;&nbsp; /* </span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">只是简单的把<span lang=EN-US>color</span>加载到虚拟地址<span lang=EN-US>0x100000</span>（也是物理地址<span lang=EN-US>0x100000</span>）<span lang=EN-US> */<br>&nbsp;&nbsp;&nbsp; hd_rw(inode.i_block[0], HD_READ, 1, (void *)0x100000);<br>}<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">还记得以前运行的<span lang=EN-US>task1_run </span>和<span lang=EN-US>task2_run</span>这两个任务吗，它们只是做一些轮流在屏幕上打印字符的无聊工作。我们把<span lang=EN-US>task1</span>换成执行磁盘中的<span lang=EN-US>color</span>程序：<span lang=EN-US><br><span style="COLOR: red">09/init.c</span><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">void<br>do_task1(void) {<br>&nbsp;&nbsp;&nbsp; __asm__ ("incb 0xb8000+160*24+2");<br>&nbsp;&nbsp;&nbsp; load_color();<br>&nbsp;&nbsp;&nbsp; __asm__ ("jmp 0x100000");<br>}<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体"><br></span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">最后在<span lang=EN-US>check_root()</span>函数中添加一些安装函数：<span lang=EN-US><br>09/fs.c<o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp; if (! testb(sect, 0)) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "/ has not been created, creating....\t\t\t\t\t&nbsp; ");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (alloc_inode(&amp;sb) != 0) {<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_PANIC, "\n/ must be inode 0!!!\n");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; halt();<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iroot.i_block[0] = alloc_blk(&amp;sb);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; iput(&amp;sb, &amp;iroot, 0);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_READ, 1, sect);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de = (struct DIR_ENTRY *)sect;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcpy(de-&gt;de_name, ".");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de-&gt;de_inode = 0;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++de;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; strcpy(de-&gt;de_name, "..");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; de-&gt;de_inode = -1;<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; hd_rw(iroot.i_block[0], HD_WRITE, 1, sect);<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "[DONE]");<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (iroot.i_size == 2*sizeof(struct DIR_ENTRY))<br>&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="COLOR: red">install_color</span>();<br>&nbsp;&nbsp;&nbsp; }<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">编译，运行一下。如果一起正常的话，应该是<span lang=EN-US>color</span>任务打印一系列的彩色字符。很有成就感吧：）<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">到此为止，这一系列的课程就结束了，大家可以继续深入下去，<span lang=EN-US>linux</span>内核是一个值得学习的好<span lang=EN-US>kernel</span>，<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">而且也有一些较好的书籍，如情景分析，<span lang=EN-US>ULK2</span>，<span lang=EN-US>In A Nut Shell</span>等。<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">学习是一件愉快的事情，当然也少不了挫折和煎熬。态度才是第一位，祝大家进步：）<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">丁亥年四月廿四<span lang=EN-US>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>于上海体育馆<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;http://www.cppblog.com/jinglexy<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">天衣有缝<span lang=EN-US><o:p></o:p></span></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt; TEXT-ALIGN: left; mso-pagination: widow-orphan" align=left><span lang=EN-US style="FONT-SIZE: 12pt; FONT-FAMILY: 宋体; mso-font-kerning: 0pt; mso-bidi-font-family: 宋体">&nbsp;<o:p></o:p></span></p>
<p class=MsoNormal style="MARGIN: 0cm 0cm 0pt"><span lang=EN-US><o:p>&nbsp;</o:p></span></p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/jinglexy/aggbug/25854.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-08 23:21 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/08/25854.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第8课：内存管理）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 08 Jun 2007 00:44:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/25801.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/25801.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/25801.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; <o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第<span lang="EN-US">8</span>课：内存管理<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;<a  href="http://skelix.org/download/08.rar" target="_blank"><span lang="EN-US"><span lang="EN-US">下载源代码</span></span></a><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">声明：转载请保留：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">译者：<span lang="EN-US">http://www.cppblog.com/jinglexy<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">原作者：<span lang="EN-US">xiaoming.mo at skelix dot org<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">MSN &amp; Email: jinglexy at yahoo dot com dot cn<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">目标</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">抱歉，其实还没有实现。在任务分配独立的<span lang="EN-US">4G</span>地址空间上调试失败了，现在只使能了分页机制，页异常。大量的工作未实现，有兴趣的同学可以搜索<span lang="EN-US">buddy</span>和<span lang="EN-US">slab</span>的相关资料，经典的内存管理算法。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
</span><span style="font-size: 12pt; font-family: 宋体; color: blue;">分页</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">386</span><span style="font-size: 12pt; font-family: 宋体;">处理器的内存管理单元可以实现任务独立地址空间，任务间内存保护。每个任务可以拥有独立的<span lang="EN-US">4G</span>虚拟地址空间。内存映射是内存管理很重要的一步，可以分为两部分：分段和分页。前面的课程中已经讨论过分段机制了，通过分段可以隔开不同的代码，数据，堆栈等；分页单元把虚拟地址映射成物理地址，还可以用来实现虚拟内存（和硬盘分区进行交换），现在我们来了解一下它。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">对于每个任务，我们无法分配<span lang="EN-US">4G</span>的物理内存，所以使用了一些机制来管理内存：及虚拟内存机制。该机制有处理器的分页部分来实现，首先我们将内存分成一些块，每个块大小为<span lang="EN-US">4k</span>，通常我们称之为一个页帧。操作系统通过页目录和页表来管理这些页帧。页目录是相当于第一级页表，其中的每一项再管理一个下级页表。（更详细过程请参考<span lang="EN-US">intel</span>的<span lang="EN-US">IA 32/64</span>手册）<span lang="EN-US"><br>
<br>
</span>当分页机制开启时，处理器把任务中的虚拟地址转换成物理地址，步骤如下：<span lang="EN-US"><br>
1.</span>查找段选择子在<span lang="EN-US">GDT </span>或<span lang="EN-US"> LDT </span>中的描述符，做一些权限检查，看看能否访问<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">2.</span><span style="font-size: 12pt; font-family: 宋体;">以描述符中的基址相加页目录基址得到一个线性地址<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">3.</span><span style="font-size: 12pt; font-family: 宋体;">在页表中索引虚拟地址所对应的页表项，得到页地址<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">4.</span><span style="font-size: 12pt; font-family: 宋体;">查找偏移得到实际物理地址。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">如果实际物理页不存在（可能交换到硬盘中去了），则引发异常，可以在这个异常里面做想要做的事情（加载硬盘中的交换页，或者<span lang="EN-US">kill</span>这个程序：<span lang="EN-US">Segment Fault</span>，等等）<span lang="EN-US"><br>
<br>
</span>处理器使用的页目录或者页表，都是由<span lang="EN-US">32 </span>位的项组成：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">页目录项：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;
11&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp; 876&nbsp;&nbsp; 5&nbsp;&nbsp;
43&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┃&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">指向页表的物理地址<span lang="EN-US">&nbsp; ┃ </span>用户定义<span lang="EN-US"> ┃&nbsp; X&nbsp; ┃&nbsp;A┃
X&nbsp;┃ U/S┃ R/W┃ P&nbsp;┃<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">页表项：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;12&nbsp;&nbsp;&nbsp;
11&nbsp;&nbsp;&nbsp;&nbsp;9&nbsp;&nbsp;&nbsp;87&nbsp; 6&nbsp; 5&nbsp;&nbsp;
43&nbsp;&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┃&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">指向页帧的物理地址<span lang="EN-US">&nbsp; ┃ </span>用户定义<span lang="EN-US"> ┃&nbsp;X┃D┃&nbsp;A┃ X&nbsp;┃
U/S┃ R/W┃ P&nbsp;┃<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">从上面可以知道，页目录项和页表项的结构很类似，下面逐个说明一下其中的域：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<table class="MsoNormalTable" style="width: 79.58%;" border="1" cellpadding="0" width="79%">
    <tbody>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 0<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">P<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">存在位（<span lang="EN-US">present</span>），为<span lang="EN-US">0 </span>表示该页帧或页表不在内存中。如果访问该项将发生异常。<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 1<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">R/W<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">表示页表或页帧指向的内存只读（＝<span lang="EN-US">0</span>），或可写（＝<span lang="EN-US">1</span>）<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 2<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">U/S<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">表示页表或页帧的权限，当特权级为<span lang="EN-US">0</span>时，只有<span lang="EN-US">ring0</span>到<span lang="EN-US">2</span>的特权级可以访问它，否则所有的<span lang="EN-US">ring3</span>任务都可以访问。这个域非常重要。<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 3, 4, (6), 7, 8<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">X<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Intel </span><span style="font-size: 12pt; font-family: 宋体;">保留位，设置为<span lang="EN-US">0</span>就行了<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit&nbsp; 5<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">A<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">该页是否已访问<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 84.75pt;" valign="top" width="113">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 9-11<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 63pt;" valign="top" width="84">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">用户定义<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
            <td style="padding: 1.5pt; width: 393.75pt;" valign="top" width="525">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们使用第<span lang="EN-US">11</span>位，表示该页帧是否被交互到硬盘上了<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页目录的每一项：即页表的物理地址，它的高<span lang="EN-US">20 </span>位地址表示有个页帧的起始地址，正好和<span lang="EN-US">4k</span>对齐。<span lang="EN-US">2^20</span>可以表示<span lang="EN-US">1M</span>范围，每个页帧大小是<span lang="EN-US">4k</span>，所以可以索引<span lang="EN-US">1M * 4K</span>地址空间。页目录项中还有一个<span lang="EN-US">D </span>位，它用来表示一个页帧是否已修改，<span lang="EN-US">linux</span>用它来表示一个页面释放是脏页面，这个位非常有用，当一个页帧交换到硬盘上后，如果该页帧还没有被修改，而且是已经从硬盘交换出来的，则简单取消以后的交换。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">为了将逻辑地址转换成物理地址，逻辑地址被分成<span lang="EN-US">3 </span>部分：<span lang="EN-US"><o:p></o:p></span></span></p>
<table class="MsoNormalTable" style="width: 79.58%;" border="1" cellpadding="0" width="79%">
    <tbody>
        <tr>
            <td style="padding: 1.5pt; width: 101.25pt;" valign="top" width="135">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 31-22<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 437.25pt;" valign="top" width="583">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页目录项的索引下标，由它可以得到页表的物理地址<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 101.25pt;" valign="top" width="135">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 21-12<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 437.25pt;" valign="top" width="583">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页表项的索引下标，由它可以得到页帧的物理地址<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 101.25pt;" valign="top" width="135">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 11-0<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 437.25pt;" valign="top" width="583">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">相对页帧起始地址的偏移<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">举例来说，我们有一个逻辑地址：<span lang="EN-US">0x3E837B0A</span>。前提条件：<span lang="EN-US">CR3</span>寄存器指向的页目录地址是<span lang="EN-US"> 0x0005C000</span>，这个寄存器存储了当前页目录所使用的页帧的物理地址，通常也叫做<span lang="EN-US">
PDBR</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">先取它的高<span lang="EN-US">10</span>位， 就是<span lang="EN-US">0x0FA</span>，由它可以索引到页目录的第<span lang="EN-US">0x0FA</span>项，我们取得这一项的值，假设得到的地址值是<span lang="EN-US">0x0003F000</span>。然后我们取虚拟地址的中间<span lang="EN-US">10</span>位，就是<span lang="EN-US">0x037</span>，再取出<span lang="EN-US">0x0003F000</span>指向页帧的第<span lang="EN-US">0x037</span>项的值，假设是<span lang="EN-US">0x0001B000</span>。这个地址就是我们要找的虚拟地址对应的物理地址的页帧的起始地址，最后加上偏移值（低<span lang="EN-US">12</span>位），即<span lang="EN-US">0xB0A</span>，得到实际的物理地址是：<span lang="EN-US">0x0001BB0A</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">相关的知识可以参考<span lang="EN-US"> Intel </span>的<span lang="EN-US">IA 32/64</span>手册。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">CR3</span><span style="font-size: 12pt; font-family: 宋体;">寄存器必须在分页机制开启前就装载好，可以使用<span lang="EN-US">MOV </span>指令或者在任务切换时使用<span lang="EN-US">TSS</span>中的<span lang="EN-US">CR3</span>域的值。当处理器访问不存在的页帧时，发生一个异常，<span lang="EN-US">CR2 </span>寄存器存引发异常的逻辑地址，同时错误码也会压入到堆栈中，错误码格式如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;31&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
3&nbsp;&nbsp; 2&nbsp;&nbsp;&nbsp;&nbsp; 1&nbsp;&nbsp;&nbsp;&nbsp; 0<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┃&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">未使用<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
┃ U/S┃ R/W┃ P&nbsp;┃<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">异常处理例程通常采取如下的步骤：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">查找一个空闲的页帧或从硬盘中将页帧交换出来，重新设置正确的页目录项或页表项的值，刷新<span lang="EN-US">TLB</span>。处理器通常保存最近最多访问的页目录或页表项到一个<span lang="EN-US">cache</span>中，以避免每次都进行虚拟地址到物理地址的转换，这个<span lang="EN-US">cache</span>就叫做<span lang="EN-US">TLB</span>。只有我们改动了页目录或页表项，就应当刷新<span lang="EN-US">TLB</span>。方法很简单，就是重新加载<span lang="EN-US">CR3 </span>寄存器。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
</span><span style="font-size: 12pt; font-family: 宋体;">现在我们来看看代码段，内存管理通常少不了大量的宏定义：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: red;" lang="EN-US">08/include/kernel.h</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">#define PAGE_DIR&nbsp;&nbsp;&nbsp;
((HD0_ADDR+HD0_SIZE+(4*1024)-1) &amp; 0xfffff000)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">物理内存安排：<span lang="EN-US">IDT</span>（在<span lang="EN-US">0x40000</span>），接下来是<span lang="EN-US">GDT</span>，接下来是<span lang="EN-US">HD0</span>使用，然后才是页目录，<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">所以这个宏看起来有点长。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: red;">08/include/mm.h</span><br>
#define PAGE_SIZE&nbsp;&nbsp;&nbsp;
(4*1024)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
</span><span style="font-size: 12pt; font-family: 宋体;">页帧粒度<span lang="EN-US"> */<br>
#define PAGE_TABLE&nbsp;&nbsp;&nbsp; (PAGE_DIR+PAGE_SIZE)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
</span>页表物理地址<span lang="EN-US"> */<br>
#define MEMORY_RANGE (4*1024)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
/* skelix</span>只管理<span lang="EN-US">4M </span>内存暂时<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: red;">08/mm.c</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">/* </span><span style="font-size: 12pt; font-family: 宋体;">物理内存使用情况的位图表<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">static char mmap[MEMORY_RANGE/PAGE_SIZE] = {PG_REVERSED,
};<br>
<br>
void<br>
mm_install(void) {<br>
&nbsp;&nbsp;&nbsp; unsigned int *page_dir = ((unsigned int *)PAGE_DIR);<br>
&nbsp;&nbsp;&nbsp; unsigned int *page_table = ((unsigned int *)PAGE_TABLE);<br>
&nbsp;&nbsp;&nbsp; unsigned int address = 0;<br>
&nbsp;&nbsp;&nbsp; int i;<br>
&nbsp;&nbsp;&nbsp; for(i=0; i&lt;MEMORY_RANGE/PAGE_SIZE; ++i) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* </span><span style="font-size: 12pt; font-family: 宋体;">页表项属性设置为<span lang="EN-US">: kernel, r/w, present */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; page_table[i] = address|7;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; address += PAGE_SIZE;<br>
&nbsp;&nbsp;&nbsp; };<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">上面循环初始化了<span lang="EN-US">0~4M</span>对应的所有页表项<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; page_dir[0] = (PAGE_TABLE|7);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">页目录项只需要第一个就可以了，因为只有<span lang="EN-US">4M</span>内存<span lang="EN-US"><br>
<br>
&nbsp;&nbsp;&nbsp; for (i=1; i&lt;1024; ++i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; page_dir[i] = 6;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">其他的<span lang="EN-US">1023</span>个页目录项设置为空，如果这<span lang="EN-US">1024</span>项都设置，可访问<span lang="EN-US">4G</span>内存空间<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">设置<span lang="EN-US">0</span>～<span lang="EN-US">1M</span>内存为已使用。<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; for (i=(1*1024*1024)/PAGE_SIZE-1; i&gt;=0; --i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; mmap[i] = PG_REVERSED;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">因为内核只用到了低于<span lang="EN-US">1M</span>的内存，所以保留它们，这样就不会被交换出去了<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<br>
&nbsp;&nbsp;&nbsp; __asm__ (<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "movl&nbsp;&nbsp;&nbsp;
%%eax,&nbsp;&nbsp;&nbsp;
%%cr3\n\t"&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">加载页目录基址到寄存器<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; "movl&nbsp;&nbsp;&nbsp;
%%cr0,&nbsp;&nbsp;&nbsp; %%eax\n\t"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "orl&nbsp;&nbsp;&nbsp; $0x80000000,&nbsp;&nbsp;&nbsp;
%%eax\n\t"<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "movl&nbsp;&nbsp;&nbsp;
%%eax,&nbsp;&nbsp;&nbsp;
%%cr0"::"a"(PAGE_DIR));&nbsp;&nbsp;&nbsp;&nbsp;// </span>开启分页机制，<span lang="EN-US">CR0</span>的最高位<span lang="EN-US"><br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">通过<span lang="EN-US">mmap</span>位图，我们可以清楚的知道内存的使用情况，这样就可以分配空闲页帧了，如下：<span lang="EN-US"><br>
<span style="color: red;">08/mm.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">unsigned int<br>
alloc_page(int type) {<br>
&nbsp;&nbsp;&nbsp; int i;<br>
<br>
&nbsp;&nbsp;&nbsp; for (i=(sizeof mmap)-1; i&gt;=0 &amp;&amp; mmap[i]; --i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ;<br>
<br>
&nbsp;&nbsp;&nbsp; if (i &lt; 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; kprintf(KPL_PANIC, "NO MEMORY
LEFT");<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; halt();<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; mmap[i] = type;<br>
&nbsp;&nbsp;&nbsp; return
i;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">返回页帧号<span lang="EN-US"><br>
}<br>
<br>
void *<br>
page2mem(unsigned int nr)
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span>转换为虚拟地址<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; return (void *)(nr * PAGE_SIZE);<br>
}<br>
<br>
void<br>
do_page_fault(enum KP_LEVEL kl,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
ret_ip, unsigned int ss, unsigned int gs,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
fs, unsigned int es, unsigned int ds, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
edi, unsigned int esi, unsigned int ebp,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
esp, unsigned int ebx, unsigned int edx, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
ecx, unsigned int eax, unsigned int isr_nr, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
err, unsigned int eip, unsigned int cs, <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; unsigned int
eflags,unsigned int old_esp, unsigned int old_ss) {<br>
&nbsp;&nbsp;&nbsp; unsigned int cr2, cr3;<br>
&nbsp;&nbsp;&nbsp; (void)ret_ip; (void)ss; (void)gs; (void)fs; (void)es; <br>
&nbsp;&nbsp;&nbsp; (void)ds; (void)edi; (void)esi; (void)ebp; (void)esp; <br>
&nbsp;&nbsp;&nbsp; (void) ebx; (void)edx; (void)ecx; (void)eax; <br>
&nbsp;&nbsp;&nbsp; (void)isr_nr; (void)eip; (void)cs; (void)eflags; <br>
&nbsp;&nbsp;&nbsp; (void)old_esp; (void)old_ss; (void)kl;<br>
&nbsp;&nbsp;&nbsp; __asm__ ("movl %%cr2, %%eax":"=a"(cr2));<br>
&nbsp;&nbsp;&nbsp; __asm__ ("movl %%cr3, %%eax":"=a"(cr3));<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_PANIC, "\n&nbsp; The fault at %x cr3:%x was
caused by a %s. "<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "The accessing
cause of the fault was a %s, when the "<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; "processor was
executing in %s mode, page %x is free\n", <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cr2, cr3,<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
(err&amp;0x1)?"page-level protection voilation":"not-present
page", <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
(err&amp;0x2)?"write":"read", <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
(err&amp;0x4)?"user":"supervisor",<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: red;">alloc_page</span>(PG_NORMAL));<br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">页异常函数，它什么也没有做，知识显示一些错误信息。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在我们来动态的分配一些内存，我们修改一下任务函数：<span lang="EN-US"><br>
<span style="color: red;">08/init.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">static void<br>
new_task(unsigned int eip) {<br>
&nbsp;&nbsp;&nbsp; struct TASK_STRUCT *task = <span style="color: red;">page2mem</span>(alloc_page(PG_TASK));<br>
&nbsp;&nbsp;&nbsp; memcpy(&amp;(task-&gt;tss), &amp;(TASK0.tss), sizeof(struct
TSS_STRUCT));<br>
<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.esp0 = (unsigned int)task + PAGE_SIZE;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.eip = eip;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.eflags = 0x3202;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.esp = (unsigned int)<span style="color: red;">page2mem</span>(alloc_page(PG_TASK))+PAGE_SIZE;<br>
&nbsp;&nbsp;&nbsp; task-&gt;tss.cr3 = PAGE_DIR;<br>
&nbsp;&nbsp;&nbsp; task-&gt;priority = INITIAL_PRIO;<br>
&nbsp;&nbsp;&nbsp; task-&gt;ldt[0] = DEFAULT_LDT_CODE;<br>
&nbsp;&nbsp;&nbsp; task-&gt;ldt[1] = DEFAULT_LDT_DATA;<br>
<br>
&nbsp;&nbsp;&nbsp; task-&gt;next = current-&gt;next;<br>
&nbsp;&nbsp;&nbsp; current-&gt;next = task;<br>
&nbsp;&nbsp;&nbsp; task-&gt;state = TS_RUNABLE;<br>
}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">自己分配的任务数据结构和任务堆栈，是不是很有成就感：）<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">最后在<span lang="EN-US">init.c</span>中添加初始化代码：<span lang="EN-US"><br>
<span style="color: red;">08/init.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">void <br>
init(void) {<br>
&nbsp;&nbsp;&nbsp; char wheel[] = {'\\', '|', '/', '-'};<br>
&nbsp;&nbsp;&nbsp; int i = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; idt_install();<br>
&nbsp;&nbsp;&nbsp; pic_install();<br>
&nbsp;&nbsp;&nbsp; mm_install();&nbsp;&nbsp; &nbsp;&nbsp; /*&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">初始化函数调用<span lang="EN-US"> */<br>
&nbsp;&nbsp;&nbsp; kb_install();<br>
&nbsp;&nbsp;&nbsp; timer_install(100);<br>
&nbsp;&nbsp;&nbsp; set_tss((unsigned long long)&amp;TASK0.tss);<br>
&nbsp;&nbsp;&nbsp; set_ldt((unsigned long long)&amp;TASK0.ldt);<br>
&nbsp;&nbsp;&nbsp; __asm__ ("ltrw&nbsp;&nbsp;&nbsp;
%%ax\n\t"::"a"(TSS_SEL));<br>
&nbsp;&nbsp;&nbsp; __asm__ ("lldt&nbsp;&nbsp;&nbsp;
%%ax\n\t"::"a"(LDT_SEL));<br>
<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "Verifing disk partition
table....\n");<br>
&nbsp;&nbsp;&nbsp; verify_DPT();<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "Verifing file systes....\n");<br>
&nbsp;&nbsp;&nbsp; verify_fs();<br>
&nbsp;&nbsp;&nbsp; kprintf(KPL_DUMP, "Checking / directory....\n");<br>
&nbsp;&nbsp;&nbsp; verify_dir();<br>
<br>
&nbsp;&nbsp;&nbsp; sti();<br>
&nbsp;&nbsp;&nbsp; new_task((unsigned int)task1_run);<br>
&nbsp;&nbsp;&nbsp; new_task((unsigned int)task2_run);<br>
&nbsp;&nbsp;&nbsp; __asm__ ("movl %%esp,%%eax\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl %%ecx\n\t"
\<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl
%%eax\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;"pushfl\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl
%%ebx\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"pushl
$1f\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;"iret\n" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"1:\tmovw
%%cx,%%ds\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"movw
%%cx,%%es\n\t" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"movw %%cx,%%fs\n\t"
\<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;"movw
%%cx,%%gs" \<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
&nbsp;::"b"(USER_CODE_SEL),"c"(USER_DATA_SEL));<br>
&nbsp;&nbsp;&nbsp; __asm__ ("incb 0xeeffeeff");&nbsp;&nbsp;
&nbsp;&nbsp; &nbsp;&nbsp; /*&nbsp;</span><span style="color: red;">测试：</span>触发一个异常<span lang="EN-US"> */<br>
&nbsp;&nbsp;&nbsp; for (;;) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; __asm__ ("movb&nbsp;&nbsp;&nbsp;
%%al,&nbsp;&nbsp;&nbsp; 0xb8000+160*24"::"a"(wheel[i]));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (i == sizeof wheel)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; i = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++i;<br>
&nbsp;&nbsp;&nbsp; }<br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">异常处理例程中什么也没做，访问内存出错则死机：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: red;" lang="EN-US">08/exceptions.c</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">void<br>
page_fault(void) {<br>
&nbsp;&nbsp;&nbsp; __asm__ ("pushl&nbsp;&nbsp;&nbsp;
%%eax;call&nbsp;&nbsp;&nbsp; do_page_fault"::"a"(KPL_PANIC));<br>
&nbsp;&nbsp;&nbsp; halt();<br>
}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">最后把<span lang="EN-US">mm.o </span>添加到<span lang="EN-US"> Makefile </span>的<span lang="EN-US">KERNEL_OBJS </span>中去：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: red;" lang="EN-US">08/Makefile</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">KERNEL_OBJS= load.o init.o isr.o timer.o libcc.o scr.o
kb.o task.o kprintf.o hd.o exceptions.o fs.o mm.o<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/25801.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-06-08 08:44 <a href="http://www.cppblog.com/jinglexy/archive/2007/06/08/25801.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第7课：文件系统）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/19/24377.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Sat, 19 May 2007 03:35:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/19/24377.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/24377.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/19/24377.html#Feedback</comments><slash:comments>5</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/24377.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/24377.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第7课：文件系统&nbsp;&nbsp;&nbsp; 下载源代码声明：转载请保留：译者：http://www.cppblog.com/jinglexy原作者：xiaoming.mo at skelix dot orgMSN &amp; Email: jinglexy at yahoo dot com dot cn&nbsp;&nbsp;目标&nbsp;这一课中，...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/19/24377.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/24377.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-19 11:35 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/19/24377.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第6课：多任务）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/15/24158.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Tue, 15 May 2007 08:55:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/15/24158.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/24158.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/15/24158.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/24158.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/24158.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第6课：多任务&nbsp;&nbsp;&nbsp; 下载源代码声明：转载请保留：译者：http://www.cppblog.com/jinglexy原作者：xiaoming.mo at skelix dot orgMSN &amp; Email: jinglexy at yahoo dot com dot cn目标&nbsp;在本课中，我们将在skelix内核中同时...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/15/24158.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/24158.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-15 16:55 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/15/24158.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个调试工具编写的发现（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/11/23909.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 11 May 2007 09:02:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/11/23909.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23909.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/11/23909.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23909.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23909.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 没有什么意义，只是记录而已......&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/11/23909.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/23909.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-11 17:02 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/11/23909.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第5课：中断和异常2）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/11/23881.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 11 May 2007 02:39:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/11/23881.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23881.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/11/23881.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23881.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23881.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第5课：中断和异常2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下载源代码声明：转载请保留：译者：http://www.cppblog.com/jinglexy原作者：xiaoming.mo at skelix dot orgMSN &amp; Email: jinglexy at yahoo dot com dot cn目标在上一节课中，我们介...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/11/23881.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/23881.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-11 10:39 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/11/23881.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>整理一些有用的网页（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/09/23727.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 09 May 2007 13:01:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/09/23727.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23727.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/09/23727.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23727.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23727.html</trackback:ping><description><![CDATA[<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">一、</span><span lang="EN-US">solaris </span><span style="font-family: 宋体;">内核及应用程序源程序：</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://src.opensolaris.org/source">http://src.opensolaris.org/source</a><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></span><span style="font-family: 宋体;">主页</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/ls/ls.c">http://src.opensolaris.org/source/xref/onnv/onnv-gate/usr/src/cmd/ls/ls.c</a><span>&nbsp;&nbsp; 范例：</span>ls</span><span style="font-family: 宋体;">源程序</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">二、比较多的</span><span lang="EN-US">gcc</span><span style="font-family: 宋体;">资料</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://gcc.cookys.org/">http://gcc.cookys.org/</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">三、</span><span lang="EN-US">linux</span><span style="font-family: 宋体;">内核交叉引用，从</span><span lang="EN-US">0.1</span><span style="font-family: 宋体;">到1.0，2.0，2.2，2.4，</span><st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on"><span lang="EN-US">2.6.20</span></st1:chsdate><span style="font-family: 宋体;">都有</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://lxr.linux.no/source/">http://lxr.linux.no/source/</a></span></p>
<p class="MsoNormal"><span lang="EN-US">http://www.oldlinux.org/lxr/http/source/</span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">四、</span><span lang="EN-US">C </span><span style="font-family: 宋体;">语言常见问题集</span><span lang="EN-US">(</span><span style="font-family: 宋体;">中英文</span><span lang="EN-US">)</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://c-faq-chn.sourceforge.net/">http://c-faq-chn.sourceforge.net/</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://c-faq.com/">http://c-faq.com/</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">五、操作系统相关的一些资料，包括</span><span lang="EN-US">linux</span><span style="font-family: 宋体;">源程序分析</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://osdev.gro.clinux.org/">http://osdev.gro.clinux.org</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">六、</span><span lang="EN-US">linus</span><span style="font-family: 宋体;">自传</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://www.bookcool.com/online/zhuanji/happyking-gb/0/content.htm">http://www.bookcool.com/online/zhuanji/happyking-gb/0/content.htm</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">七、嵌入式及OS开发资料（英文）</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://my.execpc.com/~geezer/">http://my.execpc.com/~geezer/</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">八、</span><span lang="EN-US">Testing and
debugging KOS</span><span style="font-family: 宋体;">（英文）</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://kos.enix.org/~d2/snapshots/kos_current/doc/testingen-html">http://kos.enix.org/~d2/snapshots/kos_current/doc/testingen-html</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">九、</span><span lang="EN-US">the Single
UNIX Specification Version 3</span><span style="font-family: 宋体;">（推荐：可作为</span><span lang="EN-US">posix</span><span style="font-family: 宋体;">的替代参考资料）</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://www.unix.org/single_unix_specification">http://www.unix.org/single_unix_specification</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
<p class="MsoNormal"><span style="font-family: 宋体;">十、</span><span lang="EN-US">OS</span><span style="font-family: 宋体;">设计参考（英文）</span></p>
<p class="MsoNormal"><span lang="EN-US"><a href="http://www.nondot.org/~sabre/os/articles">http://www.nondot.org/~sabre/os/articles</a></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/23727.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-09 21:01 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/09/23727.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第4课：中断和异常1）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/08/23600.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 23:37:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/08/23600.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23600.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/08/23600.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23600.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23600.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第4课：中断和异常1声明：转载请保留：译者：http://www.cppblog.com/jinglexy原作者：xiaoming.mo at skelix dot orgMSN &amp; Email: jinglexy at yahoo dot com dot cn目标&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/08/23600.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/23600.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-08 07:37 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/08/23600.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第3课：辅助函数）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/08/23599.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 23:36:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/08/23599.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23599.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/08/23599.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23599.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23599.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第<span lang="EN-US">3</span>课：辅助函数<span lang="EN-US"><o:p></o:p></span></span></p>
<br>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">声明：转载请保留</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">：</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"></span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">译者</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">http://www.cppblog.com/jinglexy</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">原作者：</span>xiaoming.mo at skelix dot org</p>
MSN &amp; Email: jinglexy at yahoo dot com dot cn<br><br>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">目标<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<a href="http://skelix.org/download/03.rar" target="_blank"><span lang="EN-US"><span lang="EN-US">下载源程序</span></span></a><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">这节课我们讲述的内容与操作系统暂无太大关系，但是这些基础函数非常重要，并且在后面的课程中经常用到。这就是我们经常听到的内核库。如果你对这些不是很感兴趣，知道<span lang="EN-US">kprintf</span>象<span lang="EN-US">c</span>语言里面的<span lang="EN-US">print</span>一样工作就行了。简单掠过即可。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<a name="kprintf"></a>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">C</span><span style="font-size: 12pt; font-family: 宋体;">用户库里面的<span lang="EN-US">printf</span>具有高度可伸缩性，也很容易理解，相比之下<span lang="EN-US">C</span>＋＋中的<span lang="EN-US">IO</span>运算符就比较难了。为了在屏幕上显示字符串或数据，我们现在需要实现类似<span lang="EN-US">C</span>库中的<span lang="EN-US">printf</span>，显示字符在<span lang="EN-US">B8000</span>开始的显存处。我并不像完全实现<span lang="EN-US">printf</span>的所有功能，因为<span lang="EN-US">skelix</span>内核只需要显示字符串，十进制和十六进制或二进制，正整数，字符就行了，并且需要支持可变参数。其他更高级的功能我们不会用到。<span lang="EN-US"><br>
<br>
</span>这里有一种方法来实现，我们直到象<span lang="EN-US">func(int arg1, int arg2, int arg3)</span>这样一个函数被调用时，它汇编后的指令应该如下（所有从左向右入栈的编译器应该从地球上彻底消失）：<span lang="EN-US"><br>
pushl&nbsp;&nbsp; arg3<br>
pushl&nbsp;&nbsp; arg2<br>
pushl&nbsp;&nbsp; arg1<br>
call&nbsp;&nbsp;&nbsp; func<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们看到，参数从右向左一个个入栈，参数越多，入栈越深。如果是可变参数那我们怎么知道有多少个参数呢？答案是<span lang="EN-US">printf</span>格式化字符串中参数判断：有多少个<span lang="EN-US">%X</span>，就有多少个参数要解析。在<span lang="EN-US">32</span>位模式下，所有小于<span lang="EN-US">4</span>字节的参数都被当作<span lang="EN-US">4</span>字节处理。例如一个<span lang="EN-US">char</span>型参数，入栈时就是<span lang="EN-US">int</span>型了，所以在解析参数时务必保证正确。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们这样设计<span lang="EN-US">kprintf</span>参数：<span lang="EN-US">kprintf(color,
format string, arguments...)<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第一个参数定义输出的前景<span lang="EN-US">/</span>背景颜色。我们定义了很多宏来解析栈，如果你熟悉<span lang="EN-US">C</span>语言应该很容易理解它们。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: red;">03/kprintf.c</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">#define args_list char
*&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">这个宏用例转换栈空间为字符串指针<span lang="EN-US"><br>
#define _arg_stack_size(type)&nbsp;&nbsp;&nbsp;
(((sizeof(type)-1)/sizeof(int)+1)*sizeof(int))<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">这个宏四舍五入参数大小为<span lang="EN-US">4</span>字节的倍数<span lang="EN-US"><br>
#define args_start(ap, fmt) do {&nbsp;&nbsp;&nbsp; \<br>
ap = (char *)((unsigned int)&amp;fmt + _arg_stack_size(&amp;fmt));&nbsp;&nbsp;
\<br>
} while (0)<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//
</span><span style="font-size: 12pt; font-family: 宋体;">参数将从格式化字符串后面开始解析，即<span lang="EN-US">fmt</span>就是栈顶，上面这个宏就是取参数的首地址<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
#define args_end(ap)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//
</span><span style="font-size: 12pt; font-family: 宋体;">到现在为止，什么也不做<span lang="EN-US"><br>
#define args_next(ap, type) (((type *)(ap+=_arg_stack_size(type)))[-1])<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//
</span><span style="font-size: 12pt; font-family: 宋体;">取<span lang="EN-US">&#8216;</span>当前<span lang="EN-US">&#8217;</span>参数地址，然后设置指针为下一个参数地址，暧昧的函数名！<span lang="EN-US"><br>
<br>
<span style="color: red;">03/kprintf.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">static char buf[1024] =
{-1};&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">注意没有锁保护，引用该变量的函数不可重入！<span lang="EN-US"><br>
static int ptr = -1;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">下面两个函数解析值为指定的进制数：<span lang="EN-US"><br>
static void<br>
parse_num(unsigned int value, unsigned int base)
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span>可以打印小于等于<span lang="EN-US">10</span>进制的数<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; unsigned int n = value / base;<br>
&nbsp;&nbsp;&nbsp; int r = value % base;<br>
&nbsp;&nbsp;&nbsp; if (r &lt; 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; r += base;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; --n;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if (value &gt;= base)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; parse_num(n, base);<br>
&nbsp;&nbsp;&nbsp; buf[ptr++] = (r+'0');<br>
}<br>
<br>
static
void&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//
</span>打印<span lang="EN-US">16</span>进制数<span lang="EN-US"><br>
parse_hex(unsigned int value) {<br>
&nbsp;&nbsp;&nbsp; int i = 8;<br>
&nbsp;&nbsp;&nbsp; while (i-- &gt; 0) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buf[ptr++] =
"0123456789abcdef"[(value&gt;&gt;(i*4))&amp;0xf];<br>
&nbsp;&nbsp;&nbsp; }<br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在我们来看一下<span lang="EN-US"> kprintf</span>这个函数，它支持的格式：<span lang="EN-US">%s,
%c, %x, %d, %%<br>
void<br>
kprintf(enum KP_LEVEL kl, const char *fmt, ...) {<br>
&nbsp;&nbsp;&nbsp; int i = 0;<br>
&nbsp;&nbsp;&nbsp; char *s;<br>
&nbsp;&nbsp;&nbsp; /* must be the same size as enum KP_LEVEL */<br>
&nbsp;&nbsp;&nbsp; struct KPC_STRUCT {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; COLOUR fg;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; COLOUR bg;<br>
&nbsp;&nbsp;&nbsp; } KPL[] = {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {BRIGHT_WHITE, BLACK},<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; {YELLOW, RED},<br>
&nbsp;&nbsp;&nbsp; };<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
enum KP_LEVEL {KPL_DUMP, KPL_PANIC}&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">定义在<span lang="EN-US"> include/kprintf.h, </span>它表示两种输出方案<span lang="EN-US">, KPL_DUMP </span>使用黑色背景白色前景显示字符，<span lang="EN-US">KPL_PANIC </span>使用黄色前景和红色背景。颜色常量定义在<span lang="EN-US"> include/scr.h,
</span>后面会介绍到<span lang="EN-US">.<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; args_list args;<br>
&nbsp;&nbsp;&nbsp; args_start(args, fmt);<br>
<br>
&nbsp;&nbsp;&nbsp; ptr = 0;<br>
<br>
&nbsp;&nbsp;&nbsp; for (; fmt[i]; ++i) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ((fmt[i]!='%') &amp;&amp;
(fmt[i]!='\\')) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buf[ptr++] = fmt[i];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; continue;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else if (fmt[i] == '\\') {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; /* \a \b \t \n \v \f
\r \\ */<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; switch (fmt[++i]) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'a': buf[ptr++] =
'\a'; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'b': buf[ptr++] =
'\b'; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 't': buf[ptr++] =
'\t'; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'n': buf[ptr++] =
'\n'; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'r': buf[ptr++] =
'\r'; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case '\\':buf[ptr++] =
'\\'; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; continue;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* </span><span style="font-size: 12pt; font-family: 宋体;">下面是支持的打印格式<span lang="EN-US"> */<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; switch (fmt[++i]) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 's':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; s = (char
*)args_next(args, char *);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; while (*s)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp;
buf[ptr++] = *s++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'c':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buf[ptr++] =
(char)args_next(args, int);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'x':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; parse_hex((unsigned
long)args_next(args, unsigned long));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case 'd':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; parse_num((unsigned
long)args_next(args, unsigned long), 10);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; case '%':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buf[ptr++] = '%';<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; default:<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; buf[ptr++] = fmt[i];<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; buf[ptr] = '\0';<br>
&nbsp;&nbsp;&nbsp;&nbsp;args_end(args);<br>
&nbsp;&nbsp;&nbsp; for (i=0; i&lt;ptr; ++i)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; <span style="color: red;">print_c</span>(buf[i],
KPL[kl].fg,
KPL[kl].bg);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
print_c() </span>是下层的显示函数，本文后面会有讲解<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">由于是内核程序，我们无法使用<span lang="EN-US">C</span>用户库。所以一下<span lang="EN-US">memcpy</span>，<span lang="EN-US">memset</span>，<span lang="EN-US">memcpy</span>函数需要自己实现，但是需要注意的是在<span lang="EN-US">BSD</span>系统中，即便使用了<span lang="EN-US">-nostdlib</span>，编译器仍然会产生<span lang="EN-US">System V</span>中相关的<span lang="EN-US">memcpy</span>等代码，具体情况我也不是很清除。这些函数的效率当然无法和<span lang="EN-US">linux</span>内核中的内嵌汇编相比！我们暂时这样实现它们吧。<span lang="EN-US"><br>
<span style="color: red;">03/libcc.c</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">/* </span><span style="font-size: 12pt; font-family: 宋体;">下面函数对重叠区域也进行了处理<span lang="EN-US">
*/<br>
void <br>
bcopy(const void *src, void *dest, unsigned int n) {<br>
&nbsp;&nbsp;&nbsp; const char *s = (const char *)src;<br>
&nbsp;&nbsp;&nbsp; char *d = (char *)dest;<br>
&nbsp;&nbsp;&nbsp; if (s &lt;= d)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (; n&gt;0; --n)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; d[n-1] = s[n-1];<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (; n&gt;0; --n)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *d++ = *s++;<br>
}<br>
<br>
void<br>
bzero(void *dest, unsigned int n) {<br>
&nbsp;&nbsp;&nbsp; memset(dest, 0, n);<br>
}<br>
<br>
void *<br>
memcpy(void *dest, const void *src, unsigned int n) {<br>
&nbsp;&nbsp;&nbsp; bcopy(src, dest, n);<br>
&nbsp;&nbsp;&nbsp; return dest;<br>
}<br>
<br>
void *<br>
memset(void *dest, int c, unsigned int n) {<br>
&nbsp;&nbsp;&nbsp; char *d = (char *)dest;<br>
&nbsp;&nbsp;&nbsp; for (; n&gt;0; --n)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *d++ = (char)c;<br>
&nbsp;&nbsp;&nbsp; return dest;<br>
}<br>
<br>
int<br>
memcmp(const void *s1, const void *s2, unsigned int n) {<br>
&nbsp;&nbsp;&nbsp; const char *s3 = (const char *)s1;<br>
&nbsp;&nbsp;&nbsp; const char *s4 = (const char *)s2;<br>
&nbsp;&nbsp;&nbsp; for (; n&gt;0; --n) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (*s3 &gt; *s4)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else if (*s3 &lt; *s4)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return -1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++s3;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++s4;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; return 0;<br>
}<br>
<br>
int<br>
strcmp(const char *s1, const char *s2) {<br>
&nbsp;&nbsp;&nbsp; while (*s1 &amp;&amp; *s2) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; int r = *s1++ - *s2++;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (r)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return r;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if (*s1 == *s2)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return 0<br>
&nbsp;&nbsp;&nbsp; else<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return (*s1)?1:-1;<br>
}<br>
<br>
char *<br>
strcpy(char *dest, const char *src) {<br>
&nbsp;&nbsp;&nbsp; char *p = dest;<br>
&nbsp;&nbsp;&nbsp; while ( (*dest++ = *src++))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ;<br>
&nbsp;&nbsp;&nbsp; *dest = 0;<br>
&nbsp;&nbsp;&nbsp; return p;<br>
}<br>
<br>
unsigned int<br>
strlen(const char *s) {<br>
&nbsp;&nbsp;&nbsp; unsigned int n = 0;<br>
&nbsp;&nbsp;&nbsp; while (*s++)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++n;<br>
&nbsp;&nbsp;&nbsp; return n;<br>
}<br>
<br>
<a name="print_c"></a><span style="color: red;">print_c</span></span><span style="color: red;">函数</span><span lang="EN-US"><br>
</span>直接操作显存区域一点也不方便，所以我们需要一个显示模块。这个就是我们的<span lang="EN-US">&#8216;</span>显卡驱动<span lang="EN-US">&#8217;</span>了，是不是不敢相信驱动是这么简单的事情？我们先来看一下一些常量定义：<span lang="EN-US"><br>
<span style="color: red;">03/include/scr.h</span><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">#define MAX_LINES&nbsp;&nbsp;&nbsp;
25&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//
bios</span><span style="font-size: 12pt; font-family: 宋体;">默认设置屏幕为<span lang="EN-US"> 80x25</span>大小，彩色字符模式<span lang="EN-US"><br>
#define MAX_COLUMNS&nbsp; 80<br>
#define TAB_WIDTH&nbsp;&nbsp;&nbsp;
8&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// </span>必须是：<span lang="EN-US">2^n<br>
#define VIDEO_RAM&nbsp;&nbsp;&nbsp;
0xb8000&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span>显存地址<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">我们曾简要提到过这个地址，在字符模式下，适配器使用<span lang="EN-US">0xB8000-0xBF000</span>作为视频内存。通常我们处于<span lang="EN-US">80x25</span>大小屏幕，有<span lang="EN-US">16</span>种颜色。由于一个屏幕只需要<span lang="EN-US">80x25x2</span>个字节，即<span lang="EN-US">4k</span>，所以该视频内存可以分为多个页。我们使用所有的页，但是当前只能有一个页面可见。为了显示一个字符，将用到<span lang="EN-US">2</span>个字节，一个字节是字符值，另一个字节是字符属性（即颜色）。属性字节定义如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">To display a single character, two bytes are being used
which called the character byte and the attribute byte. The character byte
contains the value of the character. The attribute byte is defined like this: <o:p></o:p></span></p>
<table class="MsoNormalTable" style="width: 51.76%;" border="1" cellpadding="0" width="51%">
    <tbody>
        <tr>
            <td style="padding: 1.5pt; width: 99pt;" width="132">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit 7<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 600.75pt;" width="801">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">闪烁<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 99pt;" width="132">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bits 6-4<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 600.75pt;" width="801">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">背景色<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 99pt;" width="132">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit 3<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 600.75pt;" width="801">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">明亮模式<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
        <tr>
            <td style="padding: 1.5pt; width: 99pt;" width="132">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">Bit3 2-0<o:p></o:p></span></p>
            </td>
            <td style="padding: 1.5pt; width: 600.75pt;" width="801">
            <p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">前景色<span lang="EN-US"><o:p></o:p></span></span></p>
            </td>
        </tr>
    </tbody>
</table>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">#define LINE_RAM&nbsp;&nbsp;&nbsp; (MAX_COLUMNS*2)<br>
#define PAGE_RAM&nbsp;&nbsp;&nbsp; (MAX_LINE*MAX_COLUMNS)<br>
<br>
#define BLANK_CHAR&nbsp;&nbsp;&nbsp; (' ')<br>
#define BLANK_ATTR&nbsp;&nbsp;&nbsp; (0x70)&nbsp;&nbsp;&nbsp;
&nbsp;&nbsp;&nbsp; /* </span><span style="font-size: 12pt; font-family: 宋体;">白色前景，黑色背景<span lang="EN-US"> */<br>
<br>
#define CHAR_OFF(x,y)&nbsp;&nbsp;&nbsp;
(LINE_RAM*(y)+2*(x))&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/* </span>计算给定坐标<span lang="EN-US">x</span>，<span lang="EN-US">y</span>的偏移地址（相对<span lang="EN-US">0xB8000</span>）<span lang="EN-US"> */<br>
Calculates the offset of a given ordinary x, y from 0xB8000<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">typedef enum COLOUR_TAG
{&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/*
</span><span style="font-size: 12pt; font-family: 宋体;">颜色表<span lang="EN-US"> */<br>
&nbsp;&nbsp;&nbsp; BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, WHITE,<br>
&nbsp;&nbsp;&nbsp; GRAY, LIGHT_BLUE, LIGHT_GREEN, LIGHT_CYAN, <br>
&nbsp;&nbsp;&nbsp; LIGHT_RED, LIGHT_MAGENTA, YELLOW, BRIGHT_WHITE<br>
} COLOUR;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">坐标系如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;___________________\<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;|&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">（<span lang="EN-US">0</span>，<span lang="EN-US">0</span>）<span lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;/<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;|<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">\|/<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<br>
<span style="color: red;">03/scr.c</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">static int csr_x = 0;<br>
static int csr_y = 0;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">由于我们只用到了一个视频页，所以上面两个变量就可以存储坐标了。关于多页显示可以在网络上查找相关资料。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
static void <br>
scroll(int lines) {&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">向上滚动屏幕多少行，就是一些内存复写。<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; short *p = (short *)(VIDEO_RAM+CHAR_OFF(MAX_COLUMNS-1,
MAX_LINES-1));<br>
&nbsp;&nbsp;&nbsp; int i = MAX_COLUMNS-1;<br>
&nbsp;&nbsp;&nbsp; memcpy((void *)VIDEO_RAM, (void
*)(VIDEO_RAM+LINE_RAM*lines),<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp; LINE_RAM*(MAX_LINES-lines));<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; for (; i&gt;=0;
--i)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">说明这个<span lang="EN-US">for</span>循环有问题，觉得应该改成下面这样：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;// for (i&nbsp;= i *&nbsp;lines;
i&gt;=0; --i)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *p-- =
(short)((BLANK_ATTR&lt;&lt;4)|BLANK_CHAR);<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">}<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">下面函数设置光标可能会引发竞态条件，但是<span lang="EN-US">print_c</span>只准备在内核中使用，所以没有关中断。它可能会引起一些<span lang="EN-US">bug</span>，但是我没有找到。译注：全局变量没有锁保护在设计上就是一种错误。这里的代码保护确实是没有做！读者应用到自己的内核时要小心了。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">void <br>
set_cursor(int x, int y) {<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;csr_x = x;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;csr_y = y;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; outb(0x0e,
0x3d4);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><span style="font-size: 12pt; font-family: 宋体;">设置光标高<span lang="EN-US">8</span>位的准备工作<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;
outb(((csr_x+csr_y*MAX_COLUMNS)&gt;&gt;8)&amp;0xff,
0x3d5);&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">设置光标高<span lang="EN-US">8</span>位<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; outb(0x0f,
0x3d4);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">设置光标低<span lang="EN-US">8</span>位的准备工作<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; outb(((csr_x+csr_y*MAX_COLUMNS))&amp;0xff,
0x3d5);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span>设置光标低<span lang="EN-US">8</span>位<span lang="EN-US">&nbsp;&nbsp;&nbsp;<br>
}<br>
<br>
void<br>
get_cursor(int *x, int *y) {<br>
&nbsp;&nbsp;&nbsp; *x = csr_x;<br>
&nbsp;&nbsp;&nbsp; *y = csr_y;<br>
}<br>
<br>
void <br>
print_c(char c, COLOUR fg, COLOUR bg) {<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">// </span><span style="font-size: 12pt; font-family: 宋体;">用这个函数来显示一个具体的字符到屏幕，我们可以把它看作<span lang="EN-US">&#8216;</span>显卡驱动<span lang="EN-US">&#8217;<br>
&nbsp;&nbsp;&nbsp; char *p; <br>
&nbsp;&nbsp;&nbsp; char attr;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; p = (char *)VIDEO_RAM+CHAR_OFF(csr_x,
csr_y);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">取光标位置<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp; attr =
(char)(bg&lt;&lt;4|fg);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
// </span>属性<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; switch (c) {<br>
&nbsp;&nbsp;&nbsp; case '\r':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; csr_x = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; case '\n':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (; csr_x&lt;MAX_COLUMNS; ++csr_x) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *p++ = BLANK_CHAR;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *p++ = attr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; case '\t':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; c =
csr_x+TAB_WIDTH-(csr_x&amp;(TAB_WIDTH-1));<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; c = c&lt;MAX_COLUMNS?c:MAX_COLUMNS;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; for (; csr_x&lt;c; ++csr_x) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *p++ = BLANK_CHAR;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *p++ = attr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; case '\b':<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if ((! csr_x) &amp;&amp; (! csr_y))<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; return;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (! csr_x) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; csr_x = MAX_COLUMNS -
1;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; --csr_y;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; } else<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; --csr_x;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ((short *)p)[-1] = (short)((BLANK_ATTR&lt;&lt;4)|BLANK_CHAR);<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; default:<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *p++ = c; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; *p++ = attr;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++csr_x;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; break;<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; if (csr_x &gt;= MAX_COLUMNS) {<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; csr_x = 0;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; if (csr_y &lt; MAX_LINES-1)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; ++csr_y;<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; else <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; scroll(1);<br>
&nbsp;&nbsp;&nbsp; }<br>
&nbsp;&nbsp;&nbsp; set_cursor(csr_x,
csr_y);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;// </span><span style="font-size: 12pt; font-family: 宋体;">设置光标位置<span lang="EN-US"><br>
}<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">函数比较简单，没有分析的必要了，大家自己琢磨吧。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
</span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/23599.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-08 07:36 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/08/23599.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第2课：保护模式）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/08/23598.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 23:35:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/08/23598.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23598.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/08/23598.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23598.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23598.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第2课：保护模式声明：转载请保留：译者：http://www.cppblog.com/jinglexy原作者：xiaoming.mo at skelix dot orgMSN &amp; Email: jinglexy at yahoo dot com dot cn目标&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;下载源程序...&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/08/23598.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/23598.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-08 07:35 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/08/23598.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（第1课：引导程序）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/08/23597.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 23:34:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/08/23597.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23597.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/08/23597.html#Feedback</comments><slash:comments>6</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23597.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23597.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第<span lang="EN-US">1</span>课：引导程序<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">声明：转载请保留</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">：</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"></span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">译者</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">http://www.cppblog.com/jinglexy</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">原作者：</span>xiaoming.mo at skelix dot org</p>
MSN &amp; Email: jinglexy at yahoo dot com dot cn<br><br><br>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">目标：</span><span style="font-size: 12pt; font-family: 宋体;">使<span lang="EN-US">"system"</span>从软盘启动，并打印<span lang="EN-US">"Hello World!" <a href="http://skelix.org/download/01.rar" target="_blank"><span lang="EN-US"><span lang="EN-US">下载源程序</span></span></a><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">内存寻址</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">处理器以<span lang="EN-US">&#8216;</span>字节<span lang="EN-US">&#8217;</span>管理和访问内存，每个字节都有独立的地址，即物理地址。有两种地址映射方式：分段和分页，<span lang="EN-US">skelix</span>内核中都用到了。<a name="Memory_Addressing"></a>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
</span><span style="font-size: 12pt; font-family: 宋体;">段对于我们来说再熟悉不过了，先回顾一下<span lang="EN-US">dos</span>时期的段吧。它是一个<span lang="EN-US">16</span>位的寄存器，所以最多可以直接访问<span lang="EN-US">2^16</span>字节的内存，即<span lang="EN-US">64K</span>。这对应用程序来说太少了，于是<span lang="EN-US">Intel</span>使用<span lang="EN-US">Segment:Offset</span>结合方式来表示一个虚拟地址。段寄存器左移<span lang="EN-US">4</span>位加上偏移就得到实际的物理地址了。例如，<span lang="EN-US">0x<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7c</st1:chmetcnv>00:0x0189</span>表示物理地址<span lang="EN-US">0x<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7c</st1:chmetcnv>189</span>，而不是<span lang="EN-US">0x<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7c</st1:chmetcnv>000189</span>。计算过程如下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7C</st1:chmetcnv>000<br>
+ 0189<br>
-------<br>
&nbsp;<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7C</st1:chmetcnv>189<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在我们来计算最大可以访问的地址：<span lang="EN-US">FFFF:FFFF<br>
<br>
&nbsp;FFFF0<br>
+ FFFF<br>
-------<br>
10FFEF<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">这个范围是<st1:chmetcnv unitname="m" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on"><span lang="EN-US">1M</span></st1:chmetcnv><span lang="EN-US"> + 65519 bytes, </span>因为在<span lang="EN-US">80386</span>中使用了<span lang="EN-US">20</span>位地址线，所以可以额外多访问<span lang="EN-US">65519</span>个字节虚拟地址，例如地址<span lang="EN-US">0x100010</span>被映射到地址<span lang="EN-US">0x10</span>，访问这两个地址是等价的。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">表示同一个物理地址有多种方式，例如<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on"><span lang="EN-US">07C</span></st1:chmetcnv><span lang="EN-US">0:0000</span>和<span lang="EN-US">0000:<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7C</st1:chmetcnv>00 </span>就是一样的。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">另一个概念是线性地址，这个是<span lang="EN-US">32</span>位地址，只有当分页机制开启时才有效，文章后面会提到它。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">引导过程</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">当系统上电或<span lang="EN-US">RESET</span>时，处理器将执行一些列的初始化，寄存器被设置成非预知状态，并且<span lang="EN-US">cpu</span>处于实模式。也许你想知道<span lang="EN-US">cpu</span>是怎样设置<span lang="EN-US">segment:offset</span>为物理地址<span lang="EN-US">FFFF0</span>的（<span lang="EN-US">0xf000:0xfff0</span>就是<span lang="EN-US">bios</span>入口地址），这是因为<span lang="EN-US">cs</span>寄存器有一个非可见部分，它保存了<span lang="EN-US">ffff:0000</span>地址，并且<span lang="EN-US">cs</span>在初始化时会被装入<span lang="EN-US">f000</span>值。此后以正常方式使用它。当<span lang="EN-US">bois</span>取得控制权后，根据用户配置（从软驱，硬盘，或<span lang="EN-US">cdrom</span>）中读取第一个<span lang="EN-US">sector</span>到<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on"><span lang="EN-US">00007C</span></st1:chmetcnv><span lang="EN-US">00</span>，并跳转到该地址执行（就是引导程序<span lang="EN-US">bootstrap</span>）。在<span lang="EN-US">bootstrap</span>中我们可以使用<span lang="EN-US">bios</span>中断，但是进入<span lang="EN-US">kernel</span>后就不能再使用了。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
</span><span style="font-size: 12pt; font-family: 宋体; color: blue;">程序一：使用<span lang="EN-US">as</span>和<span lang="EN-US">ld</span>的范例</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">你可以在下载源程序的<span style="color: red;" lang="EN-US">01/first.cry/bootsect.s</span><span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.text&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;.text</span><span style="font-size: 12pt; font-family: 宋体;">表示代码段<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
.globl&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start</span>表示<span lang="EN-US">start</span>可以用作外部符号<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
.code16&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;GCC</span>默认使用<span lang="EN-US">32</span>位地址和操作数，这里告诉它使用<span lang="EN-US">16</span>位<span lang="EN-US"><br>
start:<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
start&nbsp;&nbsp;&nbsp;&nbsp; </span>死循环<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">.org&nbsp;&nbsp;&nbsp; 0x1fe,&nbsp;&nbsp;
0x90&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: blue;">.org NEW-LC,
FILL</span></span><span style="font-size: 12pt; font-family: 宋体; color: blue;">，</span><span style="font-size: 12pt; font-family: 宋体; color: black;">说明：这里填充<span lang="EN-US">0x90</span>，是<span lang="EN-US">nop</span>指令的机器码<span lang="EN-US"><br>
</span></span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">.word&nbsp;&nbsp; 0xaa55<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">讲解：<span lang="EN-US">.org</span>指令指示下一个数据地址，为了编译这个程序，我们写了一个<span lang="EN-US">Makefile</span>，总不能老是敲命令吧，呵呵。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">网络上可以找到很多写<span lang="EN-US">Makefile</span>的资料，编译选项才是我们关注的焦点。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: red;">01/first.cry/Makefile</span><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">AS=as&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
gcc</span><span style="font-size: 12pt; font-family: 宋体;">汇编工具<span lang="EN-US"><br>
LD=ld&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
gcc</span>连接器<span lang="EN-US"><br>
<br>
.s.o:<br>
&nbsp;&nbsp;&nbsp;&nbsp;${AS} -a $&lt; -o $*.o &gt;$*.map<br>
<br>
all: final.img<br>
<br>
final.img: bootsect<br>
&nbsp;&nbsp;&nbsp; mv bootsect final.img<br>
<br>
bootsect: bootsect.o<br>
&nbsp;&nbsp;&nbsp; ${LD} --oformat binary -N -e start -Ttext 0x<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7c</st1:chmetcnv>00 -o bootsect $&lt;<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">讲解：<span lang="EN-US">ld</span>可以被配置为支持多于一种的目标文件<span lang="EN-US">. binary</span>表示没有程序头和其他信息，仅仅是一些裸数据。如果没有这个选项，将被默认链接为<span lang="EN-US">elf</span>格式。<span lang="EN-US">-N</span>把<span lang="EN-US">text</span>和<span lang="EN-US">data</span>节设置为可读写。<span lang="EN-US">-Ttext</span>将<span lang="EN-US">text</span>节起始地址设置为<span lang="EN-US">0x<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7c</st1:chmetcnv>00</span>（在<span lang="EN-US">jmp</span>和数据引用等重定位链接时会用到这个参考值），所有的引用地址都是在<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on"><span lang="EN-US">7c</span></st1:chmetcnv><span lang="EN-US">00</span>这个地址上加出来的。<span lang="EN-US">-e</span>选项指定程序入口点<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在我们运行<span lang="EN-US">make</span>指令编译一下：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">[root@root~/source/os/skelix/01/first.cry]$ ls<br>
<span style="color: green;">bootsect.s&nbsp; COPYING&nbsp; Makefile</span><br>
[root@root~/source/os/skelix/01/first.cry]$ make<br>
as -a bootsect.s -o bootsect.o &gt;bootsect.map<br>
ld --oformat binary -N -e start -Ttext 0x<st1:chmetcnv unitname="C" sourcevalue="7" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">7c</st1:chmetcnv>00 -o bootsect bootsect.o<br>
mv bootsect final.img<br>
[root@root~/source/os/skelix/01/first.cry]$ ls<br>
<span style="color: green;">bootsect.map&nbsp; bootsect.o&nbsp;</span>
bootsect.s&nbsp; COPYING&nbsp; <span style="color: green;">final.img</span>&nbsp;
Makefile<br>
[root@root~/source/os/skelix/01/first.cry]$<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">现在，我们启动<span lang="EN-US">vmware</span>，运行，载入软驱映象文件<span lang="EN-US">"final.img"</span>，我们得到一个黑屏，这是正确的，因为我们什么也没有做。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">程序一：显示 <span lang="EN-US">Hello World!</span></span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">好了，上面的黑屏程序并不是太好玩，现在我们尝试在上面打印<span lang="EN-US">"Hello World!"<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: red;" lang="EN-US">01/hello.world/bootsect.s</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .text<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .globl&nbsp; start<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; .code16<br>
start:<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; code<br>
msg:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
</span><span style="font-size: 12pt; font-family: 宋体;">使用<span lang="EN-US">jmp</span>指令跳过该变量，这是我们为什么在<span lang="EN-US">Makefile</span>使用<span lang="EN-US">-N</span>链接选项了<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .string "Hello World!\x0"<br>
code:<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; movw&nbsp;&nbsp;&nbsp; $0xb800,%ax<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movw&nbsp;&nbsp;&nbsp;
%ax,&nbsp;&nbsp;&nbsp;
%es&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;es</span>段设置成<span lang="EN-US">B800</span>，如前所述，<span lang="EN-US">segment:offset</span>地址映射方式，它指向<span lang="EN-US">B8000</span>，<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">这意味着第一个字节地址是<span lang="EN-US">0</span>（映射到<span lang="EN-US">B8000</span>），属性字节是<span lang="EN-US">1</span>（映射到<span lang="EN-US">B8001</span>）<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;B8001</span><span style="font-size: 12pt; font-family: 宋体;">值设置为<span lang="EN-US">0x07</span>可以将这个<span lang="EN-US">byte</span>颜色设置为黑底白字。<span lang="EN-US"><br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorw&nbsp;&nbsp;&nbsp;
%ax,&nbsp;&nbsp;&nbsp; %ax<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; movw&nbsp;&nbsp;&nbsp;
%ax,&nbsp;&nbsp;&nbsp; %ds<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
movw&nbsp;&nbsp;&nbsp; $msg,&nbsp;&nbsp;
%si&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">为<span lang="EN-US">movsb</span>指令设置正确的<span lang="EN-US">si</span>和<span lang="EN-US">di<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; xorw&nbsp;&nbsp;&nbsp;
%di,&nbsp;&nbsp;&nbsp; %di<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; cld<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; movb&nbsp;&nbsp;&nbsp; $0x07,&nbsp;
%al&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>字的颜色<span lang="EN-US"><br>
<br>
1:<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; cmp&nbsp;&nbsp;&nbsp;&nbsp;
$0,&nbsp;&nbsp;&nbsp; (%si)<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; je&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <st1:chmetcnv unitname="F" sourcevalue="1" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">1f</st1:chmetcnv>&nbsp;&nbsp;&nbsp; <br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; movsb<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; stosb<br>
&nbsp;&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 1b<br>
1:&nbsp; &nbsp;&nbsp;&nbsp; jmp&nbsp;&nbsp;&nbsp;&nbsp; 1b<br>
<br>
.org&nbsp;&nbsp;&nbsp; 0x1fe,&nbsp; 0x90<br>
.word&nbsp;&nbsp; 0xaa55<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: center;" align="center"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p>
</span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/23597.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-08 07:34 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/08/23597.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（环境篇）（原创）  </title><link>http://www.cppblog.com/jinglexy/archive/2007/05/08/23596.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 23:32:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/08/23596.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23596.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/08/23596.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23596.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23596.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">第<span lang="EN-US">0</span>课：环境需求<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">声明：转载请保留</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">：</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"></span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">译者</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">：</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">http://www.cppblog.com/jinglexy</span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">原作者：</span>xiaoming.mo at skelix dot org</p>
<p class="MsoNormal" style="text-align: left;" align="left">MSN &amp; Email: jinglexy at yahoo dot com dot cn<br><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"> <o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;" lang="EN-US">GCC</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"> <br>
Skelix </span><span style="font-size: 12pt; font-family: 宋体;">使用<span lang="EN-US">c</span>语言编写，当然也用了汇编语言（<span lang="EN-US">at&amp;t</span>风格），在<span lang="EN-US">linux</span>下使用<span lang="EN-US">gcc</span>编译。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">[root@root ~]$ gcc -v<br>
<st1:city w:st="on"><st1:place w:st="on">Reading</st1:place></st1:city> specs
from /usr/lib/gcc/i386-redhat-linux/<st1:chsdate year="1899" month="12" day="30" islunardate="False" isrocdate="False" w:st="on">3.4.2</st1:chsdate>/specs<br>
Configured with: ../configure --prefix=/usr --mandir=/usr/share/man
--infodir=/usr/share/info --enable-shared --enable-threads=posix
--disable-checking --with-system-zlib --enable-__cxa_atexit
--disable-libunwind-exceptions --enable-java-awt=gtk --host=i386-redhat-linux<br>
Thread model: posix<br>
gcc version 3.4.2 20041017 (Red Hat 3.4.2-6.fc3)<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">在每篇教程中都给出了源程序和软盘映象文件，你可以直接使用它们。如果你需要编译这些源程序，编译环境必须正确。我们推荐的环境是<span lang="EN-US">linux2.6.x</span>内核，<span lang="EN-US">gcc3.x</span>编译器。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">由于在源程序中使用了<span lang="EN-US">__asm__, __attribute__, __extention__</span>，以及<span lang="EN-US">gcc</span>内嵌汇编，还有<span lang="EN-US">unsigned long long(</span>直到<span lang="EN-US">C99</span>才开始支持<span lang="EN-US">)</span>；如果你使用了其他编译器，需要修改对应的源程序。且编译器必须是<span lang="EN-US">32</span>位，这样做的目的是保持源程序简洁清晰。<span lang="EN-US"><br>
<br>
</span>对于<span lang="EN-US">windows</span>用户可以使用<span lang="EN-US"> cygwin</span>，它提供了<span lang="EN-US">windows</span>下的<span lang="EN-US">linux</span>环境。不过我没有尝试使用它，因为我的电脑上没有安装<span lang="EN-US">windows</span>操作系统。也可以在你的<span lang="EN-US">windows</span>系统上安装一个虚拟机上的<span lang="EN-US">linux</span>，如果你的电脑足够快的话。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><br>
<span style="color: blue;">VMWARE</span><br>
<br>
</span><span style="font-size: 12pt; font-family: 宋体;">为了运行教程中的范例，一个虚拟机必不可少，<span lang="EN-US">virtual pc2007</span>已经可以免费使用了，在<span lang="EN-US">M$</span>的官方网站上可以找到下载。当然也可以使用<span lang="EN-US">qemu</span>和<span lang="EN-US">bochs</span>之类的虚拟机。推荐的虚拟机是<span lang="EN-US">VMWARE</span>。<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><a name="Things_Are_Good_To_Know"></a>
</p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: helvetica; color: blue;" lang="EN-US">Things Are Good To Know</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US"><br>
<br>
</span><span style="font-size: 12pt; font-family: 宋体;">如果能看懂</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">Makefile</span><span style="font-size: 12pt; font-family: 宋体;">最好了，这是</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">*nix</span><span style="font-size: 12pt; font-family: 宋体;">程序员必须掌握的一项基本知识。另外，如果你熟悉内存地址映射，中断，异常，</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">GDT</span><span style="font-size: 12pt; font-family: 宋体;">，</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">LDT</span><span style="font-size: 12pt; font-family: 宋体;">，</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">IDT</span><span style="font-size: 12pt; font-family: 宋体;">，分页机制，范围端口就更好了。当然不懂也没关系，</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">Intel</span><span style="font-size: 12pt; font-family: 宋体;">的三卷手册是案头必备：</span><span style="font-size: 12pt; font-family: helvetica;" lang="EN-US">http://www.intel.com</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">IA-32 Intel Architecture Software Developer's Manual
Volume1: Basic Architecture<br>
IA-32 Intel Architecture Software Developer's Manual Volume<st1:chmetcnv unitname="a" sourcevalue="2" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">2A</st1:chmetcnv>: Instruction Set Reference: <st1:city w:st="on">A-M</st1:city><br>
<st1:state w:st="on">IA</st1:state>-32 Intel Architecture Software Developer's
Manual Volume2B: Instruction Set Reference: <st1:place w:st="on"><st1:city w:st="on">N-Z</st1:city><br>
<st1:state w:st="on">IA</st1:state></st1:place>-32 Intel Architecture Software
Developer's Manual Volume<st1:chmetcnv unitname="a" sourcevalue="3" hasspace="False" negative="False" numbertype="1" tcsc="0" w:st="on">3A</st1:chmetcnv>:
System Programming Guide Part1<br>
IA-32 Intel Architecture Software Developer's Manual Volume3B: System
Programming Guide Part2<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;">读者对这些东西不必紧张，我在教程中会解释相关的知识。<span lang="EN-US">c</span>语言和汇编是最基本的要求，能够很清楚的了解什么是堆和栈。关于<span lang="EN-US">c</span>语言的数据成千上万，但是保护模式方面的书籍比哈雷慧星还少，据说每<span lang="EN-US">76</span>年可以买到一本，如果你足够幸运的话：）<a name="Color_Pattern"></a><span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: blue;">风格约定</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: black;">原文中的格式被擅自去掉了，翻译后的风格应该可以一看就懂。</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal"><span lang="EN-US"><o:p>&nbsp;</o:p></span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/23596.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-08 07:32 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/08/23596.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>自己动手写内核（序）（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/08/23595.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 23:30:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/08/23595.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23595.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/08/23595.html#Feedback</comments><slash:comments>8</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23595.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23595.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 我对深入研究系统内部非常感兴趣，在大学课程中学习了编译原理相关课程。尝试写过一个编译器，不过它看起来更像一个汇编器。后来开始使用FreeBSD，我对它到底怎么实现的感到很好奇，于是找了一份源代码开始阅读，和你想象的一样，我在数百万行源程序中深陷泥潭。我需要一把来复枪，结果确找到了一堆加农炮：）<br><br>后来，我找到了"skelix", 一个os内核，运行在i386机器上，支持多任务，分页机制，虚拟内存，文件系统等。这个tutorial教你怎样一步一步实现skelix，虽然它看起来象一个玩具。这样做的好处是看起来更清晰一些。如果你发现bug或好的建议可以告诉原作者：xiaoming.mo at skelix dot org。译者：jinglexy at yahoo dot com dot cn（email and msn both），上海体育馆。预计7月份翻译完成（2007年），因为自己的事情比较多，只能偶尔译译，进度大约2周译1课吧，也可能快些，如果有帮忙的就更欢迎了。最终整理的文档会做成一个chm或pdf文件发布在http://www.cppblog.com/jinglex&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/08/23595.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/23595.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-08 07:30 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/08/23595.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Debian 安装记录（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/07/23557.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 07 May 2007 05:23:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/07/23557.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23557.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/07/23557.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23557.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23557.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: debian是一个很方便的linux发行版，deb包管理机制使得软件的安装和管理非常简单。etch版本也于2007.4.8发布正式版本，这里简单介绍从基本系统到X环境的安装，及一些应用软件。写的很简洁，一些相关知识还是留给读者自己查资料学习吧。&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/05/07/23557.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/23557.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-07 13:23 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/07/23557.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一份可供打印的debian指令集（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/05/03/23368.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Thu, 03 May 2007 04:41:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/05/03/23368.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/23368.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/05/03/23368.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/23368.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/23368.html</trackback:ping><description><![CDATA[归纳出来的debian指令集，可能对某些人有帮助吧，下载地址：<br>http://www.cppblog.com/Files/jinglexy/40_debian_cmd.rar<br><img src ="http://www.cppblog.com/jinglexy/aggbug/23368.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-05-03 12:41 <a href="http://www.cppblog.com/jinglexy/archive/2007/05/03/23368.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>在用户程序中使用linux内核list（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/23/22630.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Mon, 23 Apr 2007 04:14:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/23/22630.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22630.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/23/22630.html#Feedback</comments><slash:comments>4</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22630.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22630.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 在我们日常程序中，常碰到写链表的情况。对于c＋＋程序，stl提供了list和vector两个模板，使用起来很方便。但是很多环境下，我们只能使用c，大多数人都是自己封装相关接口，花费了不必要的时间。linux内核提供了基于面向对象思想的链表：include/linux/list.h。通过简单的修改就可以用到我们的用户程序中去。&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/04/23/22630.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/22630.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-23 12:14 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/23/22630.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用grub中的内核demo（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/20/22392.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 20 Apr 2007 09:30:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/20/22392.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22392.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/20/22392.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22392.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22392.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.       下载grub-0.97源程序解压缩，进入到docs目录。找到boot.S  kernel.c  multiboot.h这三个文件，就是我们的试验对象。原理可以搜索多重引导规范multiboot，在grub的official site可以找到。有不清楚的过程可以和我联系（msn及邮件都是这个：jinglexy at yahoo dot com dot cn）作者：http://www.cppblog.com/jinglexy上海体育馆<br><br>2.       建立testos.lds链接脚本：<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/04/20/22392.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/22392.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-20 17:30 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/20/22392.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>使用grub加载自己的os及bochs等杂乱笔记（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/20/22391.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Fri, 20 Apr 2007 09:29:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/20/22391.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22391.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/20/22391.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22391.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22391.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 第一节：使用minix硬盘映象<br>bochs主页（http://sourceforge.net/projects/bochs）上有个minix2.0映象，<br>编译器和源代码映象文件都已经有了，如果要mount到你自己的机器上编辑源程序，<br>可以使用下面的linux指令，为什么是1024和5669888，分析下硬盘分区表就知道了。<br>（1024 ＝ 512 * 2； 5669888 = 512 * 11074，11074即2B42）<br>/sbin/losetup /dev/loop6 a.img -o 1024<br>mount -t minix -o loop /dev/loop6 mnt1<br>ls mnt1&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/04/20/22391.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/22391.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-20 17:29 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/20/22391.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>pinfo指令（man替代软件）简介等若干杂乱笔记（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/19/22300.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Thu, 19 Apr 2007 06:02:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/19/22300.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22300.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/19/22300.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22300.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22300.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: （一）虽然man帮助给了我们足够多的信息，但有时候可能还是不够多。使用info令需要对emacs有些了解，最好是熟练。这个对习惯vi的用户来说可能比较痛苦，比如说我：）文档转载请保留：jinglexy at yahoo dot com dot cn（msn和邮件都是这个）。http://www.cppblog.com/jinglexy<br><br>好在有个叫pinfo的软件包，使用lynx操作方式。pinfo快捷键定义在/etc/pinforc文档中，如果看到不爽的可以更改。常用的快捷键整理在下面表格中（vi操作风格的命令用蓝色标识）<br>&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/04/19/22300.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/22300.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-19 14:02 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/19/22300.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>gcc, as, ld的一些笔记（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/19/22298.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Thu, 19 Apr 2007 05:34:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/19/22298.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22298.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/19/22298.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22298.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22298.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 1.本文不是教程，只是描述c语言（gcc环境），编译器，连接器，加载器，at&t汇编，ia32一些相关知识和笔记，很多需要深入的地方需要大家寻找相关的资料学习。如果发现错误，请留言或通知我jinglexy at yahoo dot com dot cn，这个是我的msn。打字不易，请转载时保留作者：http://www.cppblog.com/jinglexy&nbsp;&nbsp;<a href='http://www.cppblog.com/jinglexy/archive/2007/04/19/22298.html'>阅读全文</a><img src ="http://www.cppblog.com/jinglexy/aggbug/22298.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-19 13:34 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/19/22298.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>linux学习的一些记录（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/18/22220.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 18 Apr 2007 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/18/22220.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22220.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/18/22220.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22220.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22220.html</trackback:ping><description><![CDATA[<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">1.whereis </span><span style="font-size: 12pt; font-family: 宋体;">和<span lang="EN-US">
which </span>的区别<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;which: </span><span style="font-size: 12pt; font-family: 宋体;">只在<span lang="EN-US">PATH</span>环境变量中寻找文件<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; whereis: </span><span style="font-size: 12pt; font-family: 宋体;">在系统定义的目录中寻找<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">2.</span><span style="font-size: 12pt; font-family: 宋体;">根据关键字查找<span lang="EN-US">man</span>页<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">举例：<span lang="EN-US">apropos split&nbsp; </span>或者<span lang="EN-US">&nbsp; man -k split<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">3.sed</span><span style="font-size: 12pt; font-family: 宋体;">示例：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; sed -e s/root/toor/g /etc/passwd&nbsp;&gt;
~/test.out&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">替换<span lang="EN-US"> /etc/passwd</span>中的<span lang="EN-US">root</span>为<span lang="EN-US">toor</span>输出到<span lang="EN-US">~/test.out<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; sed -e 's/root/toor/g; s/ftp/ptf/g'
/etc/passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">使用<span lang="EN-US"> -e </span>指定多个命令<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; sed -e 's/root/toor/g' -e ' s/ftp/ptf/g'
/etc/passwd&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">同上<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">使用命令文件：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;/* test.sed </span><span style="font-size: 12pt; font-family: 宋体;">开始，不包含本行<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;s/root/toor/g<br>
&nbsp;&nbsp;s/ftp/ptf/g</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;/* test.sed </span><span style="font-size: 12pt; font-family: 宋体;">结束，不包含本行<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">指令：<span lang="EN-US">sed -f
test.sed /etc/passwd<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">4.awk</span><span style="font-size: 12pt; font-family: 宋体;">示例：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; awk '{print $0}'
/etc/passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;$0</span><span style="font-size: 12pt; font-family: 宋体;">表示完整的输入记录<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; awk -F":" '{print $1}'
/etc/passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">打印第一列，以：为分隔符<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; awk -F":" '{print "username:
"$1 "\t\t\t user id: "$3}'
/etc/passwd&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">格式化并打印<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">使用命令文件：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;/* test.awk </span><span style="font-size: 12pt; font-family: 宋体;">开始，不包含本行<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;BEGIN{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; FS=":"<br>
&nbsp; }<br>
&nbsp; {printf "username: "$1 "\t\t\t user id:
"$3"\n"}<br>
&nbsp;&nbsp;END{<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf "all done processing
/etc/passwd\n"<br>
&nbsp; }</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;/* test.awk </span><span style="font-size: 12pt; font-family: 宋体;">结束，不包含本行<span lang="EN-US"> */<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; </span><span style="font-size: 12pt; font-family: 宋体;">指令：<span lang="EN-US">awk -f
test.awk /etc/passwd<o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">5.shell</span><span style="font-size: 12pt; font-family: 宋体;">脚本<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; 1)</span><span style="font-size: 12pt; font-family: 宋体;">特殊变量：<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;?</span><span style="font-size: 12pt; font-family: 宋体;">前一个命令输出状态<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;0</span><span style="font-size: 12pt; font-family: 宋体;">当前脚本名<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1~9</span><span style="font-size: 12pt; font-family: 宋体;">参数<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; 2)</span><span style="font-size: 12pt; font-family: 宋体;">范例<span lang="EN-US">1</span>，使用<span lang="EN-US">if</span>语句<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;#!/bin/bash</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;echo "guest
the select color"<br>
&nbsp;&nbsp;&nbsp;&nbsp;read COLOR</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;if [ $COLOR =
"yellow" ]&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;then<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo
"you are correct"<br>
&nbsp;&nbsp;&nbsp;&nbsp;elif [ $COLOR = "blue" ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;then<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo
"you are correct also"<br>
&nbsp;&nbsp;&nbsp;&nbsp;fi</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;3)</span><span style="font-size: 12pt; font-family: 宋体;">范例<span lang="EN-US">2</span>，使用<span lang="EN-US">case</span>语句<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;#!/bin/bash</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;case "$1"
in<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; start)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
echo "start......"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
;;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; stop)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
echo "stop......"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
;;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; status)<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
echo "status......"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
;;&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *)&nbsp; <br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
echo "usage: $0 {start | stop | status}"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
;;&nbsp;&nbsp;<br>
&nbsp;&nbsp;&nbsp;&nbsp;esac</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;4)</span><span style="font-size: 12pt; font-family: 宋体;">范例<span lang="EN-US">3</span>，使用迭代流程<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;#!/bin/bash</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;echo "guest
color: red, blue or orange\n"<br>
&nbsp;&nbsp;&nbsp;&nbsp;read COLOR</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;while [ $COLOR !=
"orange" ]<br>
&nbsp;&nbsp;&nbsp;&nbsp;do<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;echo
"incorrect, try again"<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;read
COLOR<br>
&nbsp;&nbsp;&nbsp;&nbsp;done</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体; color: fuchsia;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;echo
"correct"</span><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US"><o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; 5)</span><span style="font-size: 12pt; font-family: 宋体;">使用双引号进行命令替换<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; lines="$(wc -l 3.sh)"<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; echo $lines<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;<o:p></o:p></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp; 6)</span><span style="font-size: 12pt; font-family: 宋体;">测试文件<span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp; -d
file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">目录 <span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;-e
file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">存在 <span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;-r
file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">可读 <span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;-w
file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">可写 <span lang="EN-US"><o:p></o:p></span></span></p>
<p class="MsoNormal" style="text-align: left;" align="left"><span style="font-size: 12pt; font-family: 宋体;" lang="EN-US">&nbsp;&nbsp;&nbsp;&nbsp;-x
file&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="font-size: 12pt; font-family: 宋体;">可执行 <span lang="EN-US"><o:p></o:p></span></span></p><img src ="http://www.cppblog.com/jinglexy/aggbug/22220.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-18 15:58 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/18/22220.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>fpu, mmx及sse的一些 介绍（原创）</title><link>http://www.cppblog.com/jinglexy/archive/2007/04/18/22218.html</link><dc:creator>天衣有缝</dc:creator><author>天衣有缝</author><pubDate>Wed, 18 Apr 2007 07:57:00 GMT</pubDate><guid>http://www.cppblog.com/jinglexy/archive/2007/04/18/22218.html</guid><wfw:comment>http://www.cppblog.com/jinglexy/comments/22218.html</wfw:comment><comments>http://www.cppblog.com/jinglexy/archive/2007/04/18/22218.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/jinglexy/comments/commentRss/22218.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/jinglexy/services/trackbacks/22218.html</trackback:ping><description><![CDATA[为什么要需要FPU和MMX/SSE？<br>提供了SIMD环境（single instruction multi data），即单指令多数据。<br>内嵌浮点运算单元，64及128位寄存器等。甚至sin/cos等数学函数也囊括其中，<br>著名的xvid项目就是使用gcc编译后使用MMX/SSE优化汇编的典型案例。<br><br>转载请注明原创：http://www.cppblog.com/jinglexy<br>msn and mail: jinglexy at yahoo dot com dot cn 上海体育馆2007.4.18<br><br>FPU: 8个80位浮点寄存器（数据），16位状态寄存器，16位控制寄存器，16为标识寄存器。<br>&nbsp;&nbsp;&nbsp;&nbsp; 使用FPU指令对这些寄存器进行操作，这些寄存器构成一个循环栈，st7栈底，st0栈顶，<br>&nbsp;&nbsp;&nbsp;&nbsp; 当一个值被压入时，被存入st0，原来st0中的值被存入st7<br>MMX: 将8个FPU寄存器重命名为8个64位MMX寄存器，即mm0到mm7。<br>&nbsp;&nbsp;&nbsp;&nbsp; 57条MMX指令，加快了整形浮点运算，但是对于复杂浮点运算无帮助<br><br>SSE: 8个128位寄存器（从xmm0到xmm7），MXSCR寄存器，EFLAGS寄存器，专有指令（复杂浮点运算）<br>SSE2: 寄存器和SSE相同，增加了5种数据类型（都是128位），专有指令<br>SSE3: 仅增加了几个新的指令<br><br>由于MMX使用的寄存器影射到FPU寄存器上，所以MMX指令执行前，需要保存FPU堆栈。<br><br>示例1，FPU寄存器及指令使用（下面所有程序都使用at&amp;t风格汇编）：<br>data1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .byte 0x34, 0x12, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00<br>data2:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .byte 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00<br>.section .text<br>.globl _start<br>_start:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nop<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fbld&nbsp; data1&nbsp;&nbsp;&nbsp;&nbsp; 压入st0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fimul data2&nbsp;&nbsp;&nbsp;&nbsp; st0中的值和data2相乘，保存在st0中<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; fbstp data1&nbsp;&nbsp;&nbsp;&nbsp; st0弹出到内存44<br><br><br>示例2, SSE寄存器及指令使用<br>.lcomm data 16<br>value1:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .float 12.34, 2345.543, -3493.2, 0.44901<br>value2:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; .float -54439.234, 23231.4, 1.0098, 0.000003<br>.section .text<br>.globl _start<br>_start:<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movups value1, %xmm0<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movups value2, %xmm1<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movups %xmm0, %xmm2<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; movups %xmm0, data<br><br><br>  <img src ="http://www.cppblog.com/jinglexy/aggbug/22218.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/jinglexy/" target="_blank">天衣有缝</a> 2007-04-18 15:57 <a href="http://www.cppblog.com/jinglexy/archive/2007/04/18/22218.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>