史记:语言和编译器传 - 跨平台软件自由谈 - 胡元志

(这条文章已经被阅读了 45 次) 时间:2002-01-16 01:47:36 来源:胡元志 (逢一笑) 转载

我的回忆和一些不大有趣的故事 weizhisheng(原作)

关键字 C,Pascal,Basic

有许多朋友对我说他们对编程语言发展的历史很感兴趣,可惜的是这方面的资料少之之少。我本人也很喜欢看这方面的东西,李维的两篇作品《我的回忆和一些有趣的故事》以及《C++圣战》是我看到过的两篇非常好的文章。我想在这里以Basic、Pascal和C这三大编程语言在DOS/Windows平台上的发展为主题,把我所知道的和自己经历过的一些事情记录下来,同时尽量避免和李维的文章在内容上发生撞车的情形。我自己并没有很丰富的资料,也缺乏足够的阅历,不过片言只语亦可聊供一观。因为是靠着记忆写下的,并不敢保证所有内容都非常准确,如果您有发现任何谬误的地方,非常欢迎您的指正。

曾经有一度Basic是DOS操作系统上最风光的编程语言,而那时候各种各样的Basic编译器也可以说得上是百花齐放,包括IBM BASICA, Microsoft GW-Basic以及后来的QuickBasic,True Basic,连Borland也推出了Turbo系列的Turbo Basic,好不热闹。虽然我们现在常说Basic有这样那样的缺陷,然而在当时Basic却是非常强力的系统开发语言,比如可以用INTERRUPT语句调用DOS/BIOS中断(中断调用在DOS程序中的地位就好比是Windows下的API函数一样),也可以和汇编模块接口,所以即便是开发底层系统问题也不大。Microsoft在MS-DOS操作系统中还附带了一个QBasic(又是M$一贯的捆绑销售手段),可以看作是Microsoft QuickBasic的简化版本,目的是方便用户完成一些简单的任务,从中也可以大致看到Basic语言当年在DOS开发中的地位。

各个厂商的Basic编译器共同造就了Basic语言的繁荣景象,不过也带来了一些问题。其中最大的问题就是Basic语言缺乏一个统一的规范。当时的软件工程思想还停留在极为原始的时代,而各个厂商为了提高自己产品的竞争力,总是尽力向自己的Basic产品中加入各种各样的扩展,这些扩展没有任何标准,不可避免的造成了非常混乱的局面,也导致了移植性等诸多让人头疼的问题。这些问题到后来愈演愈烈,以至于Basic语言的发明人G。Kemeny和T。Kurty也觉得无法再坐视不理,终于有一天他们联名发表了一封措辞激烈的公开信,抨击他们所谓的“Street Basic”,认为这些“Street Basic”的所作所为是在污染Basic语言的纯洁性,并且是在把Basic程序员向坏的道路上引导。在和所抨击的对象中,首当其冲的就是IBM BASICA和Microsoft GW-Basic。两位大师所推崇的是自己所编写的True Basic,他们认为True Basic才是结构化良好、风格优美的Basic语言的代表。此信发表后引起了极大的反响,也促使许多程序员开始重新审视和反思Basic语言。遗憾的是,Basic并没有按照两位大师所设想的那样发展下去,在激烈的市场竞争中许多Basic编译器包括一度被看好的True Basic都相继倒下,再到后来,Borland推出的Turbo Pascal和Turbo C成功占领了大半开发工具市场,Basic语言也逐渐退居二线,从此宣告了Basic黄金时代的终结。

现在Visual Basic基本上是Basic语言在Windows平台上唯一的代言人了,有趣的是Visual Basic自从出世起就存在着极大的争议,激进的语言纯化论者认为Visual Basic是个怪胎,而实用主义者则觉得无所谓;并且Visual Basic的效率问题也一直是为人所诟病的焦点,其实Visual Basic自从5.0版本以后在效率上已经有了极大的提高,再非昔日吴下阿蒙。然而,有关Visual Basic“低效、迟缓”的说法仍然广泛流传,而且一直是反对者攻击Visual Basic的主要罪状,这倒是一个颇为有趣的现象。

