编译一个软件要花多长时间?

不知道现在世界上有多少人正坐在电脑前,等待着编译结束。如果把所有的软件按照规模来排名的话,编译器至少应该在最大那一批的角落里,想想自己动手编译 GNU 工具链需要的时间吧!难怪有人抗议说 gcc 应该附带音乐以便编译时候打发时间 ^_^

但是还有比 gcc 更变态的,就比如 Open64(原为 SGIPro64,开源后叫 Open64,Intel 和中科院改的叫 ORC,Pathscale 改的叫 EkoPath,特拉华大学改的叫 KylinC),Open64 前端使用的是修改后的 gcc,然后对生成的 WHIRL 文件进行处理,生成 .s 文件再让 as 去汇编。在编译 Open64 时什么稀奇古怪的问题都可能出来,最主要的原因可能是 gcc, binutils 源代码版本不对应,或者只能使用某个版本的 gcc 去编译,某个版本的 ld 去连接。看看 Open64 中的源代码就可以发现,什么风格的代码都有,gcc 的代码可能是 K&R 的,也可能是 ANSI 的,有 C 风格的 C++,还有数不清的 csh,代码的混乱程度比 gcc 有过之而无不及,warning 一大堆,我每次都奇怪它是如何编译过去的。

我没有具体计算过 Open64 的编译时间,但是从感觉上来看,如果全部编译的话,Open64 至少需要一个小时(双核3.4G,2G内存)。平常我改编译器的源代码,最多的就是改 Dwarf 相关的调试信息输出。GNU make 会增量构建,改个 c/cxx 问题还不大,顶多重编一下模块,我最怕的就是改动哪个头文件。因为如果动了头文件,尤其是那种比较关键的头文件,就意味这下面一个小时就等编译结果吧。

一般情况下 make 的逻辑是:如果源文件被更新,只需要重编这个文件生成目标文件,然后用其重新构建可执行文件;如果头文件被更新,那么所有依赖此头文件的源文件都要被重新编译。这个依赖关系是写在 Makefile 中的,为了避免无谓的重编译,一定要在 Makefile 中确定正确的依赖关系。而这个依赖关系的依据是程序中头文件的包含关系和模块之间的联系,所以在写程序时一定要谨慎地选择包含头文件。多 include 一个头文件,错误地声明一个全局变量,都会造成程序的臃肿。

其实在这一点上 GNU 的东西做得就比较不错,头文件的包含,文件的依赖关系都很清楚,而且本身做为 Linux 下的程序员来说,了解依赖关系就是理解 Makefile 的第一步。相比而言 Windows 程序员就差很多,Win 程序员太依赖 IDE(集成开发环境) 了,没有 IDE 什么都干不了。经常有人问 Linux 下没有 VC,那怎么写程序?天那,比 VC 优秀的编译器有很多,而且没有图形界面不意味着写不出图形界面的程序,VC 编译程序也是调用命令行的。VC 的编译器叫做 CL, 连接器叫做 LINK,VC 也有 make,叫做 NMAKE。不相信的人可以尝试一下:如果你安装了 VC 并且选择了将 VC 可执行文件路径加入到环境变量里,那么就可以用 CL hello.cpp 来编译你的 hello world 程序,根本没有必要为了一个单文件的命令行程序创建一个工程。

Linux 并不拒绝 IDE,从 Eclipse 的流行可以看到这一点,但是不要让 IDE 把程序员变傻。如果不了解程序编译的整个过程和逻辑,那么写程序就成了一件盲目的事情。很多 VC 的程序员都不能区分什么是 assembly file, object file, executable file,什么是 preprocess,一个程序的源文件是怎么组织起来的,最终的二进制文件是怎样生成的。他们所知道的就是把一个文件往工程里一拉,乱七八糟的头文件一包含,就希望程序能编译过去。一旦遇到问题,马上抱怨怎么报那么多错误,就算很明显的错误也要到论坛上叽叽歪歪一番,怎么能期望得到一个可靠又高效的程序呢?

从 VC 自动生成的源程序来看,本身就有很多问题,就拿 VC 自动生成的类来说,鲜有 private 类型的成员变量和方法,大多数都是 public 或者 protect 了事,因为这样它不容易出错。但是这样一来 C++ 面向对象的特性又去哪儿了?MFC 里一堆一堆的宏,又如何了解真正的 API?

IDE 仅仅是一个加强版的文本编辑器,它提供的功能是高效写代码,但需要程序员自己保证写高效的代码!

细节很重要!

你能感到书本给你的压力吗

你能感到书本给你的压力吗?随着案头累积的书越来越多,我忽然想到这个问题,因为我发现我越来越为这个焦虑。每本书我都看了个开头,几乎每本书我都没有一个具体的时间计划能完成。书单就不列了,只能比豆瓣上我的“正在读”列表要多...

我对自己的时间掌握能力还是差。不否认我现在搞得自己很忙,比一般的学生要忙得多,是一个很好的借口。但我也不否认自己有足够的时间去多做些事情,我只是无法控制自己少在网络上花费些时间,少在电脑上瞎折腾,也利用不好小块的时间。我也想通过当前的状况提高一下自己充分利用时间的能力,但是从目前的结果来看,我对自己自我控制能力的估计有些高了。

一系列的强迫症,强迫自己频繁地查看信箱,强迫自己检查BBS、校内、博客订阅的更新,强迫自己尝试这个那个新软件,面对电脑我的抵抗力太低了,尽管我经常一天超过 12 个小时对着电脑。而让我更加焦躁的是现在当打开一个页面时,我会忽然忘了我为什么要打开它,茫然地盯着电脑屏幕,得不到满足又浪费时间。也许我该限制自己使用电脑的时间了,我没有那么重要,没那么多邮件,晚回复些也没什么区别,实际上也没有多人会关注我的这个那个,何必如此周期地去检查呢?

不过唯一还好的一点是,我没有沉迷于游戏的习惯,事实上也没有那么多时间去玩游戏。当我在路上听到别人在讨论什么什么装备,心中不屑的同时我真的好羡慕他们还有时间玩游戏,起码从中得到了很多快乐,而我能从电脑和网络中得到的满足感越来越少了。大概就是别人说的别把爱好当成工作吧!虽然也有些对学习和研究的忧虑,可我甚至没有工夫去仔细想想,又是该调整自己的时候了。

我觉得自己状态好差,思绪有点儿乱,希望过两天能好些。

一些闲谈

最近听到几件事情,觉得蛮有意思的,当然了,也有点儿八卦的性质,读者不要太 serious ^_^

第一件事,中国有个南相浩(据说是军方很厉害的密码学家),搞了一个什么 CPK(组合公钥技术),据说要跟 PKI(公钥基础设施) 抗衡,据说国家拨给了很多钱,据说很多专家看出来算法有问题,据说这个问题其实很明显,据说学过线性代数的学生都能看出来,据说大家就是不说,据说某密码专家在他的学生参加宣传讲座时告诉他们要有辨别能力,据说...请大家用辨别的眼光看上述文字,本博不做任何评价。

第二件事,中国有个王小云,搞了个...(不知道的人请 Google),据说此人学术水平一般,据说在出名后的演讲中表现的素质很低,很喜欢吹嘘自己在国外有多受欢迎,据说她出名有很多中国威胁论和国外科学家炒作以赚取自然科学基金的因素在里面,据说有很多人吃不到葡萄说葡萄酸,据说...请大家用辨别的眼光看上述文字,本博不做任何评价。

第三件事,中国有个南京大学,据说这个学校的女生之间非常喜欢以老公、老婆相称而且有时候过分亲热,据说在毕业后还把这种氛围带到其它大学,据说某些其他大学的女生很惊讶,据说她们在背后都说南京大学漂亮女生多,同性恋也多,据说...请大家用辨别的眼光看上述文字,本博不做任何评价。

密码学:对3轮DES进行的差分密码攻击

我发现自己做事情老是有虎头蛇尾的习惯,就像文章标题的这篇实验报告一样,本来我的题目是 Differential Cryptanalytic Attacks of Reduced Round DES,后来发现写对更多轮的 DES 攻击代码太困难。其实密码分析很简单,都是别人做过的东西,拿来抄抄就是了,但是实际写起来代码才发现完全不是那么回事。文章中一句话带过的东西可能需要你编码好长时间再加调试,而且还很难找到正确代码做比较,所以写到后来实在泄气,就只写好了一个3轮的攻击,再加上我时间本来就不多,只好作罢。等以后有闲功夫了我再恢复原来那标题吧 :)

鉴于自己在做作业时找代码样例对比的难处,像上次的大作业一样,我把我对 3 轮 DES 差分攻击的实验报告又放到了我的个人网站共享空间里,可以从 https://github.com/solrex/solrex/blob/master/dc_des/dc_des_lr.pdf 下载。这篇文章主要内容是对 3 轮 DES 差分攻击特征的分析和实现,文章里面有全部 DES 加密解密和 3 轮攻击的源代码。本来我觉得我的实验报告够挫的了,因为都是别人已经做出来的东西。后来我发现在 2003 年 8 月份的《计算机工程》杂志上登过这样一篇文章《数据加密标准DES分析及其攻击研究》,基本信息量为0,连引用文献都没有写到 Eli Biham 和 Adi Shamir 经典文章,我庆幸我好歹还附上了代码...希望能对某些对密码学有点兴趣的人有所帮助。

