前段时间我在微博上看到了阮一峰的一篇日志 《计算机是如何启动的?》 才想起来自己之前也尝试探索x86架构计算机的启动流程来着,趁着还没遗忘就先记录下一部分结论吧。不过相对于阮一峰的这篇博文,我的侧重点在于BIOS查找“启动顺序”(Boot Sequence)之前,也就是从按下电源到BIOS移交权限之间的这一段。关于之后的过程,阮一峰描述的很详细,我就不重复造轮子了。

顺便罗嗦一下,有关“扩展分区”(Extended partition)的细节,阮一峰这里是正确的,多个扩展分区是“链式”的串起来的。网上有不少说法是错误的。倘若读者质疑,不妨用WinHex之类的工具直接以二进制打开磁盘,一看便知。Linux也可以用dd命令拷贝出磁盘的内容到文件,再查看文件内容。比如dd if=/dev/sda of=/tmp/xxx bs=512 count=1什么的。

言归正传,开始我们的探索之旅吧。不过,我们不会深入到开机电路之类的硬件问题上去,毕竟,我们还是以一个程序员的角度来看待计算机。同时,我们假定读者能完全读懂并理解上面我提到的那篇阮一峰的博文并且能理解寻址空间,实模式、保护模式、端口独立编址和端口统一编址等相关术语名词。

我们从按下电源开始。

首先,是CPU Reset主板加电之后在电压尚未稳定之前,北桥控制芯片会向CPU发出重置信号Reset,此时CPU进行初始化。当电压稳定后,控制芯片会撤销Reset信号,CPU开始工作。我们要探讨的第一个问题就是CPU执行的第一条指令的位置。

现在网上流传的资料基本上是8086 CPU的资料,给出的说法一般是这样:

CS寄存器初始化为0xF000IP寄存器初始化为0xFFF0,所以按照CPU实模式地址计算法则,CPU执行的第一条指令地址是CS*10h+IP,即0xFFFF0这里。

8086 CPU确实如此,但我们的问题是,80386及其以上的CPU怎么处理呢?其计算地址法则还是如此吗?当然不是,否则我说这些废话做什么。如果读者之前对实模式和保护模式寻址以及地址计算的理念根深蒂固的话,那么请先暂时忘却以前的认知,因为我下文说的也许有些惊世骇俗(我指的是相对于国产的某些教材来说)。

第一点,80386及其以上的现代CPU(以下CPU说的都是指80386以上的)加电Reset之后并不是直接进入实模式

第二点,CPU在合成地址的时候并不区分实模式和保护模式。

Read More

这学期被自愿的选择了《Web应用程序设计》这门课,还是自学课。好吧,反正基础的HTML和CSS迟早也是要学习的,就提前学吧。

按照我的性子,当学习新的语言以及语法规则的时候,我就又开始折腾编辑器的语法高亮和配置自动补全功能了。其实接触到新的语言时,我个人建议还是不要急着去寻找相关的IDE去使用,还是先用基本的文本编辑器写,尝试自己手工去构建。等到理解了之后再使用IDE提高编码效率也不晚。IDE的方便是建立在对很多细节的屏蔽之上的,这样对学习新的知识没有益处。没有手写HTML的经验,全靠IDE点点按钮,拖拖控件的设计人员在调试的时候就会是一场噩梦。

另外,个人吐槽下网上到处可见的什么“真正的高手写代码只用记事本”。你确定是notepad?没有++?好吧,个人感觉用记事本写代码如果不是临时找不到替代品之外,除了装逼就再没有什么意义了。即便是不需要IDE的自动补全和错误检测,个人认为代码编辑器的语法高亮和格式调整还是很重要的。手工调整格式很麻烦,而语法高亮除了看起来赏心悦目还能指出来明显的拼写错误。方便的代码编辑器notapad++、Vim,Emacs等等是很好的选择。

废话少说,言归正传。我们今天给熟悉了HTML和CSS的程序员推荐一款文本编辑器的插件——Emmet。如果你没有听说过Emmet,那你至少听说过大名鼎鼎的Zen coding吧?Emmet就是Zen coding的新名字。什么?你没有听说过?太好了,你可以继续看下去了,否则,也就没有看的必要了……

简单介绍下Emmet,官方是这么说的“Emmet is a plugin for many popular text editors which greatly improves HTML & CSS workflow”。

官方主页在 http://www.emmet.io/