有关Visual Basic是否“简单”的问题倒是可以多说两句。Microsoft原本推出Visual Basic的时候,为了强调它的简便易用而隐藏了很多细节,对于整日在SDK里面摸爬滚打的程序员来说,Visual Basic的出现着实让人眼前一亮,于是许多人欢呼:原来编程也可以这么简单。在这个时候,Visual Basic简直成了Windows程序员的苦海明灯。可是,随着Windows的不断发展,新技术和新功能层出不穷,而Visual Basic面对这些新问题的时候却显得有些捉襟见肘,“VB只不过是玩具语言”的讥评也在这时候出现了。Microsoft只好不断的向Visual Basic添加新关键字来扩展它的功能,可是这种做法多少有些削足适履的嫌疑,也引起了不少语言专家的批评。Visual Basic现在也变得非常复杂了,这在一定程度上可以说已经违背了Microsoft当初设计Visual Basic的初衷。

我本人对于“XX语言简单易学”这种说法抱着很大的怀疑态度。现实问题本来就是纷繁复杂的,所以任何致力于解决现实问题的程序语言也不可能非常简单。所谓“简单易学”者,要么是宣传口号,要么这种语言本身的功能就有所限制。(如果说某一特定领域的专有语言简单易学,那倒不是没有可能,比如Javascript这一类的脚本语言比起一般的程序设计语言来说就要简单的多。不过,要是将相关的其他网络编程元素一齐考虑进去,则即使是脚本语言也不是那么简单的。)

提到DOS平台上开发工具的历史就不能不提起Borland,正是这个公司推出的Turbo Pascal和Turbo C这两款神兵利器成功奠定了C和Pascal这两大编程语言在DOS/Windows平台上不可动摇的根基,也开创了Borland历史上最为意气风发的一段时期。Turbo Pascal和Turbo C也是世界上使用人数最多的编译器,以至于在很长一段时期内它们几乎成了Pascal和C的代名词。在Turbo Pascal和Turbo C中引进的集成开发环境(IDE)概念,至今仍然让我们受益良多。早期的Borland是一个高手云集的地方,在那里集中了大批技术精英,包括Microsoft在内的其他任何编译器厂商都没有像Borland那样的技术实力,所以Borland的名字在当时就是品质的保证。不过,经历了后来发展的曲折和动荡,许多最优秀的人才渐渐从Borland流失,他们中间一部分到了像Numega这样技术性很强的公司继续谋求发展,还有一部分则被Microsoft所挖走,可惜的是除了Anders Hejlsberg等少数顶尖人物之外,他们中绝大部分人都渐渐湮没无闻,想想也令人扼腕叹息。

在这个时期另外一个值得一提的名字是Watcom C++,要说起Watcom C++的兴起还不得不先说一点题外的话。我们知道Intel x86系列机器的基本地址定位是采用segment:offset这样的表达方法,不过这种方法其实是有许多弊端的,最典型的就是臭名卓著的“64k”限制,也就是说:任何代码段、数据段或者堆栈段的大小不得超过64k;任何动态分配的内存大小也不得超过64k。如果要跨段调用数据或者代码的话,又会引一连串难缠的问题。同时,这种内存寻址方式也限制了总共能够存取的内存大小不能超过1M,而实际上在DOS操作系统中,低端1M内存空间的高位(384k)要为设备驱动程序和ROM BIOS保留,所以真正留给程序的内存不足640K,要在这么有限的空间里编写程序简直就是带着镣铐跳舞。为了让程序员能够存取1M以上的内存,当时的多个厂商(包括IBM、Microsoft、Lotus等等)联合制定了一个扩充内存管理规范,这个规范的原理是将1M以上的内存划分成多个页面,程序员需要的时候可以换入指定的页面,不需要的时候再换出。(是不是很象Windows下面虚拟内存的概念?)不过这个规范实在是过于原始,原因之一是换入换出的操作步骤太过繁琐,另外,要程序员自己管理所有页面的分配和置换…呃,怎么说好呢…简直就不是人干的活。相应的,DOS下面的内存寻址也是麻烦的不得了,比如说光是指针就有near/far/huge模式的区别,而程序的内存模式也分成tiny/small/medium/large/huge/compact等等许多级别,如果稍微不注意这些地方的话,那DOS程序员要面对的就很可能是一场噩梦。(我就曾经有一段时间,被扩充内存、扩展内存、上位内存、高位内存、UMA、HMA、EMS、XMS这些看似相近,实际上大相径庭的名词弄得昏头转向不辨东西。)

