彭民德:《電子計算60年》(12)ALGOL 60與程式自動化

彭民德發表於2016-07-05

用機器指令和用匯編指令程式設計,都只是在計算機內部硬體之間打轉轉,比如一條指令取記憶體A單元的內容,再取記憶體B單元的內容,在運算器裡做一個加法,再把結果送到A單元,同時留在暫存器裡。指令並不知道相加的是什麼,你得心裡有數,自己要隨時記得各個記憶體單元當前存了什麼,是數還是一條指令,是數的話,當前的值是多少。也得記住暫存器的當前值,因為很可能後續指令要用到它,影響執行結果。同時每條機器指令和彙編指令功能單一,難以表達人們的計算意圖。用機器指令程式設計也很枯燥,很容易出錯,令人望而生畏。

50年代首先在IBM公司機器上推出FORTRAN,這是世界上第一個高階語言。而後1960年歐洲人發明了ALGOL 60。這兩種語言到70年代中期才引進到我國,我們首先用的是ALGOL 60。後來在DJS-6上也引進了FORTRAN。我們研究所引進121機的ALGOL 60編譯系統與ALGOL 60標準基本一致,具有較完善的語法檢查功能,對於迴圈模組進行了一定的優化處理,目標程式執行速度有較大提高,在對源程式閱讀、修改和編譯操作方面也比較方便。

所裡及時地於1976年七、八月份在全所範圍內舉辦121機的ALGOL 60(簡稱ALGOL 121)培訓班。參與者非常踴躍,搞總體設計的,自動控制系統設計的,空氣動力學的,結構設計的等專業的技術人員紛紛參加。

在ALGOL 60中可以說明變數,一個變數對應一個數學量,跟人們的數學習慣相吻合。程式中使用變數名,避免了直接與記憶體單元和暫存器打交道的枯燥易錯。編譯程式會自動為每個變數名分配記憶體單元。資料的表示無須用八進位制、十六進位制,直接用習慣的十進位制就行了。程式中出現的常數也不用程式設計人員分配記憶體單元和傳輸賦值了。源程式遠離了機器硬體,比較接近數學公式了。而其程式結構呢,正如標準化組織ISO在1972年釋出的ALGOL 60標準關於語言結構所說:
“演算法語言的目的是描述計算過程。描述計算規
則時用到的基本概念是眾所周知的算術表示式,
從這些表示式出發,運用算術運算的規則,組成
語言中自封閉的單位,叫賦值語句”。

算術表示式和賦值語句很接近數學公式。例如,前面用機器指令程式設計計算f = ((x2 + y2 –z2) sin x)/( x2 + y2),當時那麼費勁,而現在只要說明變數f,x,y,z的資料型別,對x,y,z賦初值,用一條帶算術表示式的賦值語句
f := ((x*x+y*y+z*z) * sin (x))/( x*x + y*y);
就解決了問題。

可以給語句加上標號。結合利用轉向語句,可以構成選擇、迴圈與迭代。ALGOL 60引進了語句括號BEGIN 和END,因而有了複合語句和分程式結構,並可藉以定義過程(procedure)。有了資料定義、變數、表示式、賦值語句,有了豐富的程式結構,加上程式設計師對於計算機演算法的理解,任何計算問題都可以對付了。

ALGOL中說明的過程是一個命名的程式塊,規定了入口引數的個數和型別,規定了返回引數的個數和型別。只要給予型別和個數相符的實際呼叫引數,在程式中任何地方都可以呼叫,獲得經該過程執行所得到的結果。如果返回值是數值,過程就被當做函式。ALGOL 121提供了ABS、SIGN、SIN、COS等24條標準函式。提供了36個標準過程與輔助過程。“標準”的意思是指系統預置的,無需程式中另行說明,程式中就可以直接呼叫。許多標準過程功能簡單,比如求某個數的絕對值或者某個角度的正弦函式值,但是畢竟可以直接引用,不再需要自己寫那段程式了。還有些功能很強的標準過程,比如
GS1(A,B,X,EPS)
用高斯-賽得爾迭代法求解形如X=AX+B的線性代數方程組,其中A是二維實陣列,B,X為實向量,EPS為實型賦值引數,用以指明迭代所要達到的精確度。只要實際給定了A、B和EPS,並把初值置於X中,呼叫執行該標準過程後,在X中的最終結果就是方程組的解。

除了提供一批標準子程式外,ALGOL提供程式設計師編寫自己的過程和函式的機制,只要依據其文字規範,按照其procedure的格式要求,正確說明變數,正確運用其語句結構,程式設計師可以自己定義和引用過程。這就給程式的編制提供了很大的靈活性,大大提高了程式的編寫效率。

ALGOL 121的編譯程式由一個80行的載入程式載入到記憶體。它以3次掃描方式工作,並分別報告所檢查到的錯誤。在程式沒有語法錯誤情況下,生成可執行的目標碼。

