标签 GNU 下的文章

Hacker Culture摘要

最近看了Eric S. Raymond的被称为开源文化圣典的'Cathedral and Bazaar'(大教堂与市集)以及他的另外一篇文章'How To Become A Hacker',必须承认的是我不能够完全理解其中的内容,因为没有体验,或者说我还不够资格对Hacker Culture高谈阔论,所以这里仅作部分摘要,并说说自己第一时间的感受,望日后能温故知新。

在开始了解Hacker Culture之前我们应该知道'什么是Hacker'。Hacker不同于Cracker,前者指那些热衷于计算机技术,水平高超的电脑专家,他们把通过自己的实践而获得的知识广泛传播;而后者则尤指那些为了个人利益利用计算机技术搞非法破坏的人。像我们耳熟能详的Hacker先驱包括开源软件运动的发起人Richard M. Stallman、Unix之父Ken Thompson、C语言的发明人之一的Dennis Ritchie、Linux之父Linus Torvalds以及Eric S. Raymond等等。我相信这些人才是从事计算机行业的人们心目中真正的'Hero'。

'Cathedral and Bazaar'可谓是开源世界对Hacker Culture的一个阶段性的小结,当然Hacker Culture还在进化,其内容也在不断的丰富当中。下面是从'Cathedral and Bazaar'摘录的一些我觉得能够代表Hacker Culture的语句:

1.Every good work of software starts by scratching a developer's personal itch.
这里有一个生僻词itch,这个词有'发痒'、'渴望'的意思。这句可理解为“每个好的软件工作都开始于满足开发者个人的渴望或为开发者个人'抓痒'”。Unix的起缘可以很好地证明这一点。而现在的大多数商业软件的开发者则不能归为此类,原因不讲自明。

2. Good programmers know what to write. Great ones know what to rewrite (and reuse).
Linus之所以能独立完成一个操作系统内核,很大原因是因为他没有'从头开始',而是利用已有的优秀设计思想。

3. When you lose interest in a program, your last duty to it is to hand it off to a competent successor.
Hacker也要'能上能下'。^_^

4. Treating your users as co-developers is your least-hassle route to rapid code improvement and effective debugging.
把用户当作协作开发者。

5. Release Early, Release Often
这与4相辅相成,互利互惠。Linux已经展现给我们一个Best实践,其“早发布、常发布策略”的一个效果就是利用快速的传播反馈修订来使重复劳动达到最小。

6. Smart data structures and dumb code works a lot better than the other way around.
优秀的数据结构设计总是至关重要的,在平时的开发中这一点体会破深。Brooks曾幽默地说:"Show me your [code] and conceal your [data structures], and I shall continue to be mystified. Show me your [data structures], and I won’t usually need your [code]; it'll be obvious."

7. Often, the most striking and innovative solutions come from realizing that your concept of the problem was wrong.
当你认识到你对问题的理解是错误的,这时不要灰心,因为一个具有革新性的解决方案也许正摆在你的眼前,我想很多人都有过类似的经历,Me,too。

8. "Perfection (in design) is achieved not when there is nothing more to add, but rather when there is nothing more to take away."
是不是颠覆了你以前对好的设计的理解了呢?

9. To solve an interesting problem, start by finding a problem that is interesting to you.
趣之所在,力之所在。

10. Software is developed for peer recognition not for money.
至高无上的境界,不为'铜臭'打工。

这里再列出一条,这是在一位同行给Eric的回复中提到的一条:"杀掉一个项目最快的方法是在你什么都还没有之前就宣布它,我已经见的太多了,尤其是在Linux世界里",看到这一条相信很多曾组织或参与开源项目的人都会深刻的体会到,Me , too。

中国程序员在开源软件世界中的地位大家也都略知一二,我想这或多或少都与我们对Hacker Culture的理解有关。理解和认同'Hacker Culture'是你进入开源世界的第一步,正所谓思想的融入才是真正的融入。

打开汇编之门