顺便说几句废话,看到 Eric师兄在博客里说 PageRank,我查看了一下我 WordPress 博客的 PageRank,嘿嘿,居然有到 2 ?我怀疑自己是不是看花了眼,在 Win 下的 Firefox Google 工具栏,IE Google 工具栏,Linux 下的 Firefox Google 工具栏查看了三遍,都是显示 2(希望 Google Toolbar 没有耍我)。哈哈,我的博客网站居然也有 PageRank 了!大家以后多到 这里 踩我吧,另外链接我博客时候最好也用这个链接,别用 Space 或者 Blogspot 的博客链接(那个网站是人家的...) :).

Ubuntu 7.10 的一些小问题

这两天用 Ubuntu 7.10 和 Compiz-Fusion 遇到了几个小问题:

1. Firefox 相关

Ubuntu 自带的 Firefox 2.0.0.6 好像有很多问题,用起来总不舒服。很诡异的一点是,如果启用默认的 Ubuntu Extension for Firefox,无法打开 Windows Live Space 的博客页面。我起初还以为是 Feedburner 的统计图片无法显示造成的假死呢,但在卸载 Ubuntu Extension for Firefox 后一切正常,这就让人搞不明白了 Ubuntu team 做出来这个东西究竟是想干吗?

2. Nvidia 显卡相关

我使用的驱动是 Nvidia 官方最新的 for linux 驱动,单屏是没有任何问题的。但当使用双屏时,就是 TwinView,笔记本是 1280x800 的分辨率,外接 LCD 是 1280x1024 的分辨率,这时候笔记本屏幕会使用外接 LCD 的高度,造成的效果是在笔记本屏幕上看不到工具栏,因为工具栏在底部...所以只能用 Alt+Tab 切窗口。

2. Compiz-Fusion 相关

开启了 Compiz-Fusion 3D 特效之后,由于吸附作用,窗口的标题栏会不正常,经常会跑到桌面面板工具栏的后面,或者说不停的在尝试吸附,表现就是标题栏闪屏。

在使用双屏时,第一次桌面立方体旋转需要很长时间,像死机了一样,我经常先切到 console 再重新切回 X window,但第一次旋转以后的旋转就很正常了,和单屏没什么区别,就是两个独立的屏一起转。

另外,双屏还是很耗资源的,虽然我是 1.8G 双核 CPU, 1G 内存, 256M 显卡,在跑双屏时应用程序反应会稍微慢一点儿,不过并不很明显,还是在可以忍受的范围之内。感觉上在 Linux 上使用双屏没有在 Windows 上快,不过,嘿嘿,Windows 双屏只能算两个桌面,我的 Ubuntu 双屏可是 8 个桌面!!!

北京马拉松 2007 和 QQ

早上来上班的路上发现知春路上多了很多人,每个路口都有站得笔直的警察和军人,偶尔还有几个保安,沿路二三十米一个带着治安巡逻红袖标的老大妈。本来我还为自己闯红灯惴惴,但想了一下查交通违规用不着这么大场面吧!到公司后马上到很少访问的新浪网上看了看新闻,哦,原来知春路是 2007 年北京马拉松的经过路段。反正是首都,总有这样那样的事情,比其它城市热闹多了。

最近有些厌学情绪,我不知道是因为前几天熬夜太多了精神不好还是因为天气转凉要有个适应期。虽然没有学多少,但也没有闲着,我基本连静静思考问题的时间都没有。前两天还抽空装了一下 Ubuntu Linux,在很新的硬件上安装 Linux 果然是一种很痛苦的事情,我忽然怀念起自己原来台式机落后的 Gforce MX440 显卡了。虽然安装了 Ubuntu 7.10,不过我还没有怎么用,这几天回去以后还是 Windows 用的比较多。

虽然我喜欢给别人宣扬开源的理念,可我从来不是一个彻底的 Linux 用户,从未把 Windows 从自己电脑上删除(曾经考虑过,但没实施),因为 Windows 也有很多让我不得不用的理由:我的 Samsung 手机数据传输,只有 Win 驱动;更包括很多 Office 文件,超星文件的使用问题;在中国的环境下,Linux 还没有适合中国用户的好的音乐播放器,好的下载软件,还有,现在对我来说很重要的一点是:好的语音聊天软件。不要和我提 Skype,在中科院(科学网)加南京大学(教育网+代理服务器)的条件下,还没有任何语音聊天软件比 QQ 更稳定(QQ 也不是很稳定)。所以我的 QQ 签名档是:“如果我QQ在线,说明正在和女朋友聊天,请勿打扰。闲时请使用 Gtalk 和我联系。”这是说真的,我只有在和女朋友语音聊天时候才会上 QQ,我们文字聊天也是使用 Gtalk 的。所以求求您了别对我的 QQ 签名档感到很好奇专门为此点开和我聊几句,请勿打扰就是请勿打扰,除非您觉得和我的关系非同一般。

讲到 QQ,现在恐怕很多人都会想起“珊瑚虫”的案子,我对那个倒不是很在意,侵犯知识产权就是侵犯知识产权,不要扯上什么企业道德,总之侵权是犯法的,受害者就有权告,受害者告不告和要求怎样,和侵权人的行为性质没有关系。我想说的是最近发现 QQ 也在悄悄改变,包括:可以使用“自定义状态”,像 MSN 和 Gtalk 的状态一样,会覆盖原始签名档;可以把 QQ 号与一个 Email 帐户绑定,然后对别人而言在所有显示 QQ 号码的地方都变成了 Email;据说 QQ Hummer 蜂鸟计划中有 Linux 版,希望能提供语音聊天功能,那样我又能减去一条不得不用 Win 的原因。

最近我的脑子里面没有一点安安静静的想法,所以,生活记录到这里吧。

在 Dell Latitude D630 上安装 Ubuntu LInux 7.10

摘要

这份文档主要描述了我在自己的 Dell Latitude D630 上安装 7.10 的过程,Ubuntu 7.10 现在在我的笔记本电脑上运行正常(准确说基本功能工作正常,因为我未做太多测试)。

目录

1. 介绍
2. 安装
3. 总结
4. 计算机硬件信息
5. 参考文章

1. 介绍

我最近买了一台 Dell Latitude D630 笔记本电脑。除了原装的 Windows XP Home Edition, 我已经在这台笔记本上安装 RHEL5,然后又安装了 Ubuntu 7.10 Linux 操作系统,下面是我安装 Gutsy Gibbon(Ubuntu 7.10) 的过程介绍。

2. 安装

[ 安装基本操作系统 ]
# wget http://releases.ubuntu.com/7.10/ubuntu-7.10-alternate-i386.iso
# wget http://archive.ubuntu.com/ubuntu/dists/gutsy/main/installer-i386/current/images/hd-media/initrd.gz
# wget http://archive.ubuntu.com/ubuntu/dists/gutsy/main/installer-i386/current/images/hd-media/vmlinuz
# cp vmlinuz initrd.gz /media/sda5
# echo "title Gutsy Install Entry" >> /boot/grub/menu.lst
# echo " root (hd0,4)" >> /boot/grub/menu.lst
# echo "kernel /vmlinuz root=/dev/ram ramdisk_size=40000 devfs=mount,dall" >> /boot/grub/menu.lst
# echo "initrd /initrd.gz" >> /boot/grub/menu.lst
# reboot
以上下载地址可以换成任何 Ubuntu 镜像站点的下载地址。重新启动时在 Grub 的启动列表中选择 Gusty Install Entry,接下来就是标准的安装过程了。关于里面硬盘分区的位置问题(即 (hd0,4), sda5) 等这些名字,每个计算机有所不同,请根据自己计算机分区和硬盘情况相应修改。最简单的办法,把那两个文件放在某个分区根目录下,一个分区一个分区的试。

[ 修改更新源列表 ]
添加以下行到 /etc/apt/source.list 中:
deb http://ubuntu.cn99.com/ubuntu/ gutsy main restricted
deb http://ubuntu.cn99.com/ubuntu/ gutsy-updates main restricted
deb http://ubuntu.cn99.com/ubuntu/ gutsy universe
deb http://ubuntu.cn99.com/ubuntu/ gutsy-updates universe
deb http://ubuntu.cn99.com/ubuntu/ gutsy multiverse
deb http://ubuntu.cn99.com/ubuntu/ gutsy-updates multiverse
deb http://ubuntu.cn99.com/ubuntu/ gutsy-security multiverse
deb http://ubuntu.cn99.com/ubuntu/ gutsy-security main restricted
deb http://ubuntu.cn99.com/ubuntu/ gutsy-security universe

在其它行前加上注释符 #

[ 更新操作系统,安装工具软件包 ]
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get install libc6 libc6-dev
$ sudo apt-get install gcc-4.2
$ sudo apt-get install g++-4.2
libc6 和 gcc 主要是为下面安装显卡驱动准备的。

[ 下载 nVidia 最新显卡驱动 ]
$ wget http://us.download.nvidia.com/XFree86/Linux-x86/100.14.09/NVIDIA-Linux-x86-100.14.09-pkg1.run

[ 修改 root 用户密码 ]
$ sudo passwd