Emmet作为文本编辑器的插件提供给 Eclipse/Aptana,Sublime Text 2,TextMate 1.x,Coda 1.6 and 2.x 等等编辑器作为扩展。我们以我比较喜欢的编辑器 Sublime Text 为例介绍下安装与使用方法吧。(暂时先委屈下Vim,因为Vim的插件自动补全是“Ctrl+Y+逗号/分号”,这个快捷键很不好用,而我还没有找到修改的方法 我暂时在vimrc文件里加入 imap ; 映射到Ctrl+E,官方的重定义方法太麻烦了)

Read More

那个C++写的网络数据包捕获分析的程序终于告一段落了。因为学校明年的教学安排有Java程序设计,再加上去年C++的教学方式让我到现在还心有余悸,所以我觉得还是提前翻翻Java的基础知识比较好,免得到时候再一次被动。

C++虽然只是学了一点点皮毛,但是OOP的基础概念之类的东西还是知道一些的。我在看Java基础的同时依旧在复习C++。这两种语言实现OOP的方式不尽相同,这样一边比较着一边辩证学习倒也颇有乐趣。

相较于Java,窃以为C++确实在对OOP的支持上确实略有逊色。我还是坚持自己以前的看法,即C++是大杂烩式的语言,以至于很难把C++归到哪一类。至于C++和OOP的关系,窃以为只能说是C++提供了一些特性,这些特性在一定程度上支持面向对象编程罢了,而不能说C++是一门OOP语言。C++的确是一门没有完全成熟的语言,很多所谓熟悉C++的人不过是在用C++的语法在写C语言程序罢了。就像Linus说的那样,“C++是一门糟糕的(horrible)语言。而且因为有大量不够标准的程序员在使用而使情况更糟,以至于极容易产生彻头彻尾的垃圾(total and utter crap)”。

我这么说并不是我不喜欢C++而找茬,相反,我个人很喜欢C++,但是我不掩盖C++的确存在的不足。我向来不认同说某种语言比某种语言好的论述,因为这要分情况来研究。假如语言是工具,我们总不能说榔头总是胜过锯子吧?这得分情况讨论,不是吗?

好了,不谈这些会挨喷的话题了,毕竟对技术的看法都是个在人学习和理解的基础上产生的,不同的环境和不同的学习历程就会有不一样的看法。我们不可能强求别人认可自己的观点,也没有必要非得去争个脸红脖子粗,没意义的,看法也不过就是看法么。

上面的话各位看官批判着去看就好了,貌似我从很早就学会了审视的去看别人的文章,有时也刻意的去“找找茬”。不过我们真应该学会批判着去看待技术类文章,和作者意见相同或者相左没有什么大不了的,学会自己思考才是最关键的。我喜欢那种独立思考之后再和别人的思维碰撞的感觉,方法上孰优孰劣倒是退居其次,重要的是通过这种方式,自己能学到新的思路和方法。

毕竟年关将近,只有零散的时间去研究技术。我们就不谈具体的技术细节了,来说说我最近做项目的一些感慨吧。再次声明,我毕竟在这一行阅历有限,谈到的不过是自己这两年学习的感触和一些方法的总结。这些方法不见得适用于任何人,也不见得每个人都能认同我的看法。不过即使意见相左,您也没必要非得和我争个青红皂白不可,您批判着看就可以,哪怕是全盘否定都行,我向来也不愿意在这些问题上浪费时间。

Read More

最近在读《深入理解计算机系统》(顺便打个广告,卡内基梅隆出品的这本书绝对精品),在书的48页提到了在C语言标准库limits.h中将int类型的最小值INT_MIN定义为-INT_MAX-1。书中提到了为何不写做-2147483648或者0x80000000,但是并没有给出解释,只是说这需要我们钻研C语言标准的一些比较隐晦的角落。

我们先看看MSVC的相关头文件内容:

GCC也给出了类似的定义方式:

为何是这样呢?这个头文件对我来说并不陌生。这几个宏也时常在用着,但是从没有注意过这个细节问题。百度一番后没找到满意的答案,最后勉强找到了http://www.hardtoc.com/archives/119这个比较靠谱的答案。因为英文看起来比较麻烦,再者作者描述的也不是很清楚,我写篇文章 权当翻译 一下,再加上一点点自己查到的内容。

我们先来查看C语言标准文档是怎么解释常量的,ISO/ANSI C99 和C11对于这里的描述是相同的。我们摘录下来:

“An integer constant begins with a digit, but has no period or exponent part. It may have a prefix that specifies its base and a suffix that specifies its type.”

大概意思是“一个常量起始于一个数字,但是不包含小数点或指数的部分。并且可能有一个用于指定数字基底的前缀和一个指定类型的后缀。”

Read More