工作这么长时间,一直在C语言这一层面上钻研和打拼,日积月累,很多关于C的疑惑在书本和资料中都难以找到答案。程序员是追求完美的一个种群,其头脑中哪怕是存在一点点的思维黑洞都会让其坐卧不宁。不久前在itput论坛上偶得《Computer Systems A Programmer's Perspective》(以下称CSAPP)这本经典好书,遂连夜拜读以求解惑。虽说书中没有能正面的回答我的一些疑惑,但是它却为我指明了一条通向“无惑”之路 — 这就是打开汇编之门。

汇编语言是一门非常接近机器语言的语言,其语句与机器指令之间的对应关系更加简单和清晰。打开汇编之门不仅仅能解除高级语言给你带来的疑惑,它更能让你更加的理解现代计算机的运行体系,还有一点更加重要的是它给你带来的是一种自信的感觉,减少了你在高处摇摇欲坠的恐惧,响应了侯捷老师的“勿在浮沙筑高台”的号召。现在学习汇编的目的已与以前大大不同了。正如CS.APP中所说那样“程序员学习汇编的需求随着时间的推移也发生了变化,开始时是要求程序员能直接用汇编编写程序,现在则是要求能够阅读和理解优化编译器产生的代码”。能阅读和理解,这也恰恰是我的需求和目标。

在大学时接触过汇编,主要是Microsoft MASM宏汇编,不过那时的认识高度不够加上态度不端正,错失了一个很好的学习机会。现在绝大部分时间是使用GCC在Unix系列平台上工作,选择汇编语言当然是GNU汇编了,恰好CS.APP中使用的也是GNU的汇编语法。由于学习汇编的主要目的还是“解惑”,所以形式上多是以C代码和汇编代码的比较。

1、汇编让你看到更多
随着你使用的语言的层次的提高,你眼中的计算机将会越来越模糊,你的关注点也越来越远离语言本身而靠近另一端“问题域”,比如通过JAVA,你更多看到的是其虚拟机,而看不到真实的计算机;通过C,你看到的也仅仅是内存一层;到了汇编语言,你就可以深入到寄存器一层自由发挥了。汇编程序员眼里的“独特风景”包括:
a) “程序计数器(%eip)” — 一个特殊寄存器,其中永远存储下一条将要执行的指令的地址;
b) 整数寄存器 — 共8个,分别是%eax、%ebx、%ecx、%edx、%esi、%ebi、%esp和%ebp,它们可以存整数数据,可以存地址,也可以记录程序状态等。早期每个寄存器都有其特殊的用途,现在由于像linux这样的平台多采用“平面寻址[1]”,寄存器的特殊性已经不那么明显了。
c) 条件标志寄存器 — 保存最近执行的算术指令的状态信息,用来实现控制流中的条件变化。
d) 浮点数寄存器 — 顾名思义,用来存放浮点数。
虽说寄存器的特殊性程度已经弱化,但是实际上每个编译器在使用这些寄存器时还是遵循一定的规则的,以后再说。

2、初窥汇编
下面是一个简单的C函数:
void dummy() {
 int a = 1234;
 int b = a;
}
我们使用gcc加-S选项将之转换成汇编代码如下(省略部分内容):
 movl $1234, -4(%ebp)
 movl -4(%ebp), %eax
 movl %eax, -8(%ebp)
看了一眼又一眼,还是看不懂,只是发现些熟悉的内容,因为上面提过如%ebp、%eax等。这只是个引子,让我们感性的认识一下汇编的“容貌”。我们一点点地来看。咋看一眼汇编代码长得似乎很相似,没错,汇编代码就是一条一条的“指令+操作数”的语句的集合。汇编指令是固定的,每条指令都有其固定的用途,而操作数表示则有多种类型。