[ 安装显卡驱动 ]
$ sudo reboot
重新启动时在 Grub 的启动列表中选择 Ubuntu 7.10, kernel 2.6.22-14-generic (recovery mode),输入 root 用户密码,运行 NVIDIA-Linux-x86-100.14.09-pkg1.run,按照指示进行。安装成功后重新启动系统,在系统启动前跳出的对话框里选择配置显示效果,选择 1280x800 分辨率的基本配置,并在下方的使用宽屏选项栏打上勾。

[ 解决 DVD±RW 驱动问题 ]
$ cp /etc/modules /etc/modules.bak
$ cp /etc/modules /tmp
$ echo piix >> /tmp/modules
$ sudo cp /tmp/modules /etc/modules
$ sudo reboot
这个我未曾尝试,因为还没有在 Linux 下刻录过光盘。

[ 解决声卡驱动问题 ]
因为 Dell Latitude D630 声卡版本比较新,用 Ubuntu 自带的 ALSA 驱动无法配置。解决办法是手工安装 ALSA 最新版本的 driver, lib 和 utils。详细步骤请参考:
http://blog.solrex.org/articles/solve-ubuntu-intel-soundcard-problem-with-latest-alsa-driver.html

[ 安装中文输入法 ]
首先在 System->Administration->Language Support 中选择安装中文支持,自动安装完中文支持以后:
$ sudo apt-get install scim-bridge-agent
$ sudo im-switch -s scim -z default
在 /etc/X11/xinit/xinput.d/scim 中找到以下两行并更改:
GTK_IM_MODULE=scim-bridge
QT_IM_MODULE=xim
如果 im-switch 不成功,可以手动将设置文件 copy 到 default 去
$ sudo cp /etc/X11/xinit/xinput.d/default /etc/X11/xinit/xinput.d/default.bak
$ sudo cp /etc/X11/xinit/xinput.d/scim /etc/X11/xinit/xinput.d/default
$ sudo reboot
如果重启后 Firefox 仍然不可以使用中文输入,可以在 Firefox 的启动脚本 /usr/lib/firefox/run-mozilla.sh 中最后 exit 前面加这么一句:
export GTK_IM_MODULE=xim

[ 安装 Windows 中文字体 ]
未在电脑上安装 Windows 操作系统者不需要此步骤,已安装者也可以选择跳过。我写了一个脚本做这个工作,可以下面链接下载。

$ wget http://share.solrex.org/scripts/install_win_CN_fonts_to_linux.sh
$ sudo sh install_win_CN_fonts_to_linux.sh
重新登录 X window

[ 安装 compiz-fusion 3D 桌面效果 ]
为了这一步的安装,你需要修改一下 xorg.conf 文件,请参考:http://compiz.org/NVidia。需要特别注意的是,如果选择了官方驱动,请不要安装任何 Ubuntu 软件仓库里的驱动。你可以从下面得到我的 xorg.conf 文件。
$ wget http://share.solrex.org/scripts/xorg.conf
$ sudo apt-get install compiz-fusion-plugins-* compizconfig-settings-manager
安装完成以后在 System->Preference->Appearance 中的 Visual Effects 中多出一项 Custom,选择以后,点右侧的 Preferences 配置效果。
注:最新版本的 Ubuntu 官方驱动已经支持 D630 的显卡,在选择 Custom选项时会自动安装驱动。安装完驱动后自动配置的 xorg.conf文件为:
http://share.solrex.org/scripts/xorg.conf.glx 

3. 总结

硬件信息 Linux 下状态 备注
Intel Core2 Duo T7100 @ 1.8 GHz 工作正常
14.1" WXGA TFT (1280x800) 工作正常
nVidia Corporation Quadro NVS 135M 工作正常 手工安装驱动程序
1 GB RAM (2 x 512 MB DDR2 533 MHz) 工作正常
120 GB HDD (Hitachi HTS722016K9A300) 工作正常
DVD±RW (PBDS DVD±RW DS-8W1P) 未验证 据说可以在 /etc/modules 增加 piix 解决.
Broadcom NetXtreme BCM5755M Gigabit Ethernet 工作正常
Broadcom Corporation BCM94311MCG wlan mini-PCI 未验证
Intel 82801H sound card (ICH8) 工作正常 Ubuntu 7.10 参见上面讲的处理方法.
Memory card reader 未验证
Internal 56k modem 未验证

4. 计算机信息

[ 所有 pci 设备 ]
$ lspci
00:00.0 Host bridge: Intel Corporation Mobile PM965/GM965/GL960 Memory Controller Hub (rev 0c)
00:01.0 PCI bridge: Intel Corporation Mobile PM965/GM965/GL960 PCI Express Root Port (rev 0c)
00:1a.0 USB Controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Contoller #4 (rev 02)
00:1a.1 USB Controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #5 (rev 02)
00:1a.7 USB Controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #2 (rev 02)
00:1b.0 Audio device: Intel Corporation 82801H (ICH8 Family) HD Audio Controller (rev 02)
00:1c.0 PCI bridge: Intel Corporation 82801H (ICH8 Family) PCI Express Port 1 (rev 02)
00:1c.1 PCI bridge: Intel Corporation 82801H (ICH8 Family) PCI Express Port 2 (rev 02)
00:1c.5 PCI bridge: Intel Corporation 82801H (ICH8 Family) PCI Express Port 6 (rev 02)
00:1d.0 USB Controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #1 (rev 02)
00:1d.1 USB Controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #2 (rev 02)
00:1d.2 USB Controller: Intel Corporation 82801H (ICH8 Family) USB UHCI Controller #3 (rev 02)
00:1d.7 USB Controller: Intel Corporation 82801H (ICH8 Family) USB2 EHCI Controller #1 (rev 02)
00:1e.0 PCI bridge: Intel Corporation 82801 Mobile PCI Bridge (rev f2)
00:1f.0 ISA bridge: Intel Corporation 82801HEM (ICH8M) LPC Interface Controller (rev 02)
00:1f.1 IDE interface: Intel Corporation 82801HBM/HEM (ICH8M/ICH8M-E) IDE Controller (rev 02)
00:1f.2 IDE interface: Intel Corporation 82801HBM/HEM (ICH8M/ICH8M-E) SATA IDE Controller (rev 02)
00:1f.3 SMBus: Intel Corporation 82801H (ICH8 Family) SMBus Controller (rev 02)
01:00.0 VGA compatible controller: nVidia Corporation Quadro NVS 135M (rev a1)
03:01.0 CardBus bridge: O2 Micro, Inc. Cardbus bridge (rev 21)
03:01.4 FireWire (IEEE 1394): O2 Micro, Inc. Firewire (IEEE 1394) (rev 02)
09:00.0 Ethernet controller: Broadcom Corporation NetXtreme BCM5755M Gigabit Ethernet PCI Express (rev 02)
0c:00.0 Network controller: Broadcom Corporation BCM94311MCG wlan mini-PCI (rev 01)

以下省略了,只是写一下查看这些信息的命令
[ 电池信息 ]
$ less /proc/acpi/battery/BAT0/info
[ CPU 信息 ]
$ less /proc/cpuinfo
[ 内存信息 ]
$ less /proc/meminfo
[ 内核消息 ]
$ dmesg
[ 加载的内核模块 ]
$ lsmod
[ X.org 设置文件(显示及输入设置)]
$ less /etc/X11/xorg.conf

5. 参考文章

* HARDWARE Dell Latitude D630
* My Ubuntu Installation
* Ubuntu on my Dell Latitude D630

基于 WinPcap 的一个嗅探器 Windows

这几天相当之忙,好多事情要做,每天都要熬很晚,觉得都有点儿在崩溃的边缘了。

才写完一个大作业,Windows 下基于 WinPcap 库的图形界面网络嗅探器。以前从来没有摸过 MFC 编程,忽然让写这种程序,都要头痛死了。十一回南京也没时间做,只有回来猛补,从网上抄些,自己写些,拼拼凑凑算是写出来一个很简单的网络嗅探器程序。不过我也不想再花工夫了,其实用 WinPcap 库写嗅探器简单到了极点,最难做的是图形界面,了解 MFC 编程对我价值不是很大,不准备再深入了。我把代码包放到我的网站上了,这里是链接地址:
http://share.solrex.org/MyWork/Eavesdrop_Windows_Sniffer_Based_on_Winpcap_VC6.rar
有兴趣了解如何写网络嗅探器的可以下载下来看看。至于使用网络嗅探器,最好还是用 Ethereal,现在好像改名叫做 Wireshark 了,那才是真正强大的网络嗅探和协议分析工具,我们这种东西都是小儿科。

今天抽空把上一篇博客里给出的在 Linux 下安装 Windows 中文字体的脚本稍微完善了下,也根据师兄的建议把源代码放在了网站上(用 Google translate 访问了一下我的 blogspot 才发现上面显示的代码全乱套了)
http://share.solrex.org/scripts/install_win_CN_fonts_to_linux.sh
,修改了一下上一篇博客内容。之所以喜欢把代码放在文章里主要是经常搜索一些示例代码时发现源代码的下载链接不能使用,还是放在文章里一份拷贝比较有利于知识共享。

估计这个星期还会很忙,有一个对 DES 进行差分攻击的报告,有一个希腊哲学史方面的课程论文,还有很多书和 paper 要看。就算我不兼职,研究生生活也并不轻松啊...