在当时,不论是Borland还是Microsoft对这个问题都没有提供很好的解决方案,而Watcom C++的出现无疑是久旱逢干雨,被折磨得痛苦不堪的DOS程序员终于看到了一线曙光。Watcom C++的办法是让程序在所谓的“保护模式”下运行(其实Windows操作系统也是这么做的),在这种模式下无论存取多少内存都没有问题,并且方法也非常的简单。有一位老程序员在第一次用Watcom C++成功分配了整整1M内存的时候,这样形容他此刻的心情:“我感动得想哭!”这句话深深印在了我的脑海中,也让我联想起另外一位著名程序员的话:程序员的生活就是在痛苦的地狱和快乐的巅峰之间反复震荡,只有在这种生活中才能体会到人生的真义。闲云谭影日悠悠,物换星移几度秋。我们今天的程序员是否仍然能够体会到这种心情呢?

正是因为有了这么吸引人的功能,所以即使是在Borland虎视于前,Microsoft狼顾于后的C++开发工具市场上,Watcom C++仍然取得了辉煌的成功。特别是对于开发DOS下面的游戏来说,Watcom C++在相当长的时期内几乎是不二的选择。可惜的是Watcom缺乏一位有眼光的领导者,没有能够巩固和发扬Watcom C++的优势,在Windows兴盛以后逐渐失去了往日的光彩,最后在激烈的市场竞争中黯然出局,让许多曾经是Watcom忠实Fans的程序员空为之魂断神伤。

让我们把目光再次聚焦到Borland和Microsoft两大巨头的较量。Microsoft最初用来和Turbo C较量的是一个称为QuickC的产品,有趣的是这个产品在编译速度上确实是非常的Quick,但是产生的代码却过于庞大,而且执行效率也不尽如人意。Microsoft后来放弃了QuickC而开始Microsoft C/C++的开发,不过QuickC中有一个相当不错的编辑器却被Microsoft保留了下来,这个编辑器就是后来Microsoft的开发环境(包括初期的PWB——Programmer’s WorkBench以及后来的Developer Studio)的基础。在这个时期Microsoft C的编译器技术仍然远远落后于Turbo C的水平,不过失之东隅,收之桑榆,Microsoft QuickBasic却在这个时候战胜了一些对手而赢得了相当的市场份额。作为开发工具市场老大的Borland对此自然不能熟视无睹,不久Borland就推出了自己的Turbo Basic来与QuickBasic抗衡。Turbo Basic有着和Turbo Pascal与Turbo C非常相似的工作环境,而且编译和执行效率也都相当不俗,再加上Borland的品牌作后盾,所以Turbo Basic诞生后很快也争取到了相当多的客户。而Microsoft在这个时候非常出人意料的公布了Microsoft Pascal的开发计划,当时很多人对Microsoft的计划都不抱乐观态度,因为Borland就是靠Pascal起家的,Microsoft要在自己的软肋上和Borland竞争,希望实在太渺茫了。过了一段时期,还未成熟的Microsoft Pascal突然胎死腹中,而Borland在Turbo Basic 1.0版本之后不久也停止了进一步的开发和推广。于是业界盛传Microsoft和Borland私下签订了一个协议,彼此不进入对方的市场,这个消息是否属实则不得而知。

在操作系统进入Windows时代以后,Borland和Microsoft都迫切需要新一代的开发环境。Microsoft在这个时候推出的Microsoft C/C++ 7.0多少有些出人意料,因为作为Windows生产厂家,Microsoft自己推出的开发工具竟然还是一个基于DOS的环境,这意味着它虽然可以在Windows下运行,但是将无法利用Windows系统的许多优秀特性,包括易于操作的图形界面和存取扩展内存的功能等等。而Borland同期推出的Borland C++ 3.0已经是一个真正的Windows图形界面开发环境了。不过对于Microsoft来说,这一时期真正值得纪念的最重大事件是Visual Basic for Windows的问世,Visual Basic中的Form-Based Programming Modal在当时看来的确是非常具有革命性的功能,也让许多在繁复的SDK中挣扎的程序员从此解脱出来,因此Visual Basic很快取得了喜人的市场佳绩。

我想,Microsoft之所以多年来一直独钟于Visual Basic,并不单单因为Microsoft是以Basic起家的,恐怕更重要的原因是Visual Basic代表了MS的光荣与梦想,因为在开发工具市场当了多年的老二之后,Visual Basic的成功第一次让MS从Borland手中抢得了一些风头,也标志着Microsoft在这一市场上开始吹响了反攻的号角。

