斯蒂夫·沃兹尼亚克是如何为Apple从零开始开发BASIC的
英文原文:How Steve Wozniak Wrote BASIC for the Original Apple From Scratch
为了庆祝 BASIC 诞生五十周年,斯蒂夫·沃兹尼亚克写下了一些文字,讲述了他与这个广受欢迎的开发语言的旧事,他是如何为 Apple I 和 Apple II 从零开始创造了他自己的 BASIC 语言。
1967 还是 1968 年高中快毕业的时候,我的电子学老师(此生所遇最好的一位老师)介绍我到位于森尼韦尔的喜万年公司参与电脑编程工作,因为我在学校时已经掌握了全面的电子 学知识。McCollum 先生每年都会为掌握了扎实电子学知识的学生安排实习,将他们送入当地的公司。在这些公司的工程师和项目的帮助下,这些高中生可以获得实习经验。当时我在 IBM 电脑上学习和使用 FORTRAN 语言进行编程。
也就是在那一年我第一次接触了 BASIC 语言。学校里那时并没有电脑,但通用电气公司有,我想他们是利用那个带调制解调器的终端来提升他们的分时业务的。我们中几个数学比较好的学生拿到了几页说 明,然后用 BASIC 语言写出了很简单的几个程序。我觉得 BASIC 简单易学易上手,但是当时那台电脑只在我们学校放了几天。数学老师还让我写一份报告来说明电脑对学校会有什么好处。报告里我从逻辑思考和解决问题这两方面 进行了阐述,但是学校之后并没有在分时程序中有进一步动作。
大学时我的编程语言主要是 FORTRAN,PL-1 和 Algol。当然,我在学校和家里也经常使用汇编语言来编程。
在 Homebrew 电脑俱乐部的时候,有几本被我奉为“圣经”的书籍。一本是 Ted Nelson 的《Computer Lib/Dream Machine》,描述了未来世界里的超链接。他的想法像科幻小说,但我们都觉得那些想法在技术上是可行的。他如此看待未来的电脑运作,而我们就是他的信 徒。另一本“圣经”就是《101 Games in BASIC》。我是一个电脑游戏迷,曾想过以后要有电脑的话我会要把所有游戏都放入电脑玩一遍。感觉让我相信,这将是开启家用电脑革命的关键所在。我身体 中非商人的那一部分让我远离谈论市场和财政。
电脑为公司处理财政工作,这些电脑售价昂贵,而一台真正的电脑为此需要些什么,我并不是十分清楚。那些电脑物有所值。而我所清楚知道的只有眼前 的东西。在惠普工作的时候,我在计算器上从事仿真芯片设计和逻辑设计。我的电脑必须能做这些事。我的电脑还必须能够玩游戏。至少我肯定一点,我的电脑应该 能做那些昂贵的电脑能做的事,但我还不是十分肯定。
游戏的关键所在就是 BASIC。那时比尔·盖茨在电子学领域之外无人知晓。俱乐部里的人都知道他已经为英特尔的微处理器编写了 BASIC。经过深思熟虑,我认为要让我的电脑好用(受欢迎)的话,必须使用一款高级语言,而这款语言只能是 BASIC。开启家用电脑革命的不会是使用 FORTRAN 的程序员。
学习 BASIC 并为之写一个解释器
我当时对 BASIC 几乎一无所知,高中有过的三天接触只让我勉强记住了它的每行语句前面有行号。于是我挑了一本 BASIC 手册开始熬夜研读,在笔记本上记下了这种语言的各种命令。而之前我从未学习过如何编写编译器(或解释器)。还好我在麻省理工的朋友 Allen Baum 给我寄了一些这方面的影印讲义,因此我也可以声称我是毕业于麻省理工的,哈哈哈。大二的时候,我在数学分析课上努力自学如何编写 FORTRAN 编译器,虽然我根本不懂编写编译器的相关知识。那时起,我开始为我的 6502 微处理器编写代码,逐行读取用户输入的命令,进行分析和错误检查。
我懂语法图知识,于是为这个 BASIC 创建了一份语法图。那时我并不知道 HP BASIC 和 DEC BASIC 大相径庭,后者正是《101 Games in BASIC》中使用的,也正是比尔·盖茨编写的那个 BASIC。我以为所有的 BASIC 都是一样的,但是在处理字符串时,惠普的 BASIC 非常不一样。然后我完成了语法图,完整的语法图。我隐约觉得如果我能为 6502 编写第一个 BASIC 的话,我将会成为一颗明星,在业界会小有名气,就像比尔·盖茨那样。为了节省一些时间,我将浮点运算从语法图中剔除了。在为惠普工作时,我需要编写基于整 形的模拟,而游戏正是基于逻辑的,也就是基于整形的。放弃浮点小数为我节省了几个星期的时间,让我更快地成为 6502 上开发出 BASIC 的第一人。你会看到在 Apple II 上我使用了浮点运算,但是在 BASIC 上我从没有使用过。手动写代码的时候,要更改位于中间位置的固定地址上的东西是十分困难的。
Breakout on?Integer Basic?running on the original Apple II.
我不懂如何编写编译器并非偶然。但是我确实了解堆栈以及如何利用堆栈将表达式转换成逆波兰表达式。惠普的计算器正是使用的逆波兰表达式。在思考 如何编写 BASIC 时,我使用了自己脑中的技巧,而非来自书本的技巧。我使用了称之为 NOUN 和 VERB 堆栈(操作数和运算符)的东西。在语法图中我使用了标签,但是在这个 256-byte 还是 512-byte(记不清了)的表中,每个运算符都有一个与其线性位置一致的编号。譬如第 41 个操作数具有 41 号运算符的代码。
我还为所有具有两个优先级的运算符列了一份清单。其中一个是位于其他运算符前面的倾向。例如,+运算符会让*运算符先运算。但我还需要一张表来 处理类似带括号的运算,防止类似的运算被误操作。我不知道前进的道路是否正确,但运行结果正确,正是按我想的那样运行的。这些技巧并不一定要从书上才能学 到。
在 Homebrew 电脑俱乐部里向大家展示我的 BASIC 让我觉得很享受。从来没在什么书上看到过印着我的名字,因此我的名气也没能和比尔·盖茨比肩,但在俱乐部里我还是很有名的。这些都是在乔布斯看到我的电脑 研发出来之前发生的事。随着时间流过,我要做的仅仅是逐个逐个地将每个编好号的运算符操作写成代码。每次俱乐部会议上我都会完成几个命令。
在 Apple II 上我让视频和电脑内存合为一体,这样本来每秒可以交换大概 100 万(夸张了)个数字的微处理器就可以每秒交换大概 100 万屏的字节了。Atari 街机游戏机是用硬件实现的,但现在利用 6502 机器语言编程游戏可以作为软件实现了。BASIC 是一种解释性语言。BASIC 一边检查每条语句的每个字母一边执行,决定要做什么。因此,它要比机器语言慢上 100 或者 1000 倍。然后有一天我突然好奇,是否可以用 BASIC 编个程序,可以像动画一样移动物体。
我之前已经在硬件上实现了 Atari 游戏打砖块。那我是否可以用 BASIC 来实现这个简单的街机游戏呢?我知道可以用机器语言来实现这个游戏。因为这是我自己的 BASIC,于是我就到语法图中加了一些命令,用来划分颜色以及绘画垂直线和水平线。然后我在芯片手册里选了一个带有四个计时器(555 风格的计时器)的芯片。利用软件读取电位器上挡球板的位置以及移动的幅度。我把这些东西安装好以后(还要为 BASIC 烧录新的 EPROMS),就坐下来写了一些简单的 for 循环语句把砖块染成不同的颜色。几分钟里我大概试了 30 种颜色组合。然后我又加上了挡球板、得分和一个球。通过调整程序参数来改变球的速度和角度。另外,我想是时候增加一个1-bit 音频设备的扬声器,因为像球撞到砖块这样的事件发生时会需要一个音效。
我打电话让乔布斯到我那里看看我的成果。我向他展示了我可以就像改变砖块颜色一样简单迅速地做出其它修改。最重要的是,在一个半小时里,我尝试 的改动要比硬件版本的游戏中花上 10 年可以做出的改动还要多。乔布斯和我都意识到很重要的一点,那就是现在动态游戏(街机风格的)可以用软件来实现了。更重要的是,用 BASIC 实现的话意味着任何年纪的任何人都可以通过编程来实现它。
我在 BASIC 设计中所有的努力都记录在了文件里,这些文件按年份排列在了 50 个文件夹里。每个文件夹的标签都是“GAME BASIC”现在你们知道我的才智是如何来的了吧。
更新
附记:高中还是大一时,我跟爸爸说有天我要拥有一个 4K 版的 Data General NOVA. 他说这抵得上一座豪宅的首付款了。我被惊到了,告诉他说我会住在公寓里。
为什么是 4KB?
因为这是运行更高级语言所需要的最小要求。对我来说,电脑不仅仅只有开关和灯。它必须能够运行程序。
在 Apple I 之前我就做了台只有开关和灯的电脑。那时没办法负担得起 4KB 的内存,所以只能 256 字节的。
在 Homebrew 俱乐部的那些日子里,也就是 1975 年的夏天,有 3 家公司引进了 4KB 的 DRAM 的电脑。那是 4KB 内存第一次真正地出现。为了让 BASIC 成为电脑的一部分,我必须要有 4KB 内存。别无选择。从而苹果一代和苹果二代的最小内存就是 4KB。假如我不在意 BASIC 的话,我也许就只是造了另外一种只有开关和灯的电脑,只有最小的静态内存,但也就仅此而已了。
编者按:如果你想了解更多斯蒂夫·沃兹尼亚克的生活,可以看看他的传记 《iWoz 沃兹传:与苹果一起疯狂》。—JD