在双系统环境中使用Windows字体美化Linux中文字体

安装完 Linux 操作系统的中文支持后,看到那些难看的字体是不是很不爽,下面这个脚本就帮助你使用 Windows 字体来自动美化 Linux 中文字体。

下面的脚本使用 windows 自带字体美化 Linux 字体,主要是将软件中文字体使用宋体,终端使用黑体替换。脚本源程序可以在 http://share.solrex.org/scripts/install_win_CN_fonts_to_linux.sh 下载到。

首先确保 windows 系统所在分区被挂载到 /media 目录下将以下内容保存为脚本文件:install_win_CN_fonts_to_linux.sh

#!/bin/bash
check_answer()
{
    case $1 in
        y|Y|Yes|yes|YES)
            return 0;
            ;;
        n|N|No|no|NO)
            return 1;
            ;;
        *) echo "Answer either yes or no, default is yes"
            return 2
            ;;
    esac
}

LIN_FONTS_DIR=/usr/share/fonts/zh_CN/TrueType
LANG_SEL_FILE=/etc/fonts/language-selector.conf
SEARCH_DIR=/media

echo -n "This script is for installing Windows Chinese fonts to Linux on a dual-OS-installed computer. And the writer doesn't promise it will work on your system. Do you want to continue?(y/n)[y]:"
read ANS_STR
: ${ANS_STR:="y"}
check_answer $ANS_STR
ANS=$?
if [ $ANS -ne 0 ]; then
    echo "Exit."
    exit
fi

echo -n "There might be license problems, i.e. you have no permission to use Windows fonts in other program except Windows OS. Do you want to continue?(y/n)[y]:"
read ANS_STR
: ${ANS_STR:="y"}
check_answer $ANS_STR
ANS=$?
if [ $ANS -ne 0 ]; then
    echo "Exit."
    exit
fi

echo -n "You run this script with root account or "sudo" command?(y/n)[y]:"
read ANS_STR
: ${ANS_STR:="y"}
check_answer $ANS_STR
ANS=$?
if [ $ANS -ne 0 ]; then
    echo "Exit."
    exit
fi

echo -n "You mounted Windows System partation "C:\" to /media directory?(y/n)[y]:"
read ANS_STR
: ${ANS_STR:="y"}
check_answer $ANS_STR
ANS=$?
if [ $ANS -ne 0 ]; then
    echo "Exit."
    exit
fi

echo "Searching for windows's fonts directory..."
echo "That may take a few minutes, please wait."
WIN_FONTS_DIR=`echo $(find $SEARCH_DIR -name simsun.ttc -type f) | sed s/simsun.ttc//g`
if [ -d $WIN_FONTS_DIR ]; then
    while true; do
        echo "Windows fonts dir found! Your windows fonts directory is: "
        echo -n ""$WIN_FONTS_DIR" Is it right?(y/n)[y]:"
        read ANS_STR
        : ${ANS_STR:="y"}
        check_answer $ANS_STR
        ANS=$?
        if [ $ANS -eq 0 ]; then
            break
        elif [ $ANS -eq 1 ]; then 
            echo "Please enter path to your windows fonts dir?"
            read ANS_STR
            if [ -d $ANS_STR ]; then
                WIN_FONTS_DIR=$ANS_STR
                break
            else
                echo "Your input is not a dir. Exit."
                exit
            fi
        else
            echo "Unrecognized input."
        fi
    done
else
    echo "Can not find windows fonts directory. "
    echo -n "Please enter path to your windows fonts dir:"
    read ANS_STR
    if [ -d $ANS_STR ]; then
        WIN_FONTS_DIR=$ANS_STR
    else
        echo "Your input is not a dir. Exit."
        exit
    fi
fi

echo "Entering $WIN_FONTS_DIR"
cd $WIN_FONTS_DIR

echo "Creating Linux fonts directory: $LIN_FONTS_DIR..."
mkdir -p $LIN_FONTS_DIR
if [ $? -ne 0 ]; then
    echo "Creating Linux fonts dir failed. Exit."
    exit
fi

echo "Copying windows fonts to linux fonts dir... sim*|tahoma|tohomabd.ttf"
cp sim* SimSun18030.ttc tahoma.ttf tahomabd.ttf $LIN_FONTS_DIR
if [ $? -ne 0 ]; then
    echo "Copying windows fonts to linux fonts dir failed. Exit."
    exit
fi

echo "Changing font files' access permissions.."
chmod 644 $LIN_FONTS_DIR/*

echo "Entering $LIN_FONTS_DIR"
cd $LIN_FONTS_DIR

echo "Creating an index of scalable font files in $LIN_FONTS_DIR for X..."
mkfontscale
if [ $? -ne 0 ]; then
    echo "Creating an index of scalable font files for X failed. Exit."
    exit
fi

echo "Creating an index of X font files in $LIN_FONTS_DIR"
mkfontdir
if [ $? -ne 0 ]; then
    echo "Creating an index of X font files in $LIN_FONTS_DIR failed. Exit."
    exit
fi

echo "Creating an index of FreeType font files in $LIN_FONTS_DIR"
fc-cache $LIN_FONTS_DIR
if [ $? -ne 0 ]; then
    echo "Creating an index of FreeType font files in $LIN_FONTS_DIR failed. Exit."
    exit
fi

echo "Backing up $LANG_SEL_FILE"
if [ -f $LANG_SEL_FILE ]; then
    cp $LANG_SEL_FILE $LANG_SEL_FILE.bak
fi

echo "Generating new $LANG_SEL_FILE... for language select"
echo '
<fontconfig>
  <alias>
    <family>serif</family>
      <prefer>
        <family>Bitstream Vera Serif</family>
        <family>SimSun</family>
        <family>DejaVu Serif</family>
        <family>AR PL ShanHeiSun Uni</family>
        <family>AR PL ZenKai Uni</family>
      </prefer>
  </alias>
  <alias>
    <family>sans-serif</family>
      <prefer>
        <family>Bitstream Vera Sans</family>
        <family>SimSun</family>
        <family>DejaVu Sans</family>
        <family>AR PL ShanHeiSun Uni</family>
        <family>AR PL ZenKai Uni</family>
      </prefer>
  </alias>
  <alias>
    <family>monospace</family>
      <prefer>
        <family>DejaVu Sans Mono</family>
        <family>Bitstream Vera Sans Mono</family>
        <family>SimHei</family>
    </prefer>
  </alias>

<match target="font" >
  <test name="family" compare="contains" >
    <string>Song</string>
    <string>Sun</string>
    <string>Kai</string>
    <string>Ming</string>
  </test>
  <test compare="more_eq" target="pattern" name="weight" >
    <int>180</int>
  </test>
  <edit mode="assign" name="embolden" >
    <bool>true</bool>
  </edit>
</match>

<match target="font" >
  <test name="family" compare="contains" >
    <string>Song</string>
    <string>Sun</string>
    <string>Kai</string>
    <string>Ming</string>
  </test>
  <edit name="globaladvance">
    <bool>false</bool>
  </edit>
  <edit name="spacing">
    <int>0</int>
  </edit>
  <edit name="hinting">
    <bool>true</bool>
  </edit>
  <edit name="autohint">
    <bool>false</bool>
  </edit>
  <edit name="antialias" mode="assign">
    <bool>true</bool>
  </edit>
  <test name="pixelsize" compare="less_eq">
    <int>18</int>
  </test>
  <edit name="antialias" mode="assign" >
    <bool>false</bool>
  </edit>
</match>

<match target="pattern">
  <test name="family">
    <string>SimSun</string>
    <string>SimSun-18030</string>
    <string>AR PL ShanHeiSun Uni</string>
    <string>AR PL New Sung</string>
    <string>MingLiU</string>
    <string>PMingLiU</string>
  </test>
  <edit binding="strong" mode="prepend" name="family">
    <string>Tahoma</string>
    <string>Verdana</string>
  </edit>
</match>

<match target="pattern">
  <test name="family">
    <string>宋体</string>
  </test>
  <edit name="family" mode="assign">
    <string>SimSun</string>
  </edit>
</match>
<match target="pattern">
  <test name="family">
    <string>新宋体</string>
  </test>
  <edit name="family" mode="assign">
    <string>SimSun</string>
  </edit>
</match>
<match target="pattern">
  <test name="family">
    <string>仿宋_GB2312</string>
  </test>
  <edit name="family" mode="assign">
    <string>FangSong_GB2312</string>
  </edit>
</match>
<match target="pattern">
  <test name="family">
    <string>楷体_GB2312</string>
  </test>
  <edit name="family" mode="assign">
    <string>KaiTi_GB2312</string>
  </edit>
</match>
<match target="pattern">
  <test name="family">
    <string>黑体</string>
  </test>
  <edit name="family" mode="assign">
    <string>SimHei</string>
  </edit>
</match>
</fontconfig> ' > $LANG_SEL_FILE
echo "Finished. Please quit your X session and relogin."
echo "If you have problems on start X(sometimes happened on Ubuntu 7.04.), please delete $LIN_FONTS_DIR and copy the backuped $LANG_SEL_FILE.bak to $LANG_SEL_FILE. Then do "fc-cache" with no options. That may work."

执行:
sudo sh ./install_win_CN_fonts_to_linux.sh

登出 Xwindow,再重新登录即可。

黄金周之末日

长假结束了,要乘今天晚上的 T66 回北京。唉,虽然基本算是哪里都没去,但还是好累,大概是因为住同学租的房子,没有在校园里的缘故吧。

这几天主要做的事情就是陪女朋友,然后到丹阳配了副眼镜,剩下的好像没干什么。

回去也比较痛苦,因为貌似有好多作业没写...尤其是一个网络嗅探器的大作业。所以要赶紧买个电脑,把程序赶出来,估计后面一个星期要有几天不用睡觉了~~~

南京有个想我的小白

南京不仅有个想我的小白,南京还有个我想的小白,所以在下周的今天,我就该行走在南大的校园里了。离开了三个月,真的是三个月,6月27日离开南京,9月 28日即将回到南京,我很感谢中科院研究生院英明睿智的领导作出的让我无比拥护的决定:十一放假九天。这样我就不用排三百个人的队去买票,也能多出两天宝贵的时间陪陪女友。

我给希希说过,博客里我不想写风花雪月。因为文字一旦写下,它就会留存在某个地方,即使是美索不达米亚的泥板,也会有重新唤起人们回忆的一天,那些留下的刻痕又会在你心里划上一道一道。但如此地谨小慎微对另一个人来说很不公平,我看过丫头写给我的文字,那么至少我也应该给她写一点点东西。

不过千万不要误会的是,这里的小白不是指蜡笔小新的那条小狗,只是说我的女孩儿是个傻丫头。这个小白能在自己只剩下三百块生活费的时候还硬要替我交手机费;在我开玩笑问她“你难道没有什么追求吗?”的时候告诉我:有啊,就是和你结婚!在我威胁她说我的老婆一定要会做饭的时候,在家学了一暑假的厨艺还几次烫到了手。她喜欢躲在宿舍里不去上自习,在别人眼里可能是有点精灵古怪的小丫头。我最喜欢看到的场景,就是她在看见我的一刹那脸上露出的笑容,足以让周围的景物都黯然失色。她一点儿都不介意陪我去吃我喜欢的陕西凉皮,坐在脏兮兮的桌子旁,依然能笑得很灿烂。有一次老余看到都不忍心,狠狠地责怪我说,你难道就带女朋友在这种地方吃饭?

希希家里一点都不富裕,现在自己还欠着四年的助学贷款没有还,但每次和我出去总要抢着付钱,尽管我一遍又一遍苦口婆心地告诉她我一个月实习赚的钱也能顶她在档案馆打一年工。她还总要费尽心机地想送我些小礼物,说看着它们我就不会想到别人了,为此在离开南京那一天还硬拉着我到新街口地下广场照了几片大头贴,亲自给我贴到手机上,说这是主权声明。这两天也不知道在捣什么鬼,我问她在干吗总是语焉不详,肯定又想在我到南京时候给我个惊喜。

其实她也不是总那么好脾气,假如我们在一起时有人找我有事,她总要把那个人好好地埋怨一番;我们吃饭的时候如果有认识的人要过来坐,她的眼神都能把别人给杀掉,我又想起杨春雷那次在“傣妹”的悲惨遭遇 :)。

丫头对我也算情深义重,却总是担心我会不会被别人抢去,但这世上还能有谁能让我更珍惜?那张笑脸,那份情意,足以让我把南京当作另一个家乡。那里,有我的女孩儿!

重返简约纳

在经过一番思考之后,我还是决定返回公司继续做我的兼职,每周三天,星期五到星期日。

专业课选了四门,分别是:密码学,信息安全工程学,网络攻击与防范,计算机网络,事实上课业没有很重。我的意思不是这几门课不高深,任何一门课拿出来都足 以研究一阵子。只是作为入门课程来说,不算很难。密码学和计算机网络还好,本来就是一个学科,又有经典教材,但是自己以前曾经自学过一部分,再加上数学基 础,应该是比初学者要好。信息安全工程学就有点儿扯了,基本上和软件工程的是近似的一类东西,老师自己都说这实际上是一门文化课;网络攻击与防范从某种意 义上讲可以叫做黑客与反黑客,内容就是一些攻击和防范技巧,主要是 Windows 下的工具和技术。这四门课全都放在了每周前四天,所以想想觉得在课余还是有精力出来打工的,就向经理申请重新回到了公司。虽然并没有很大的经济压力,但是 多赚些钱总能让自己在某些选择上更自由一些。

只是这样一来,课业时间就比较紧了,我自己也很明白这一点,所以自习也是比较努力的,而且住的是两个人的宿舍,环境很好,回去也可以不受干扰地看会儿书,挺不错的。

原来一直在做 GDB 和调试相关的东西,现在整个构架和流程都搭起来了,剩下的就是验证和测试,比较依赖于硬件和工具链的正确性,所以没有太多大工作量的东西可做了。现在新的 工作主要是把 system simulator 和硬件的更新对应起来,让它反应真实的硬件环境,原来负责这个的香港同事辞职回香港了,所以一直就没有更新。其实 simulator 的 gdbserver interface 就是我写的,对整个 sim 的结构也是比较了解,今天看了下代码就找到了些关键点。本来以为是很严重缺失的东西其实已经有实现,只是没完善,这也就是软件工程中关注的问题,关键开发 人员离职给整个项目带来的损失。

嘿嘿最后记录一下这两天比较感慨的一点:最近八卦比较多~~~^_^

2007 新的开始

新学期开始了,住房条件还可以,青年公寓 B 座 5 楼,两人间没阳台没空调有卫生间有热水上床下桌一立柜。其实最开心的是有热水,这样洗澡就非常方便。

要说各方面的条件,中科院研究生院应该算是国内最好的了,尤其是中关村园区。主教红楼必须凭学生证入内,中央空调开得很足,桌椅都是分离式的,桌面很大很干净,整个教室也特别特别干净,人也不是很多,在这种环境下不去教室上自习都有一点儿罪恶感。在南大那种硬件条件巨差的学校呆时间长了,到这里觉得一切都太好了,哦,除了运动场。中关村园区的校园巨小,宿舍楼都是一二十层,就那么十几座,还都挨着,连鼓楼校区南园的二分之一都不到,要不是教学区在中关村东路对面,一天的运动量那是超级有限的。一片两个篮球场那么大区域,铺上人工草皮就叫足球场,连球门都没有,晕的一塌糊涂啊!而教学区就别提了,没有最小只有更小~~~

选课已经开始了,中科院的选课制度非常灵活,除了英语政治以外,其它的课程自由选择,自己设置几门课作为专业学位课,当然这个要和导师协商。我们实验室很逗,学校通知是 7 号回所,我们实验室根本就不知道这事儿,就把我们扔在中关村了。我们只好自己坐公交车回去见导师。我的导师也很 easy,没给我要求要上什么课,说你按照兴趣自己决定就好了。我只有一个直系的师兄,研三,清华毕业的,他给我号了几门课大致要选的。所以这学期除英语政治外选了 5 门课,3 门作为专业学位课,1 门作为专业选修课,还有 1 门人文公选课。

下面该说钱了,好象第一年所有的中科院学生都一样,359.5 院里补助加 240 助研费总共 599.5 块。可是中关村园区的食堂开学前涨了大约百分之二十,一份荤菜至少 3.5 以上,所以两个荤菜加米饭至少得八块多,黑得要命,这 600 块钱补助大约都得花在吃上了,好怀念南大的食堂啊!上网倒还好,一年级学生每个月免费 2 G 国内和 1 G 出国流量,超出部分国内 1 分 1 M,国外 1 块 1 M,其实如果不下电影看视频什么的也足够了,而且网速暴快呀,比我们公司的网络还快。

昨天和数学系以前过来的师兄吃了顿饭,也都认识了一下,南大数学系的队伍是越来越壮大了,前年5个去年6个今年8个。不过听他们讲,数学院最多的是山东大学的人,有好几十,因为,数学院的领导和老师太多山大的了。其实数学院的待遇也是挺好的了,老师还肯给报销买书的钱,而且院里打印资料不要钱,好羡慕的啊!

徐扬扬王超他们就住 B 座 1 楼,挨着楼梯口,基本上每天都要碰见他们几次,没事在上楼前面也都到他们宿舍逛一圈,现在这篇博客就是用王超的电脑写的。总之呢,就是交待一下基本情况,一切都好,以后有自己电脑了再恢复更新频率吧。

暂停更新一段

明天就要开学了,今天是我在公司的最后一天。现在自己还没有个人电脑,以后大概就失去了持续的 Internet access,所以标题就叫做暂时安静。博客更新频率、信箱登录频率、IM 上线频率、BBS 和 SNS 网站刷新频率都会放慢,等十一后我买了电脑再说吧~_~。

由于个人时间安排和公司接受程度,暂时不会在公司继续兼职了。以后是否有机会再出来做事,就得看情况了。刚开学这段时间应该比较忙,再加上我还有 7 本正在读的书没有读完 [href: http://www.douban.com/do/Solrex/book/ ],空闲的时间恐怕还是很少滴。

不知道要住什么样的宿舍,不知道要学什么样的课程,不知道要做什么样的研究,一个数学系的学生去读工程方向的网络安全,应该还是有很多东西要学,最基本的通信和编码这块就有很多需要弥补的差距。我想刚进实验室时导师是不会对我太满意的,不过咱数学系的学生,数分高代常微偏微离散数值概率运筹泛函近世实变复变都学过,还怕什么?

最近身体也不是很好,因为吃饭麻烦,饮食总不是那么有规律,期望开学以后会好一些。十一要回南京,去看 xixi,嘿嘿还有一个额外的计划是教她学 TeX,这样以后我就不用干排版的活了~~~

今天徐宥的 Gtalk 签名改成了“中国网,封天下”,唉,我也深刻地体会到了。和“墙”打交道也很久了:刚开始 Blog 用 MSN Space,因为 Space 没有到信息产业部备案,05年下半年和06年上半年访问都不正常,直到咱们主席造访盖茨家为止,总算没再出大问题;个人主页用 Google Page,隔三岔五总要封几天,这不这两天正封着呢;后来 Blog 用 Blogspot,封的时间比能访问的时间多;正想到 Flickr 上开个相册,被封掉了;刚用上 Feedburner,这两天又被封了,这次封得更绝,不封主页封子域名;Wikipedia 就不用说了,祈祷吧!

所以我的博客现在在三个地方同步更新:http://blog.solrex.cn , http://solrex.spaces.live.com , http://solrex.blogspot.com ,我只能希望不会被同时“墙”三个,这样我还有点写博客的念想。另外我也劝各位使用 Feedburner 烧制的 RSS feed 订阅别人博客的同学(不管是订阅谁的),把阅读器换成 Google Reader(已经支持离线功能,下载浏览器插件即可)吧,那样不管怎么“墙”你都可以得到博客更新(如果这个世界上还有 Google 服务器不能抓到的网页,那么这台服务器 80% 的可能是物理层隔离于 Internet 的)。

罗嗦完了,我 peace out~~~~~~

十字路口

说十字路口其实也不对,只不过是又到了一个转折点。下周五工作完以后,周六就会到中科院新生报到了。今天上午才到沃尔玛把“一寸正身免冠彩色光面纸(通知书上原话)”照片给照了,剩下的证件什么的都已经准备好了。徐洋洋和我都是到中科院中关村园区报到,他大概 30 日到北京,可能还要把行李放我那,因为我住的地方离青年公寓很近。

同时比较焦虑的是不知道还能不能在公司继续兼职,从我的角度讲,是比较乐意做下去的,主要是因为有一笔额外的收入会让自己在经济上宽裕很多,毕竟现在是自负盈亏。虽然听师兄说一年级课并不忙,但是时间分配能否合理,公司能否接受都是一个问题,大概经理下周会和我谈。

其实考虑来考虑去都是钱的问题,如果纯粹是为了锻炼,自己单独参加一些开源项目等等也可以得到很好的机会,只不过那样是不会有收入进帐的。科学院基本是导师如果项目多,学生就忙,得的钱也多,如果项目少,学生就比较闲,得的钱也比较少。而一年级都是集中学习,除了个别变态的老师,很少有让学生做项目的,也就比较有时间去兼职。现在也算是成人了,花钱的事情比较多,当然赚钱越多越好了。所以就算这面公司不能继续做下去,还是要找些其它的路子去赚钱,年轻时候把太多空闲时间花在玩上也不好。

开学又会认识一批新同学,可能也会有些新朋友。面对变化的时候,人总是有一点点恐惧又有一点点向往,很矛盾的心理。不过等适应下来,一切仍然会都好。其实我算是好的了,已经在北京待了大半年了,可以称作“北漂”族的。而且住处就在青年公寓附近,这周围的情况摸得熟得不行,在环境上起码不陌生了,已经比其他的同学好很多了。

Hacking 《自己动手写操作系统》Chapter 4

——Writing x86 PC Bootloader With Free Software 2

本文内容已被整理为一本电子书,请到这里下载

强烈建议随《自己动手写操作系统》这本书读本篇文章,基础知识:x86 汇编指令,AT&T 汇编格式,FAT12 文件系统格式。

由于《自己动手写操作系统》第三章讲的是保护模式,示例代码全是 DOS 可执行代码,和直接的 Bootloader 没有太大关系,所以这次继续下来从第四章开始。

前两章中写的 Bootloader 其实严格意义上只算是一个 Boot sector(扇区),因为它只是简单地打印了一个字符。第四章的 Bootloader 实现了从软盘中读写一个文件并加载运行的功能。

总共有以下几个文件:boot.S loader.S solrex_x86_boot.ld solrex_x86_dos.ld Makefile

下面解释每个文件的作用:
boot.S:
它生成的 .bin 文件就是软盘镜像的第一个扇区。由上一篇文章提供的 boot.S 只有启动功能,生成的软盘镜像文件只能作为启动器而不能作为可读写软盘来使用,因为在那个镜像里面没有将软盘格式化。其实格式化说白了就是在软盘的第一个扇区添加一些头信息,这样系统就知道如何处理这张软盘,在 boot.S 中的 Floppy header 就是做这个工作的。而在软盘的前 3 个 byte 是一句跳转指令,这样在启动时候系统会跳过 floppy header,也解决了如何启动的问题。这样这张软盘既可以作为启动盘,又可以作为文件盘使用了。因为启动扇区只有 512 个字节,不可能依赖它作为启动功能,这样我们可以将另一个程序 LOADER.BIN 放入软盘,启动后,从软盘读取它进入内存并执行。

所以 boot.S 代码的主要内容是,首先将软盘主目录复制到内存中,并在其中搜索 LOADER.BIN,搜索到以后,将 LOADER.BIN 加载入内存并执行。

loader.S:
就是一个普通的打印程序,在屏幕第一行中间打印一个 'L'

solrex_x86_boot.ld:
boot.S 的连接脚本,将 boot.S 代码段连接到 0x7c00 的位置(x86 PC 操作系统启动的位置)。

solrex_x86_dos.ld:
loader.S 的连接脚本,将 loader.S 代码段连接到 0x1000 的位置,和普通 DOS 程序一样。

Makefile:
不说了,大家都知道。

这个 hacking 系列我准备继续写下去,示例代码可以从我的个人主页 http://solrex.org 打包下载,包括《自己动手写操作系统》的部分源代码,以 .asm 为后缀。对 Intel(MASM,NASM,TASM) 和 AT&T(GAS)汇编语言语法在 x86 平台的实现如何转换感兴趣的朋友,可以对比阅读 .asm 和 .S 文件。

[solrex@NJU-CAS Solrex]$ more boot.S loader.S solrex_x86_boot.ld solrex_x86_dos.ld Makefile
::::::::::::::
boot.S
::::::::::::::
.code16
.set BaseOfStack, 0x7c00 /* Stack base address, inner */
.set BaseOfLoader, 0x9000 /* Section loading address of LOADER.BIN */
.set OffsetOfLoader, 0x0100 /* Loading offset of LOADER.BIN */
.set RootDirSectors, 14 /* Root directory sector count */
.set SecNoOfRootDir, 19 /* 1st sector of root directory */
.set SecNoOfFAT1, 1 /* 1st sector of FAT1 */
.set DeltaSecNo, 17 /* BPB_(RsvdSecCnt+NumFATs*FATSz) -2 */
/* Start sector of file space =*/
.text
/* Floppy header of FAT12 */
jmp LABEL_START /* Start to boot. */
nop /* nop required */
BS_OEMName: .ascii "WB. YANG" /* OEM String, 8 bytes required */
BPB_BytsPerSec: .2byte 512 /* Bytes per sector */
BPB_SecPerCluse: .byte 1 /* Sector per cluse */
BPB_ResvdSecCnt: .2byte 1 /* Reserved sector count */
BPB_NumFATs: .byte 2 /* Number of FATs */
BPB_RootEntCnt: .2byte 224 /* Root entries count */
BPB_TotSec16: .2byte 2880 /* Total sector number */
BPB_Media: .byte 0xf0 /* Media descriptor */
BPB_FATSz16: .2byte 9 /* FAT size(sectors) */
BPB_SecPerTrk: .2byte 18 /* Sector per track */
BPB_NumHeads: .2byte 2 /* Number of magnetic heads */
BPB_HiddSec: .4byte 0 /* Number of hidden sectors */
BPB_TotSec32: .4byte 0 /* If TotSec16 equal 0, this works */
BS_DrvNum: .byte 0 /* Driver number of interrupt 13 */
BS_Reserved1: .byte 0 /* Reserved */
BS_BootSig: .byte 0x29 /* Boot signal */
BS_VolID: .4byte 0 /* Volume ID */
BS_VolLab: .ascii "Solrex 0.01" /* Volume label, 11 bytes required */
BS_FileSysType: .ascii "FAT12 " /* File system type, 8 bytes required */