實踐證明,ALGOL 60是一款很好的程式導向的程式語言,可以編寫簡短高效的程式,深受工程技術人員歡迎。我掌握了它,以後學用FORTRAN、PASCAL、C等其它第二、第三高階語言都很容易,只著重關心那些與ALGOL不同之處就行了。

121機的ALGOL 60與標準ALGOL 60文字還有一些不同,主要是受機器外設條件限制,有些地方必須變通。比如,標準本身允許英文字母大小寫均可,而我國121機的打字機只有大寫,故源程式中,也只能用大寫英文字母。如果這樣的限制拿到英語國家去,那人家一定不會接受。又比如,語言中的BEGIN、END、INTEGER、FOR等幾十個關鍵字或保留字,“為了不與變數名字相混,一律用一對尖括號‘▼’括起來”,在它們該出現的地方都是▼BEGIN▼、▼END▼,用起來要繁瑣一些。

當然ALGOL的資料型別中沒有字元型,沒有檔案概念,這兩點是在隨後學習FORTRAN語言才有的。

還有一點,也受機器條件限制,當時我們還沒有鍵盤作為輸入,源程式必須穿孔,而且當時還只有5單位孔的紙帶。用5Z-3型電傳打字機輸入,再輸出5單位穿孔紙帶,憑紙帶輸入機再把源程式輸給計算機。5單位機用起來也不方便,紙帶上5個孔位只有32種不同的碼子,無法承載字母和所有符號。要靠先按下字母鍵,隨後輸入的是英文字母;靠按下符號鍵後表示隨後輸入的是字母以外的符號,包括+、―、*、/、小數點,大於、小於等數學符號,還有尖括號▼等特殊符號。

穿孔紙帶上的當前位置用5個孔位的編碼表示一個數字或字母。比如00001代表數字5,也表示字母T,如果輸入時先按下鍵盤上的命名為“符號健”的健,再輸5,紙帶上這個00001就代表數字5;輸入時先按下鍵盤上的命名為“字母健”的健,再輸T,紙帶上這個00001就代表字母T。編碼被打孔記錄在紙帶上。1有孔,0不打。每打一排符號,紙帶卷就轉動一格,到下一個數字字母位置。紙帶格式有如圖所示的嚴格要求。

enter image description here

其中,每個空白段要1米以上。輸入Y(意即源程式開始)和S(意即資料部分開始)分別表示程式部分和資料部分的開頭。在源程式和資料輸入完畢時要後跟5個以上的“字母健”,以作為某個區域的結束。要小心謹慎,萬一有錯,用筆記下來,集中以GY(意即改源)打頭重新輸入改正後的源程式行,以GS(意即改數)打頭重新輸入改正後的某些資料。可以有多次GY、GS修改。後頭的“J(意即結束)”表示整個程式輸入完畢,最後要2米以上的空白。實際上錯誤經常發生,不該打孔的地方要把已經打了的孔貼掉,應該是1的而沒有孔的地方要手工補一個孔。每人手裡常常是一些多處手工修補的紙帶。而為了節省,先只能用成本低一些的白紙帶,待改好後,再複製到黑紙帶上,黑紙帶才是光電輸入機能夠識別的。

穿孔得到一條正確的程式紙帶後就可以申請安排上機了。

我國DJS系列計算機後來發展到上海計算機廠生產的DJS 130,依然是早期的用機環境。雖然此時穿孔紙帶機已經由以往的5單位改進為8單位,增加了校正位,可以支援對數字和英文字母以及其它更多符號的編碼和識別。但是上機環境沒有本質的提高。可以說第二代機實現高階語言程式設計的飛躍後,源程式還要穿孔和缺少作業系統,人們不得不無助地綁在控制檯前,直接對硬體進行手工操作,是它無法逾越的技術屏障。換句話說,只能在面向硬體環境下,支援高階語言程式設計,是第二代機的技術頂峰。我國這個時期一直延續到了上個世紀80年代初期。下面所附一段8單位穿孔紙帶照片,就是80年代初筆者在長沙鐵道學院,師生們依然使用DJS 130時留下的。
enter image description here

有80行印表機,可以印出帶行號的源程式。所附照片是ALGOL 121的一段源程式,從其關鍵字帶尖括號就能看出不是標準的ALGOL,的確是ALGOL 121的一段源程式。

enter image description here

高階語言的出現,在程式設計史上有著革命性的意義。當時的人認為高階語言的出現,就進入程式自動化時期了,1976年西北大學數學系計算站編寫的如何使用121機ALGOL 60的講義就用《程式自動化講義》為書名,這在今天看來顯得誇張。我們研究所在1976年7月以手刻鋼板的形式把這份講義和《ALGOL 121使用手冊》轉發給大家學習。

enter image description here