那么这时候Borland在干些什么呢?一方面Borland加紧将Borland C++从3.0升级到3.1版本,大幅度改进编译器功能并且加入Borland的得意之作OWL;另外一方面,Borland也没有忘记自己的老本行Pascal,下一步自然就是将Turbo Pascal编译器移植到Windows平台上面来。但是将Pascal移植到Windows平台上的工作面临着一个很大的问题,就是Microsoft公布的Windows开发权威资料Windows SDK,包括各种头文件、库文件、资料、文档和示例程序等等在内,全部都是以C语言为基础的,Borland有没有能力把它们完全转化成Pascal语言的形式?虽然没有人怀疑Borland的实力,但是这项工作看起来还是相当的艰巨,因此在Borland公布Turbo Pascal for Windows的开发计划后,很多业内人士都不相信Borland能够按时推出这个产品,还有人断言Borland的这个计划肯定会失败。这些人中甚至还包括鼎鼎大名的Windows编程大师Charles Petzold在内。

但是后来的事实表明他们都错了。Borland不仅按时发布了Turbo Pascal for Windows,而且这个产品问世后再次引起了巨大的轰动。我还记得Turbo Pascal for Windows的安装界面是这样的:画面中心是一辆轿车在高速公路上飞驰,一旁的路标上写着几个大字:“Speed Limit:∞”。Borland的目的自然在于强调TPW带来的极速快感,而TPW的速度也确实给人留下了深刻的印象,它比同时期任何其他编译器,包括自己的同族兄弟Borland C++都要快得多。更令人惊讶的是TPW生成的代码无论是在大小还是执行效率都堪称是最优的。用TPW 1.5编写的一个最基本的“hello, Windows”程序在最大优化后的大小居然可以达到不可思议的1.75k!而且这个程序除了Windows三大基本模块(kernel,user,gdi)以外不需要其他任何DLL支持,这么小的尺寸是任何C/C++编译器都无法做到的。(用Borland C++ 3.1产生的同等功能的程序,最小的尺寸也有6.5k左右。C/C++程序比较大的主要原因在于程序必须连接C Startup Code,而由于C/C++语言的复杂性,这些代码的大小是相当可观的。)实际的评测表明TPW产生的程序在执行效率上面也要略微优于Borland C++产生的程序。

TPW的成功不仅对那些怀疑Borland的人是一记有力的回击,同时也表明Pascal语言的潜力是不可低估的。我至今还记得当Delphi 1.0刚推出不久的时候,各种Delphi论坛上最热门的问题就是“如何用Delphi产生一个小于4k的应用程序”。答案当然就是抛开VCL,纯粹采用API来编写。不过要让可执行文件的大小不超过4k,除了汇编以外,唯有TPW和它的后继者Delphi能够做到。

TPW的发展只经历了两个版本,因为Borland已经日益感受到Visual Basic的威胁:Borland也需要一个真正的RAD环境来和VB相竞争,而TPW基本上仍然是类似于Borland C++的文本编辑环境,不是真正的RAD工具。至于Borland为什么选择Pascal而不是C++作为RAD环境的基础语言,一方面自然是因为Borland在Pascal语言上的深厚家底,另一方面恐怕也是出于效率的考虑。别忘了在当时386/486还是相当普及的机型,Pentium在那时候还是少数人的奢侈品,在这种机器上Visual Basic的效率实在是不敢恭维。而作为VB Killer的Delphi,一个主要的目标就是在效率上超过它,让快如闪电的Pascal编译器来扮演这个角色当然是再合适不过。Borland的功力确实不同凡响,虽然Delphi的推出比VB慢了一拍,但是Delphi 1.0一出世就在各项指标上全面超越Visual Basic 3.0,其中Borland特别强调的一点就是“Delphi 1.0程序的速度要比Visual Basic 3.0快40-50倍”。是否差距真的那么悬殊我无从知晓,但Delphi 1.0效率比VB 3.0高得多却是不争的事实。再加上Delphi其他方面也非常优秀,比如说Delphi 1.0提供的组件比VB 3.0中丰富得多,而且Delphi 1.0对数据库的支持也比VB 3.0要好。所以Delphi 1.0一经面世,不仅Turbo Pascal的老用户趋之若骛,而且不少原先的Visual Basic用户也逐渐转移到Delphi上面来。