/* Initial registers. */
LABEL_START:
mov %cs,%ax
mov %ax,%ds
mov %ax,%es
mov %ax,%ss
mov $BaseOfStack, %sp

/* Clear screen */
mov $0x0600,%ax /* %ah=6, %al=0 */
mov $0x0700,%bx /* Black white */
mov $0,%cx /* Top left: (0,0) */
mov $0x184f,%dx /* Bottom right: (80,50) */
int $0x10 /* BIOS int 10h, ah=6: Initialize screen */

/* Display "Booting**" */
mov $0,%dh
call DispStr /* Display string(index 0)*/

/* Reset floppy */
xor %ah,%ah
xor %dl,%dl /* %dl=0: floppy driver 0 */
int $0x13 /* BIOS int 13h, ah=0: Reset driver 0 */

/* Find LOADER.BIN in root directory of driver 0 */
movw $SecNoOfRootDir, (wSectorNo)

/* Read root dir sector to memory */
LABEL_SEARCH_IN_ROOT_DIR_BEGIN:
cmpw $0,(wRootDirSizeForLoop) /* If searching in root dir */
jz LABEL_NO_LOADERBIN /* can find LOADER.BIN ? */
decw (wRootDirSizeForLoop)
mov $BaseOfLoader,%ax
mov %ax,%es /* %es <- BaseOfLoader*/
mov $OffsetOfLoader,%bx /* %bx <- OffsetOfLoader */
mov (wSectorNo),%ax /* %ax <- sector number in root */
mov $1,%cl
call ReadSector
mov $LoaderFileName,%si /* %ds:%si -> LOADER BIN */
mov $OffsetOfLoader,%di /* BaseOfLoader<<4+100*/
cld
mov $0x10,%dx

