彭民德:《電子計算60年》 (25)可愛又可恨的BASICA

彭民德發表於2016-09-28

BASIC是繼FORTRAN 、ALGOL 60後,1964年推出的第三個高階程式設計語言,這種語言一部分基於FORTRAN,一部分基於ALGOL,並且增加了一些東西使之適合於分時系統。BASIC以簡單易用和解釋執行為特點,在計算機初學者中廣為流行。PC時代,在配置PC-DOS作業系統之前,只有ROM BASIC,一開機就進入BASIC環境。後來微軟公司寫了一套以磁碟為基礎的PC-DOS,並配了BASICA(Advanced BASIC的縮寫)。BASICA依然是一種解釋型BASIC。大約在一年左右,我們又得到其升級版本QBASIC和GWBASIC,執行於主頻4.77MHz的 CPU,1MB記憶體,10MB硬碟,配有鍵盤和印表機,CCDOS中文作業系統的軟硬體環境的機器上,這是我們承接開發流速儀實時檢定系統時,所能夠採用的最好的程式設計環境。

啟動BASICA後,螢幕上方就出現一個閃爍的游標提示符,表示可以從鍵盤上輸入語句。在螢幕最下面一行有“1list”、“2run”、“3load”、“4save”等操作提示資訊,指出可以用功能鍵F1將程式顯示於螢幕上,用F2執行程式,F3裝入某個源程式檔案,F4儲存現有程式到檔案中。想寫什麼語句就寫什麼,想執行哪一段程式,甚至哪一句都可以。不用編譯,啟動執行後隨時報告結果和錯誤資訊,簡單易用。

BASICA程式語句功能也不弱,凡是以往在第二代和第三代機上ALGOL和FORTRAN所有的資料型別和基本語言成分它都有。BASICA還強化了字串操作和檔案操作,特別是利用PC環境,新增了影像和語音功能。可以在螢幕上打點、畫線、著色。可以利用beep和sound語句讓內建喇叭發聲。我們在螢幕上畫一架小車以模擬流速儀檢定車,用GET語句存入一個陣列,通過PUT語句把小車顯示到螢幕上。再清屏,到下一個適當位置PUT顯示小車陣列,便畫出了帶彩色的小車動畫。又從當時的報刊上引用了別人介紹的歌曲程式。便開發出一架帶彩色並唱歌行進的檢定車動畫,與檢定車同步地在螢幕上跑動。使用者和開發方都很快喜歡上了BASICA。

BASICA還有一些特殊功能。比如“on key(n) gosub 行號”可以重新定義功能鍵Fn的功能,這實際上是優先處理鍵盤中斷的功能。利用這一特性,我們可以寫語句“on key(1) gosub 500”,使得操作者只要按下功能鍵F1,便轉向程式行500,啟動流速儀開車檢定程式。“on key(3) gosub 3000”,使得用功能鍵F3,馬上實現干預停車功能。又比如上面講到的BASIC與組合語言混合語言程式設計的擬中斷程式設計的實現,需要在程式中讀寫特定的記憶體區,BASICA的“def seg=某個記憶體地址”與“poke USR”直接記憶體讀寫特性,幫助我們容易做到這一點。

關於IBM上的BASICA的語法,IBM釋出的資料有詳細介紹。但是隨著程式尺寸增大到上千行左右,開發難度也急劇增大,程式中每增加一項功能,都有“戰戰兢兢,如履薄冰”之險。問題出在討嫌的行號和不得已而大量使用GOTO轉向語句。這是當時介紹BASIC的資料不會明確告訴你的。

每一行的程式碼前面都有一個整數數字作為“行號”。行號是程式順序執行的依據。整個程式沒有辦法像後來其它語言那樣,使用縮排書寫以便區分割槽段,每一行都是齊頭並列的,因此是一種非結構化的“麵條式程式碼”。行號也是GOTO轉向的標號,隨著程式邏輯的增加,GOTO語句必將大大增加。行與行之間預設行號距離為10,當需要在兩個相鄰行間插入10個以上語句時,必須將行號重新命名。GOTO要轉去的語句標號也將隨之改變。因此每往前走一步,都只能得到一份全新的,跟上一個版本形式上無關的程式,連程式註釋都得相應修改。特別是難以掌控隨之增加的大量GOTO。

圖靈獎獲得者荷蘭計算機專家Dijkstra第一個提出GOTO有害論。允許用但是提倡少用和不用的GOTO語句,使程式結構不清晰的GOTO語句,受盡責罵的GOTO語句,讓我從1989年起,不得不跟它打交道5個年頭,有太多的無奈。