说到这一段历史的时候我常常为Borland感到惋惜,因为Borland中有一批非常有远见的工程师,他们在Borland C++ 3.0还在雏形阶段的时候就已经提出了开发一个RAD开发环境的构想,现在看来这个想法实在是非常的富有远见,可惜Borland当时的总裁Kahn太过陶醉于Turbo系列和Borland C++的巨大成功,对手下的建议没有引起充分的重视,反而把心思都用在Borland并不擅长的其他一些领域。后来的结果大家应当都知道了,Borland由于一系列的决策失误,导致在C++开发工具、数据库和电子表格等领域全线溃败,自己也跌入了公司成立以来的最低谷。如果Kahn能够早一些审时度势,及时采纳合理意见,早一些推出Delphi(当然那样就未必仍然是Delphi的名字了)的话,那么眼下的Delphi恐怕还将远远不止目前的局面。不过,在Borland最困难的一段时期,也正是由于有Delphi这根中流砥柱的支持,Borland才能够熬过那段不堪回首的岁月,不至于全军覆没。所以说Delphi之于Borland,也正如同Visual Basic之于Microsoft,已经不仅仅是一个产品那么简单,而已经成为一种复兴的象征和辉煌的纪念碑,从某种意义上说也是整个公司的希望和灵魂。

在Borland最为黑暗的这段日子里,让Borland损失最惨重的恐怕还不是市场的流失,而是许多优秀人才的纷纷出走。在经历了公司业绩下滑、市场萎缩、客户转向的打击之后,不难想象曾经辉煌的他们会是怎样的一种心情。最让他们感到痛苦的可能还是公司的内部产生了难以弥补的裂痕。Borland总裁Kahn是一位技术上无可挑剔,而且非常有雄才大略的难得的领袖人才,正是他领导Borland创造了开发工具市场上的一个神话,还有Borland长达10多年的黄金时代。但是Borland的强大也使得Kahn开始逐渐变得刚愎自用,当时Borland在高速的发展过程中已经出现一些不合谐音,公司中一部分敏锐的员工也察觉到这些问题并建议Kahn尽快解决,而这时候的Kahn已经很难听进任何不同意见了。因为自己的意见不被重视,所以Borland中一部分非常优秀的技术人才在Borland的鼎盛时期就负气离开了Borland,这也间接导致了后来Borland C++ 4.x版本的水平下滑。最终,在风雨飘摇的愁云惨雾中,许多顶尖人物带着爱恨交织的复杂心情离开了曾经寄托他们梦想的Borland。唉,可惜了这些技术精英,可惜了Borland啊!

这些优秀人才离开Borland以后,其中一些人靠着在Borland培养起来的深厚技术继续从事开发工具的编写,比如Numega这一类的公司中很多高级工程师都和Borland有着或多或少的关系;而Microsoft在这个时候也不失时机、不惜血本地展开挖角战术,我们所熟悉的Turbo Pascal和Delphi的缔造者之一,也是Borland创始人之一的Anders Hejlsberg最后也投奔了微软。这个结果对Microsoft来说无疑是梦寐以求的,因为多年来在编译器技术上MS只有跟在Borland后面亦步亦趋的份儿,有了这样一大批优秀的工程师和他们带来的技术,再加上同一时期Microsoft从Unix平台上网罗的许多资深专家,Microsoft终于能够在编译器技术上有一个质的飞跃,登上开发工具老大的位置了。尽管Microsoft当时不择手段的挖角攻势激起了业界的普遍反感包括许多盟友的指责,但Microsoft宁肯受此恶名也要达到自己的目的,所以我们后来看到Visual Studio系列中的Visual C++ 5.0和Visual Basic 5.0编译器比起它们的前辈来说真的是焕然一新,Visual C++编译器第一次能够和Borland的C++编译器一较高下,甚至在许多代码优化的功能上还超过了Borland C++;而Visual Basic通过将代码编译成native code的功能,也终于洗刷了长期以来饱受“Visual Basic代码效率低下”诟病的耻辱。

流光容易把人抛,红了樱桃,绿了芭蕉。转眼之间数十个年头过去了,而DOS/Windows平台上Basic/C/Pascal这三大程序语言的兴衰,则是一个讲不尽、道不完的故事。近年来,三大语言又面临着像Java和C#这些新生代语言的强力挑战。不知为什么,这种形势总让我联想起中国几千年来的历史,来自北方的、骠悍尚武的游牧民族,一次又一次的入主中原,成为军事上的征服者,最终却成为文化上的被征服者的情况。我觉得,Java和C#这些语言也与此多少有些类似,因为Java和C#都是属于那种带有极强的功利主义色彩的语言,它们讲求的是快速,准确,一击必杀的效果,而不像C++那样讲求理论和传统。这些新兴语言带来的活力和激情是毋庸置疑的,然而在我看来,它们都还缺乏像C++那样深广的内涵和强大的包容能力。所以我猜想这种情况发展的结果,最后必将是某种程度的融合,就象是马背上的征服者最后融入中华民族数千年来绵延不绝的血脉之中——当然,其间恐怕也少不了残酷的斗争和文明的碰撞了。