/* Search for "LOADER BIN", FAT12 save file name in 12 bytes, 8 bytes for
file name, 3 bytes for suffix, last 1 bytes for '20'. If file name is
less than 8 bytes, filled with '20'. So "LOADER.BIN" is saved as:
"LOADER BIN"(4f4c 4441 5245 2020 4942 204e).
*/
LABEL_SEARCH_FOR_LOADERBIN:
cmp $0,%dx /* Read control */
jz LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR
dec %dx
mov $11,%cx

LABEL_CMP_FILENAME:
cmp $0,%cx
jz LABEL_FILENAME_FOUND /* If 11 chars are all identical? */
dec %cx
lodsb /* %ds:(%si) -> %al*/
cmp %es:(%di),%al
jz LABEL_GO_ON
jmp LABEL_DIFFERENT /* Different */

LABEL_GO_ON:
inc %di
jmp LABEL_CMP_FILENAME /* Go on loop */

LABEL_DIFFERENT:
and $0xffe0,%di /* Go to head of this entry */
add $0x20,%di
mov $LoaderFileName,%si /* Next entry */
jmp LABEL_SEARCH_FOR_LOADERBIN

LABEL_GOTO_NEXT_SECTOR_IN_ROOT_DIR:
addw $1,(wSectorNo)
jmp LABEL_SEARCH_IN_ROOT_DIR_BEGIN

/* Not found LOADER.BIN in root dir. */
LABEL_NO_LOADERBIN:
mov $2,%dh
call DispStr /* Display string(index 2) */
jmp . /* Infinite loop */

/* Found. */
LABEL_FILENAME_FOUND:
mov $RootDirSectors,%ax
and $0xffe0,%di /* Start of current entry, 32 bytes per entry */
add $0x1a,%di /* First sector of this file */
mov %es:(%di),%cx
push %cx /* Save index of this sector in FAT */
add %ax,%cx
add $DeltaSecNo,%cx /* LOADER.BIN's start sector saved in %cl */
mov $BaseOfLoader,%ax
mov %ax,%es /* %es <- BaseOfLoader */
mov $OffsetOfLoader,%bx /* %bx <- OffsetOfLoader */
mov %cx,%ax /* %ax <- Sector number */

/* Load LOADER.BIN's sector's to memory. */
LABEL_GOON_LOADING_FILE:
push %ax
push %bx
mov $0x0e,%ah
mov $'.',%al /* Char to print */
mov $0x0f,%bl /* Front color: white */
int $0x10 /* BIOS int 10h, ah=0xe: Print char */
pop %bx
pop %ax

mov $1,%cl
call ReadSector
pop %ax /* Got index of this sector in FAT */
call GetFATEntry
cmp $0x0fff,%ax
jz LABEL_FILE_LOADED
push %ax /* Save index of this sector in FAT */
mov $RootDirSectors,%dx
add %dx,%ax
add $DeltaSecNo,%ax
add (BPB_BytsPerSec),%bx
jmp LABEL_GOON_LOADING_FILE

LABEL_FILE_LOADED:
mov $1,%dh
call DispStr /* Display string(index 1) */

/*******************************************************************
Jump to LOADER.BIN's start address in memory.
*/
jmp $BaseOfLoader,$OffsetOfLoader
/*******************************************************************/

/* ==================================================================
Variable table
*/
wRootDirSizeForLoop: .2byte RootDirSectors
wSectorNo: .2byte 0 /* Sector number to read */
bOdd: .byte 0 /* odd or even? */

/* ==================================================================
String table
*/
LoaderFileName: .asciz "LOADER BIN" /* File name */
.set MessageLength,9
BootMessage: .ascii "Booting**" /* index 0 */
Message1: .ascii "Loaded in" /* index 1 */
Message2: .ascii "No LOADER" /* index 2 */

/* ==================================================================
Routine: DispStr
Action: Display a string, string index stored in %dh
*/
DispStr:
mov $MessageLength, %ax
mul %dh
add $BootMessage,%ax
mov %ax,%bp /* String address */
mov %ds,%ax
mov %ax,%es
mov $MessageLength,%cx /* String length */
mov $0x1301,%ax /* ah = 0x13, al = 0x01(W) */
mov $0x07,%bx /* PageNum 0(bh = 0), bw(bl= 0x07)*/
mov $0,%dl /* Start row and column */
int $0x10 /* BIOS INT 10h, display string */
ret

/* ==================================================================
Routine: ReadSector
Action: Read %cl Sectors From %ax sector(floppy) to %es:%bx(memory)
Assume sector number is 'x', then:
x/(BPB_SecPerTrk) = y,
x%(BPB_SecPerTrk) = z.
The remainder 'z' PLUS 1 is the start sector number;
The quotient 'y' devide by BPB_NumHeads(RIGHT SHIFT 1 bit)is cylinder
number;
AND 'y' by 1 can got magnetic header.
*/
ReadSector:
push %ebp
mov %esp,%ebp
sub $2,%esp /* Reserve space for saving %cl */
mov %cl,-2(%ebp)
push %bx /* Save bx */
mov (BPB_SecPerTrk), %bl /* %bl: the devider */
div %bl /* 'y' in %al, 'z' in %ah */
inc %ah /* z++, got start sector */
mov %ah,%cl /* %cl <- start sector number */
mov %al,%dh /* %dh <- 'y' */
shr $1,%al /* 'y'/BPB_NumHeads */
mov %al,%ch /* %ch <- Cylinder number(y>>1) */
and $1,%dh /* %dh <- Magnetic header(y&1) */
pop %bx /* Restore %bx */
/* Now, we got cylinder number in %ch, start sector number in %cl, magnetic
header in %dh. */
mov (BS_DrvNum), %dl
GoOnReading:
mov $2,%ah
mov -2(%ebp),%al /* Read %al sectors */
int $0x13
jc GoOnReading /* If CF set 1, mean read error, reread. */
add $2,%esp
pop %ebp
ret

/* ==================================================================
Routine: GetFATEntry
Action: Find %ax sector's index in FAT, save result in %ax
*/
GetFATEntry:
push %es
push %bx
push %ax
mov $BaseOfLoader,%ax
sub $0x0100,%ax
mov %ax,%es /* Left 4K bytes for FAT */
pop %ax
movb $0,(bOdd)
mov $3,%bx
mul %bx /* %dx:%ax = %ax*3 */
mov $2,%bx
div %bx /* %dx:%ax/2 */
cmp $0,%bx /* remainder %dx = 0 ? */
jz LABEL_EVEN
movb $1,(bOdd)

LABEL_EVEN:
xor %dx,%dx /* Now %ax is the offset of FATEntry in FAT */
mov (BPB_BytsPerSec),%bx
div %bx /* %dx:%ax/BPB_BytsPerSec */
push %dx
mov $0,%bx
add $SecNoOfFAT1,%ax /* %ax <- FATEntry's sector */
mov $2,%cl /* Read 2 sectors in 1 time, because FATEntry */
call ReadSector /* may be in 2 sectors. */
pop %dx
add %dx,%bx
mov %es:(%bx),%ax
cmpb $1,(bOdd)
jnz LABEL_EVEN_2
shr $4,%ax

LABEL_EVEN_2:
and $0x0fff,%ax

LABEL_GET_FAT_ENTRY_OK:
pop %bx
pop %es
ret

.org 510 /* Skip to address 0x510. */
.2byte 0xaa55 /* Write boot flag to 1st sector(512 bytes) end */
::::::::::::::
loader.S
::::::::::::::
.code16
.text
mov $0xb800,%ax
movw %ax,%gs
mov $0xf,%ah
mov $'L',%al
mov %ax,%gs:((80*0+39)*2)
jmp .
::::::::::::::
solrex_x86_boot.ld
::::::::::::::
SECTIONS
{
. = 0x7c00;
.text :
{
_ftext = .;
} = 0
}
::::::::::::::
solrex_x86_dos.ld
::::::::::::::
SECTIONS
{
. = 0x0100;
.text :
{
_ftext = .;
} = 0
}
::::::::::::::
Makefile
::::::::::::::
CC=gcc
LD=ld
OBJCOPY=objcopy

CFLAGS=-c
TRIM_FLAGS=-R .pdr -R .comment -R.note -S -O binary

LDFILE_BOOT=solrex_x86_boot.ld
LDFILE_DOS=solrex_x86_dos.ld
LDFLAGS_BOOT=-e c -T$(LDFILE_BOOT)
LDFLAGS_DOS=-e c -T$(LDFILE_DOS)

all: boot.img LOADER.BIN

boot.bin: boot.S
$(CC) $(CFLAGS) boot.S
$(LD) boot.o -o boot.elf $(LDFLAGS_BOOT)
$(OBJCOPY) $(TRIM_FLAGS) boot.elf $@

LOADER.BIN: loader.S
$(CC) $(CFLAGS) loader.S
$(LD) loader.o -o loader.elf $(LDFLAGS_DOS)
$(OBJCOPY) $(TRIM_FLAGS) loader.elf $@

boot.img: boot.bin
dd if=/dev/zero of=emptydisk.img bs=512 count=2880
dd if=boot.bin of=boot.img bs=512 count=1
dd if=emptydisk.img of=boot.img skip=1 seek=1 bs=512 count=2879
rm emptydisk.img

# You must have the authority to do mount, or you must use "su root" or
# "sudo" command to do "make copy"
copy: boot.img LOADER.BIN
mkdir -p /tmp/floppy;
mount -o loop boot.img /tmp/floppy/ -o fat=12;
cp LOADER.BIN /tmp/floppy/;
umount /tmp/floppy/;
rm -rf /tmp/floppy/;

clean:
@rm -f *.o *.elf *.bin *.BIN

distclean:
@rm -f *.img

7 7 七夕

恩,今天是中国情人节,大家大概都知道。但我这里不是想写这个话题的,只是采用了标题党的惯用作法 :-)

其实我现在不太想写字,最近的生活没什么波澜,码字的激情少了许多。算了,还是写点儿和七夕有点儿联系的事儿吧。

昨天在豆瓣上看到一篇对《与二哥书》的评论:乡下人,来喝杯甜酒吧。

这句话是张兆和答应沈从文婚事的一封电报,源于沈从文托她征询父亲对婚事的意见:“如爸爸同意,就早点让我知道,让我这个乡下人喝杯甜酒吧。”多美的文字,可以载入传奇的一句话!

看到这句话,真想读读这本书,看看那个时代的爱情。每天面对电脑十小时以上,走出写字楼仍然觉得眼神呆滞的程序员,还能不能理解那是什么东西呢?

我真的不懂生在乱世的人,怎么能那么执着地追求一份看起来飘渺的爱情?大概他们也不可能理解我们,这些生在红旗下长在新中国沐浴在改革开放春风里的 80 后一代,小小年纪却都已如此现实如此势利。美丽的爱情,善变的人,可能远不及沉甸甸的孔方兄让人觉得心里踏实。如若不信,君可以到各大BBS 的某些版面,看看哪天没有类似的讨论?伪君子也好,真小人也罢,问问自己,能不能真的贫贱富贵均相濡以沫。于男人来讲,最着心者恐怕不过“才”“财”二字。又说多了,打住打住。

藉此也想起大学一年级那段与好友书信相通的日子,上次回家还翻出一个小本儿,最后一页上记录着谁谁谁哪天来过封信,很美好的回忆。不知道等我五十年后再翻开,心情又会怎样?

看来真的没什么想说的了,写到这里吧。

邮件签名的重要性

首先,非常感谢 Eric You Xu 师兄在博客里推荐我的博客,但嵌入式开发高手不敢当,我只能说在 GDB 的移植和远程调试方面有比较多的经验,离高手还有很大距离(不是谦虚,我一直想成为那种无论在哪儿都能独挡一面的程序员,努力中 ^_^)。

下面我开始发牢骚:
有一个人,中国某家公司的员工,大概也从事 GDB 的移植,前段时间一直问我有关 GDB 移植方面的问题,我也一直非常耐心的回答他。但是,但是,搞得我非常非常不爽,条缕如下:
1. 刚开始通过 Gtalk 与我联系,在我的状态为 busy 时给我发消息,而我工作时总是使用全屏的远程桌面,自然看不到消息。
2. 问我问题前不知道自我介绍一番,在我强调更喜欢邮件联系时仍给我发送 Gtalk 消息。
3. 由于对方没有自我介绍,我委婉地劝他最好使用公司信箱跟我联系,他说公司信箱不准向外发信,但你邮件总得有个签名吧,连签名都没有。
4. 在我使用公司信箱和他联系后,仍然发送工作邮件到我的私人信箱中,谁想在私人信箱中看到工作上的联系啊?
5. 后来总算有了签名,却是英文名,但没有公司信息,没有个人联系方式;我给他签名叫做 Wenbo,他抬头仍然使用 Hi Yang。
6. 最后我回答了他很多问题,忍无可忍了,因为谁也不希望帮助的人是自己的竞争对手,就算是义务劳动,也得搞清楚对方是谁吧。请他告诉我他的中文名字和公司,并且开玩笑说说不定哪天我可以到他们那里找工作呢。结果呢,就没有回应了。我猜,难道是怕我抢他的饭碗?太荒谬了吧。

其实我最不爽的就是他没有自我介绍,因为我觉得这是提问时,尤其是一对一提问时候起码的礼貌,唉!

所以我真的很希望大家都能看看 How To Ask Questions The Smart Way,晓得怎么做才是礼貌的问问题的方法。为别人也为自己,想想要是自己碰到这样的情况会有什么感觉。

至于自我介绍其实也不一定需要,只要养成在邮件中附加自己联系方式签名的习惯,像下面这样:
--
Wenbo Yang

SimpLight Nanoelectronics Ltd. 6 Zhichun Road, 10th Floor, Beijing, China
Phone: +86-10-5126-6989 --- Email: wenbo.yang@simplnano.com

一是方便别人,从邮件签名就能了解你的基本情况;二是方便自己,省得专门的自我介绍;三是宣传自己和宣传公司,不相信你 Google 一下 "Wenbo Yang" 和 "simplnano"。有这么多好处,为什么不使用呢?

Trace 啊 Trace

一周无事,要实现一个支持双硬件线程的 gdb stub,全是在写 interrupt 和 exception handler ,纯汇编编程,纯 trace 调试,16 和 32 bits 指令夹杂,总会有千奇百怪的问题,机器代码看得眼睛痛苦地要命,下班以后一会儿也不想多呆。有 GDB 用是多么幸福的事情啊,可是我需要给 GDB remote debug 提供支持,好歹算完了,大概只需要解决最后几个 BUG。

回去会看一会儿高达,因为室友喜欢看,而对于我这个定力不足的人来说,计算机书自然没那个有吸引力。还挺刺激,大机器就是男人的玩具啊!唉,下星期我一定要把我的美嘉影城的兑换券给兑了,变形金刚也好哈里波特也好,不然真浪费了。

买了几本书,Design Pattern,Artificial Intelligence,师兄豆列中推荐的。不过还是眼高手低,看完不知要何时了。

周末会出去走走,最近感冒的人挺多,要小心。

至于奥运那档子事,管它一周年也罢,几百天也罢,确定了,不掺和。什么东西到中国总会变味,既然被打上 me generation 的标签,还是 me 下去吧。

国家美术馆一游

黑乎乎地阴沉了一天,空气湿闷湿闷,到晚上总算开始下雨了。幸亏上次下雨带来的雨伞还扔在办公桌下, 北京 的雨是够少的,雨伞几个月才能用一次。

昨天难得去逛了逛国家美术馆,和小力姐还有她表姐。看了一个西班牙普拉多国家博物馆藏品展《从提香到戈雅》,基本上全是油画,基本上看不懂。像我这种连素描都觉得深奥无比的人,怎么可能有什么艺术欣赏能力呢?不过还是耐心地把每幅画都看了一遍,艺术欣赏能力嘛,要慢慢培养的。又想起来中国大学教育和美国的差距,公司里 Berkely 的实习生小 Kevin 下学期四门课有两门是非 engineering 的课,好像是一门美国文化,一门东南亚文化史。他说他要在暑假里看完八本书,这样去上这些文化类的课程时候,就不用再读了,只想怎么写文章好了。在我们大学里的这类课程,是向来受到鄙视而且不放在必修课程里面的。也不是说哪个好或者哪个不好,不过看问题的角度和需求确实很不一样。

mp3 被我摔坏了,虽然外面看一点儿毛病都没有,拿去修人家说坏得太厉害,只好返厂了。看来魅族的随身听质量也没那么好,三十厘米的高度都能摔报废。搞的我很郁闷,也不能拷电影回去看了。上次买了张中关村美嘉的电影兑换券,本来说去看变形金刚呢,唉,一直懒得动,现在看见就烦,扔不是不扔也不是。心血来潮果然不好,还是逮个空去看看吧。

很久不写记叙性的文字了,都觉得有点儿生疏了。大概是因为生活比较平淡,尤其是在感情方面,现在的女朋友对我很好,再没有以前的那种期望总变失望的苦闷。比以前更能随心地做事,不觉得有什么得失之类的强迫性的精神紧张了。

这一段时间来来往往的人还真不少,Baosheng 来大唐电信做技术支持两趟,小力姐来动物所提前报到了,表姐来武警总医院实习,表哥在丰台那面工作,周四哲子也会过来一趟。哈哈看来这京城和旧都还是不一样,真热闹。