水文流速儀實時檢定系統中,主要的一個實時檢測程式,用解釋型BASIC編寫的源程式有1304行,按照BASIC程式的預設編號,從行號10開始,以10為間距,到13040行結束。除去部分純註釋行,執行語句大約1200行左右。其中竟然有多達80個GOTO語句,停車後做資料處理的900多行的程式也有39個GOTO,總共有100多處。這樣寫程式肯定不好。用BASICA做實時控制,反映計算機從機房到桌面時候一段短暫的歷史吧。 enter image description here

程式的流程控制只有GOTO一種,必要時用GOTO語句控制程式轉向。沒有while、for等其它控制結構,也沒有分程式概念,程式無法分塊。所有變數都是全程的。子程式無法帶入口引數和返回引數,因而劃分子程式也不容易。我們雖然早幾年就已熟悉了C語言,但那時C語言只能執行在較高檔的UNIX機器上,在IBM PC上還不能用,在這裡只有BASIC可用。又考慮到此課題的甲方希望他們水文方面的技術人員能夠參加到程式設計中來,BASIC最簡單,便於他們參加和以後維護。

程式中為何要那麼多GOTO語句呢?基本原因是程式的順序性和要解決問題複雜性之間的矛盾。程式總是順序執行的,順序執行無法解決複雜問題。複雜性體現在幾個方面。首先要提供檢測人員一組控制命令,比如輸入初始狀態引數,開車,干預停車,檢測行車速度,檢測被檢流速儀引數等,每次只能執行其中一種,在麵條式程式格式下,只得按照使用者的不同輸入使用GOTO。其次要維繫IBM PC與負責控制行車的微控制器以及另外3個分別負責某臺流速儀引數檢測的微控制器之間的通訊聯絡。這種聯絡靠一根銅線,實施半雙工通訊,即一邊發另一邊收,待一次發收過程完成後,轉化成另一邊發,這邊收。這種收與發及轉化過程一直維繫到本次按某個檢測條件檢測完成。要不斷地按照通訊協議,收發信件,並對收發信件的可靠性進行校驗。必要時一封信要重發3次。組織信件、收、發、校驗、重發等模組,都必須按一定條件轉去執行。第三,既然是實時控制,實時系統的事件是隨機的,為了保證操作的實時性、系統的堅定性、資料的可靠性,程式中要用不同的轉向,以保證對所有事件都能得到及時處理。第四,部標規定被檢測的流速儀有7種型號,需要7個程式段,至少要7條GOTO語句轉向公共處理部分。

BASICA中GOTO語句有3種格式。一種是強行轉,格式“GOTO 行號”,強制轉向指定的語句行。第二種是條件轉,格式“IF 條件表示式 THEN GOTO 行號”,表示式成立就轉向指定的語句行。第三種是多路開關轉,格式“ON 數字表示式 GOTO 行號1,行號2,…”,將根據表示式的值為1,2,…,分別轉向行號1,行號2等處。

值得慶幸的是,我們還是成功了。系統能夠正確運轉,每次檢測3臺流速儀,及時對所檢流速儀按照國家標準給出定量判斷,該儀器可以繼續使用,還是需要修理,或者該報廢了。省科委組織的專家鑑定,給予填補國家技術空白的領先水平的評價,獲得了省級科技進步獎。

今天回頭去看,把初期的PC機用於開發工業過程實時控制系統,有點勉為其難。當時的開發環境,雖然用了高階語言,比早期只能用機器語言或組合語言,有了進步。有了微機,除錯可以實時地在現場進行,發現和解決問題都很及時。但是跟後來的開發環境比,實在太差了。所有變數都是全程的,程式語句只能以行號表示,無法給程式塊命名,是編制程式很忌諱的。要在某兩條語句之間插入若干條語句就很不方便,它涉及原有語句行號的改動,而行號的改動意味著語句命名的改動, GOTO所在行以及轉去的目的行都變了,整個程式就變成一個“新程式”了。每增加一條GOTO語句,都會增加程式閱讀和掌控的難度。我們要多次面對有100多條GOTO語句,使得程式結構變成了一團亂麻的新程式。對這個上千行的BASICA程式掌控的複雜性,已經大大超過也有近千行的收發資訊和與微控制器通訊用的組合語言程式。開始沒有把問題估計得那麼複雜,哪想到由於種種原因,實際專案常常有料想不到的困難,要拖很久。課題中途又不忍心放棄已做的程式框架,遇到問題總想稍事修補把當前問題解決掉就算了,沒有下決心轉用其它結構化程式語言(課題中途已經有了C語言等可用),這一點讓我留下遺憾和深刻的教訓。想到這裡,對於當時的苦頭還有些後怕。由此也聯想到許多同仁在做電子計算的種種開發運用中,都會經歷多少別人所不知道的艱辛。

(本文內容也可參看 彭民德《電子計算60年》第5章 電子工業出版社)

相關文章