根據什麼講ALGOL 60就是程式自動化了呢?書上是這樣寫的:
“程式設計是一件繁瑣而細緻的工作。它所使
用的指令程式碼與算式完全是兩碼事,一個簡單
的算術公式往往需要很多步驟才能完成。由於
機器不同,指令系統也不同,若把一個題目換
成另外一臺機器,還得熟悉所換機器的指令系
統”。而“演算法語言接近數學描述,用演算法語
言程式設計序大大減少了程式設計時間和錯誤,而且它
適用於各種型別機器,便於程式交流”。“當
輸入用高階語言寫的源程式後,事先存放在機
器裡的編譯程式,將自動地加工分析,隨之把
它轉換成由機器指令組成的目的程式。然後機
器執行目的程式,最後得出計算結果。這一過
程把大量工作交給機器去做,在這個意義上,
是由機器編制程式,即程式自動化”。

原來程式的自動化不是指編寫源程式的自動化,只是編譯程式將源程式生成目標碼的自動化。不過由此足以看出,編譯程式的出現,對於原先不得不用機器語言程式設計的人們來說,是多麼有意義的生產力解放。高階語言的意義還在於,它把更多的工程技術人員吸引到計算機旁。計算機雖然還在深閨中,但是可以成為幫助工程設計的好助手了。

在我國推動程式設計轉向高階語言程式設計,這一重大跨越的功臣,有北大的王選院士(國家最高科學技術獎獲得者)和中科院數學所陸汝鈴院士(中國計算機學會終生成就獎獲得者)等人。“DJS 21機由北京大學配上ALGOL” (郭平欣:《中國計算機工業概覽》P158電子工業出版社 1985.5)。ALGOL 60編譯程式具體由北京大學王選院士等人開發,貴州凱里830廠配的編譯程式是王選院士編寫的。這麼複雜的一個程式,當時只能全部用 DJS 21計算機的機器指令寫成。王選院士等人開發的編譯程式大概有 12000條左右的指令,其編寫除錯難度令人難以想象。830廠DJS 21程式自動化組,曾經著文“DJS 21機編譯系統”在《數學的實踐與認識》雜誌1973年第4期上介紹當時的“編譯程式和執行系統共約2×6000條指令”。

陸汝鈴院士最初作為使用者單位在該廠接受使用 ALGOL 60語言的培訓,回到單位後,負責數學所該編譯程式的維護。由於該編譯程式還沒有經過長期使用的考驗,在使用過程中,也陸續暴露了一些問題,使用者根據ALGOL 60語法寫的程式有時編譯通不過,或執行不正確。陸院士在查詢問題和修改編譯程式的實踐中,進一步提高了對ALGOL 60 編譯程式和ALGOL 60語言本身的理解。對原編譯程式進行了修改和擴充。經陸汝鈴院士的修改和擴充,最後該編譯程式的指令數達到了16000條左右。陸院士的工作,使DJS 21機的ALGOL 60編譯程式基本成熟,能夠可靠地使用。後來830廠在銷售 DJS 21機的時候,不再提供ALGOL 60 編譯程式,而是讓客戶單位到數學所去索取。數學所也很樂意提供編譯程式的穿孔紙帶。筆者所在研究所,DJS 21機的ALGOL 60 編譯程式“用機器語言寫成,約為16000條指令” (西北大學數學系計算站編,第三機械工業部612所翻印:《121機程式自動化講義》P6,1976年7月),就是經過陸院士改寫完善後的版本了。

今天回顧這段歷史,讓人十分感慨,特別是作為直接使用過ALGOL 60 編譯程式的受益者,我們要對王選院士、陸汝鈴院士等先行開拓者們,由衷地說一聲謝謝。

上個世紀七十年代,四機部曾經先後向阿爾巴尼亞和巴基斯坦提供DJS 21計算機,隨機配備的都是陸院士的ALGOL 60 編譯程式紙帶。

繼ALGOL之後,以DJS 6為代表的一些國產機器上又引進了FORTRAN 4,使得這個階段的計算機本領又有所增強。在我國大規模推廣FORTRAN是70年代末通過CCTV的電視大學課程進行的。

FORTRAN源程式最初使用卡片作為載體,每一行用一張卡片。鑑於一張卡片上放兩條語句不便處理,故嚴格地限制,每個語句行只能寫一條語句,不能寫兩條或更多語句。但是一個FORTRAN語句可以佔多行,一行寫不完的語句,只要在專門的位置用續行標記,也可以佔兩行或多行。在一個FORTRAN語句裡可以帶下一個格式語句的行標號,這樣來指明某些變數的輸出格式,用單獨的格式行可以豐富對輸出格式的描述。每一行不能寫多個語句,是一種比較呆板的語言。這與其它自由格式語言不同,ALGOL和以後的PASCAL、C語言都允許一行中有多個語句。

(與本文相關的更多內容,可參看彭民德《電子計算60年》第3章 二代計算硬體獨唱 電子工業出版社)

相關文章