1) 操作数表示
大部分汇编指令都有一个或多个操作数,包括指令操作中的源和目的。一条标准的指令格式大致是这样的:“指令 + 源操作数 + 目的操作数”,其中源操作数可以是立即数、从寄存器中读出的数或从内存中读出的数;而目的操作数则可以是寄存器或内存。按这么一分类,操作数就大致有三种:
a) 立即数表示法 — 如“movl $1234, -4(%ebp)”中的“$1234”,就是一个立即数作为操作数,按照GNU汇编语法,立即数表示为“$+整数”。立即数常用来表示代码中的一些常数,如上例中的“$1234”。注意一点的是立即数不能作为目的操作数。
b) 寄存器表示法 — 这种比较简单,它就是表示寄存器之内容。如上面的“movl -4(%ebp), %eax”中的%eax就是使用寄存器表示法作源操作数,而“movl %eax, -8(%ebp)”中的%eax则是使用寄存器表示法作目的操作数。
c) 内存引用表示法 — 计算出的该操作数的值表示的是相应的内存地址。汇编指令根据这个内存地址访问相应的内存位置。如上例“movl -4(%ebp), %eax”中的“-4(%ebp)”,其表示的内存地址为(%ebp寄存器中的内容-4)得到的值。

2) 数据传送指令
汇编语言中最最常用的指令 — 数据传送指令,也是我们接触的第一种类别的汇编指令。其指令的格式为:“mov 源操作数, 目的操作数”。
mov系列支持从最小一个字节到最大双字的访问与传送。其中movb用来传送一字节信息,movw用来传送二字节,即一个字的信息,movl用来传送双字信息。这些不详说了。除此以外mov系列还提供两个带位扩展的指令movsbl和movzbl,我们举个例子来说明一下这两个特殊指令的作用何在:

a) movzbl指令
void dummy1() {
 unsigned char c = 'a';
 unsigned int a = c;
}
其对应的GNU汇编为(省略部分内容):
 movb $97, -1(%ebp)   //'a'的ASCII码为97
 movzbl -1(%ebp), %eax
 movl %eax, -8(%ebp)
说明:在dummy1函数中“unsigned int a = c”语句完成的是一个从unsigned char到unsigned int的赋值操作,由于int的类型长度大于char类型长度,所以实际是将一个字节的内容拷贝到一个可以容纳4个字节的地方,这样的话需要对源数据进行一下扩展,即填充高位的3个字节。

如何填充呢?由于变量a和c都为无符号整型,所以只需要填充0即可。而movzbl就是干这个活的。movzbl指令负责拷贝一个字节,并用0填充其目的操作数中的其余各位,这种扩展方式叫“零扩展”。

b) movsbl指令
void dummy2() {
 signed char c = 'a';
 unsigned int a = c;
}

其对应的GNU汇编为(省略部分内容):
 movb $97, -1(%ebp)   //'a'的ASCII码为97
 movsbl -1(%ebp), %eax
 movl %eax, -8(%ebp)
说明:在dummy2函数中“unsigned int a = c”语句完成的是一个从signed char到unsigned int的赋值操作,由于int的类型长度大于char类型长度,所以实际是将一个字节的内容拷贝到一个可以容纳4个字节的地方,这样的话需要对源数据进行一下扩展,即填充高位的3个字节。如何填充呢?GNU汇编告诉我们它使用了变量c的最高位来填充其余的3个字节。movsbl指令负责拷贝一个字节,并用源操作数的最高位填充其目的操作数中的其余各位,这种扩展方式叫“符号扩展”。实际上dummy2中变量a还是保留了变量c的符号位的,起码GCC是这么做的。

c) 在CS.APP中pushl和popl也别归入“数据传送指令”类别,但对于刚入门选手这两个指令还是稍显复杂,在以后谈到“procedure”时再细说。

3、小结
已经迈出了踏入汇编之门的第一步,汇编的确让我眼前敞亮了许多,看得多了,知道得多了,疑惑也就少了。

4、参考资料
1) 《Computer Systems A Programmer's Perspective》

[注1]
平面寻址:简单的将存储器看成一个大的、按照字节寻址的数组。不区分类型、符号、地址还是整数。注意汇编程序员看到也是进程空间的虚拟地址。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats