1. 程式人生 > >編碼的奧祕:高階語言和低階語言

編碼的奧祕:高階語言和低階語言

轉自:《編碼的奧祕》    第二十四章

 

 

          用機器碼程式設計就像用牙籤吃東西,刺的塊很小且做起來很費力,吃一頓飯要花很長時間。同樣,每個機器碼位元組只是完成可以想像得到的最小且最簡單的計算工作—從記憶體裝入一個數至處理器,與把它另一個數相加,再把結果存回到記憶體—所以,很難想像機器碼如何完成一整項的工作。

          至此,我們至少已從第 2 2章開始處的原始模型階段有了一些進步,從前我們一直用控制面板上的開關輸入二進位制資料到記憶體。在第 2 2章裡,介紹瞭如何寫簡單的程式用鍵盤輸入並在視訊顯示器上檢查機器碼的十六進位制位元組碼。這當然不錯,但還不是改進的終點。

          正如我們所知道的,機器碼位元組與某些短的助記符相關聯,如 M O V、 A D D、 C A L L和H LT,因此,可以用一些模糊類似的英語來引用機器碼。這些助記符通常與運算元寫在一起,進一步表明機器碼指令的功能。例如: 8 0 8 0機器碼位元組 4 6 h使得微處理器把暫存器對 H L中的1 6位數定址的記憶體單元所存放的內容傳送到暫存器 B。這可以很簡明地寫成:

          當然,用匯編語言編寫程式比用機器碼要容易得多,但微處理器並不能理解組合語言。我們已經講過如何在紙上編寫彙編程式,只有當想在微處理器上執行組合語言程式的時候,才會手工彙編程式,意思是把組合語言語句轉換成機器碼位元組並輸入到記憶體。

          如果能讓計算機來做這項轉換工作就更好了。如果你正在 8 0 8 0計算機上執行 C P / M作業系統,則你已經具有了所需要的工具。下面介紹它是如何工作的。

          首先,建立一個文字檔案,包含有你用匯編語言編寫的程式。可以用 C P / M程式 E D . C O M來完成這項工作。該程式是一個文字編輯器,可用來建立、修改文字檔案。現假設建立的文字檔名稱為 P R O G R A M 1 . A S M。 A S M檔案型別表明該檔案是組合語言程式檔案,該檔案看起來就像下面這樣:

 

檔案中有幾個語句以前沒有見過。第一個是 O R G( o r i g i n)語句,該語句不對應於任何一條8 0 8 0指令,它表示下一條語句的地址從地址 0 1 0 0 h處開始。前面講過,這就是 C P / M程式裝入到記憶體的地址。

          下一個語句是 L X I( load extended immediate)指令,它裝入一個16位數到暫存器對 D E。本例中, 16位數由標號 Te x t給出。標號在程式的下部, D B( Data Byte)語句之前。 D B也是以前未見到的, D B語句後面可以是幾個逗號隔開的位元組或(就像本例中)在單引號裡的一些字元。

          M V I( move immediate)語句把數 9送到暫存器 C。 CALL 5 語句進行 C P / M功能呼叫。功能9的意思是:顯示一個字串,起始地址由暫存器對 D E給出,遇到美元符號結束。 (注意,文字以美元符號作為字串的結束是很奇怪的,但 C P / M就採用這種方法。 )最後的 R E T語句用來結束程式並把控制權返還給 C P / M(這實際上是結束 C P / M程式的幾種方法之一)。 E N D語句表示組合語言檔案結束。

          即然已經有了 7行文字的文字檔案,下一步是彙編該檔案,即把它轉換成機器碼。以前是用手工來完成,自從執行 C P / M後,可以用包含在 C P / M中的名為 A S M . C O M的程式來完成。這個程式是 C P / M彙編程式,在 C P / M命令列執行 A S M . C O M,方法為:

         A S M程式彙編 P R O G R A M 1 . A S M檔案並建立新的檔案,名為 P R O G R A M 1 . C O M,它含有與編寫的組合語言程式相對應的機器碼(實際上,在這個過程中還有另外一步,但在這裡並不重要)。現在,在 C P / M命令列就可以執行 P R O G R A M 1 . C O M,結果顯示字元“ H e l l o ! ”,然後結束。

         P R O G R A M 1 . C O M檔案包含有下面 1 6個位元組:

 

前面 3 個位元組是 L X I指令,緊接著 2個位元組是 M V I指令,再後面 3 個位元組是 C A L L指令,然後是R E T指令,最後 7個位元組是“ H e l l o”、感嘆號和美元符號的 A S C I I碼。

         像A S M . C O M這樣的彙編程式所做的工作是: 讀入一個組合語言程式(常稱作 原始碼檔案 ),產生一個包含有機器碼的檔案— 可執行檔案。從大的方面來看,彙編程式是相當簡單的程式,因為在組合語言助記符與機器碼之間存在一一對應的關係。彙編程式把每一個文字行分成助記符和引數,然後把這些單詞和字元與一張表相對照,該表中存有所有可能的助記符和引數。通過這種對照就可以找到每個語句所對應的機器碼指令。

          注意彙編程式是如何得出 L X I指令必須把暫存器對 D E設定為地址 0 1 0 9 h的。如果 L X I指令本身在 0 1 0 0 h處( C P / M把程式裝入記憶體執行時的地址),則 0 1 0 9 h是就Te x t字串的開始地址。通常,使用匯程式設計序的程式設計師並不需要關心程式各部分的地址。

           當然,第一個編寫彙編程式的人必須手工彙編程式。在同一臺計算機上編寫新的(或改進)彙編程式的人可以用匯編語言程式設計然後用最初的彙編程式來彙編。一旦新的彙編程式經過了彙編,它也可用來彙編自身。

           每當一個新的微處理器誕生,就需要新的彙編程式。新的彙編程式可以在已有的計算機上編寫,利用原有的彙編程式來彙編。這種彙編稱之為交叉彙編 ,即用在計算機 A上的彙編程式來生成在計算機 B上執行的程式碼。

           儘管彙編程式消除了組合語言程式設計缺少創造性這一問題(手工彙編部分),但組合語言還存在兩個主要問題,第一個(也許你已經猜測到了)是組合語言程式冗長、乏味。因為你是在微處理器晶片級程式設計,所以必須要考慮每一個細節。

          第二個問題是組合語言不可移植。如果為 Initel 8080 編寫組合語言程式,則不適用於在M o t o r o l a的 6 8 0 0上執行,必須用 6 8 0 0的組合語言重新程式設計。也許,這不像編寫最初的組合語言程式那麼困難,因為已經解決了主要的組織和演算法問題,但是,仍然有許多工作要做。

          上一章解釋了現代微處理器晶片如何整合機器碼指令來進行浮點運算,這當然已經很方便了,但還不是十分令人滿意。一種選擇是徹底放棄與處理器相關的實現每個基本算術操作的機器碼,取而代之的是用代數符號來表示許多數學運算。以下是一個例子:

這裡A、 B和C是數字, PI = 3 . 1 4 1 5 9。

          既然如此,何樂而不為呢?如果這樣的一條語句是在一個文字檔案裡,則可以編寫組合語言程式讀取文字檔案並把代數表示式轉換成機器程式碼。

          如果只計算一次這樣的代數表示式,則可以手算或用計算器計算。如果需要用不同的 A、B、 C值來計算表示式的值,則可能需要考慮如何用計算機來計算。正因為如此,代數表示式不可能單獨出現,應該考慮到表示式的上下文,用不同的值代入計算。

         現在已開始建立所謂的高階程式設計語言。組合語言稱作低階語言,因為它與計算機硬體密切相關。儘管“高階”用來描述除組合語言以外的任何程式設計語言,但這些語言中,一些語言還比另一些語言更要高階一些。如果你是一家公司的總裁,且坐在計算機前輸入“計算全年的收益和支出,做出年度報表,列印兩千份給所有的股東”,那麼你確實正在用非常高階的語言工作。在現實生活中,程式設計語言並沒有達到這樣理想的境界。

         人類語言是千百年來複雜的影響、隨機變化和不斷適應的結果,即使像世界語這樣的人工語言也來源於現實語言。然而,高階計算機語言是審慎而周密的概念語言。發明程式設計語言面臨的挑戰是如何使語言具有吸引力,因為語言定義了人們如何向計算機發送指令。從2 0世紀5 0年代開始到 1 9 9 3年,估計已發明和實現了 1 0 0 0多種高階語言。

         當然,這還並不足以簡單地定義高階語言(它牽涉到語言所採用的語法),還必須有編譯程式用來將高階語言語句轉換成機器碼。像彙編程式一樣,編譯程式需要一個字元接一個字元地讀取原始碼檔案,並分解成短語、符號和數字,但編譯程式比彙編程式更復雜。從某種意義上講,彙編程式較簡單,因為在組合語言語句與機器碼之間有一一對應的關係。編譯程式通常需要把一條高階語言語句轉換成許多機器碼指令。編譯程式不容易編寫,許多書中描述了它們的設計與構造,所以本書不作介紹了。

         高階語言有優點也有缺點。最主要的優點是高階語言比組合語言容易學且容易編寫。用高階語言編寫的程式清晰、簡明。高階語言通常是可移植的—也就是說,它不像組合語言那樣依賴於特定的處理器。所以,程式設計員不需要知道程式將要執行其上的機器的內部結構。當然,如果需要讓程式在不止一種處理器上執行,則需要相應的編譯程式生成針對這些處理器的機器碼。可執行檔案仍然只適用於某一個處理器。

         另一方面,差不多都是如此,一個好的組合語言程式設計員可以寫出比編譯程式所能產生的更優化的程式碼。也就是說,用高階語言編寫的程式所產生的可執行檔案比用匯編語言編寫功能相同的程式所產生的可執行檔案要大,且執行速度較慢。 (最近幾年,隨著微處理器的日趨複雜以及編譯程式在優化程式碼方面的日趨成熟,這種差別已變得不很明顯。 )

         還有,儘管高階語言使得處理器更容易使用,但並沒有使它的功能更強大。而使用匯編語言可以最大限度地利用處理器的能力。因為高階語言需要轉換成機器碼,所以高階語言只會降低處理器的能力。如果一個高階語言是真正可移植的,則它不能使用某種處理器的獨有特點。

          例如,許多處理器都有移位指令。前面講過,這些指令把累加器中的位向左或向右移動。但是,幾乎沒有高階語言有這樣的操作。如果程式中要用到移位,則需要用乘 2或除 2操作來處理(其實,現在許多編譯程式都用處理器的移位指令來實現乘或除以 2的冪) 。許多高階語言同樣也不包括按位的邏輯運算。

           早先的家用計算機中,許多應用程式是用匯編語言編寫的,而現在除非有特殊需要,組合語言已經很少用到。由於已在處理器中添加了一些硬體來實現流水線技術—同時有多個指令碼累進執行— 組合語言則變得更難以掌握。與此同時,編譯程式卻逐步走向成熟。現代計算機的大容量儲存能力也在這種趨勢—程式設計員不再滿足於編制在小的記憶體和磁碟上執行的程式碼—中也扮演著重要角色。

            儘管許多早期計算機的設計者都試圖用代數符號來闡明他們的觀點,但通常認為第一個真正成功的編譯程式是由 Grace Murray Hopper( 1 9 0 6- 1 9 9 2)於1 9 5 2年在雷明頓為 U N I VA C而設計的 A - 0。當 H o p p e r博士 1 9 4 4年為Howard Aiken 工作時,就已開始了計算機的早期研究工作。在她 8 0多歲時,仍然活躍在計算機界,為 D E C公司作一些公關工作。

            今天仍然在使用的最古老的高階語言(儘管這些年中得到了廣泛的修改)是 F O RT R A N。許多計算機語言的名字都是大寫字母,因為它們是由許多單詞的首字母構成的。 F O RT R A N是由 FORmula 前3 個字母和 T R A N s l a t i o n的前 4個字母混合而成,是在 2 0世紀 5 0年代中期由 I B M公司為 7 0 4系列計算機開發的。多年來, F O RT R A N一直被選作為科學和工程的計算語言,它廣泛支援浮點運算甚至支援複數運算。

             所有計算機語言都有它們的支持者和批評者,並且人們可能只熱衷於他們所喜好的語言。儘量站在中立的立場上,我選擇一種語言作為原型來解釋那些差不多再沒有人用的程式設計概念。這種語言的名字是 A L G O L(即 ALGOrithmic Language)。 A L G O L也可用來探索高階程式設計語言的本質,因為從某種意義上來說它正如一粒種子,成為過去 4 0年來許多流行的通用語言的直接祖先。甚至在今天,人們也用到“類 A L G O L”的程式設計語言。

             它的第一個版本是 A L G O L 5 8,由一個國際委員會在 1 9 5 7~1 9 5 8年設計而的。兩年後,即1 9 6 0 年進行了修改,修訂版命名為 ALGOL 60 。最後的版本是 ALGOL 68 。本章用到的A L G O L版本在文件“ Revised Report on the Algorithmic Language ALGOL 60”中有描述,該文件在 1 9 6 2年完成, 1 9 6 3年第1 次印刷。

               讓我們來編寫一些 A L G O L程式碼。假設一個名為 A L G O L . C O M的編譯程式執行在 C P / M或M S - D O S下。第一個 A L G O L程式是一個名為 F I R S T. A L G的文字檔案,注意它的檔案型別。

              一個A L G O L程式必須由 b e g i n和e n d作為開始和結束,以下為顯示一行文字的程式:

 

可以用 A L G O L編譯程式來編譯 F I R S T.ALG 程式,操作如下:

         A L G O L編譯程式的響應可能是顯示類似於下面的內容:

         A L G O L對拼寫的挑剔不亞於傳統的英語教師。在輸入程式時若拼錯了單詞 e n d,編譯程式則會告知程式有一個語法錯誤。當它碰到 e n d e時,它希望那是它可以識別的關鍵字。

         修改了錯誤以後,可以再執行 A L G O L編譯程式。有時,編譯程式會直接生成一個可執行檔案(名為 F I R S T. C O M,或者是 M S - D O S下的 F I R S T. E X E);有時,還需要進行另一個步驟。無論怎樣,你都可以從命令列執行 F I R S T程式:

 

F I R S T程式的響應是顯示:

         糟糕!還有一個拼寫錯誤。這是一個編譯程式不能發現的錯誤,因此,稱為執行時錯誤( run-time error) —即只在執行程式時才出現的錯誤。

         可以看出,在該 A L G O L程式中, p r i n t語句在螢幕上顯示一些內容,本例是一行文字(因此,這個 A L G O L程式等效於本章前面 C P / M下的彙編程式) 。 p r i n t語句實際上並不是 A L G O L語言正式定義的一部分, 這裡只假設正在用的這個 ALGOL 編譯程式包含有這樣一個實用工具,有時稱作內部函式。 p r i n t語句—就像許多 ALGOL 語句(除 b e g i n和e n d外)一樣—後面必須跟引號。 p r i n t語句向裡縮排不是必須的,只不過使得程式結構更清晰。

         假設要編寫一個程式計算兩個數的乘法。每一個程式設計語言都有 變數 這個概念。在程式中,變數名可以為一個字母、一個短的字母序列,甚至為一個短詞。實際上,變數對應於一個記憶體單元,但在程式中是通過名字來引用的,並不是通過記憶體地址。下面這個程式有 3個變數,名為 a、 b和c:

          real 語句是說明語句,用來表明程式中要說明的變數。本例中,變數 a、 b、 c是實數或浮點數( A L G O L也支援關鍵字 i n t e g e r,用來說明整型變數) 。通常,程式設計語言要求變數名以字母開頭。只要第一個字元是字母,變數名可以包含數字,但不能包含空格及許多其他字元。通常編譯程式要限制變數名的長度。本章的例子都採用一個字母作為變數名。

          如果使用的 A L G O L編譯程式支援 I E E E浮點數標準,則程式中的 3個變數都需要 4個位元組的儲存空間(對單精度數)或 8個位元組的儲存空間(對雙精度數)。

          接下來的三個語句是賦值語句。在 A L G O L中,賦值語句定義為冒號後緊跟等號。 (在許多計算機語言中,賦值語句只需用等號。 )賦值語句的左邊是變數,右邊是表示式。前兩個賦值語句是給 a和b賦給一個值,第三個賦值語句中變數 c的值由變數 a和b產生。

          今天,在程式設計語言中,大家熟悉的×(乘號)通常不允許使用,因為它不屬於 A S C I I碼和 E B C D I C的字符集。許多程式設計語言用星號( *)表示乘法。雖然 A L G O L用斜槓( /)表示除法,但也包括一個除號(÷)表示整數除法,即表明被除數中有多少倍的除數。A L G O L中也定義了箭頭(↑),這是另一個非 A S C I I碼字元,用來表示乘方。

          最後是用來顯示的 p r i n t語句。本例中即有文字又有變數,它們用逗號隔開。顯示 A S C I I字元可能並不是 p r i n t語句的主要工作,本例中,它的功能還包括把浮點數轉換成 A S C I I碼:

 

接著程式終止,返回到作業系統。

           如果想乘另外兩個數,則需要修改程式,改變數,重新編譯,再執行。可以利用一個名為r e a d的內建函式來避免這種頻繁的重新編譯工作:

 

r e a d語句從鍵盤讀入 A S C I I碼字元並轉換成浮點數。

           高階語言中一個非常重要的結構是迴圈。迴圈使得同一段程式依據一個變數的多個不同的值來執行。假設有一段程式用來計算 3、 5、 7和9的立方,就可以這樣做:

 

f o r語句設定變數 a的初值為 3 ,然後執行 d o關鍵字以後的語句。如果要執行的語句不止一條(本例中正是如此) ,則這些語句必須包括在 b e g i n和e n d之間,這兩個關鍵字定義了一個語句塊。 f o r語句接著把變數 a設定成5、 7和9,並執行這些相同的語句。

          下面是 f o r語句的另一種形式,它計算 3~9 9間奇數的立方值:

 

f o r語句設定變數 a 的初值為 3,然後執行 f o r語句後的語句塊。然後 a以s t e p關鍵字後面的值 2為步長增加,得到新值 5,並用來執行程式碼塊。變數 a不斷加 2,當它超過 9 9時, f o r迴圈結束。

             程式設計語言通常都有非常嚴格的語法。例如,在 ALGOL 60 中,關鍵字 f o r後只能跟一種型別的東西,即變數名。而在英語裡,單詞 f o r後可以跟許多不同的單詞,如“ for example”。雖然編譯程式不是容易編寫的簡單程式,但它顯然要比解釋人類語言的程式要簡單得多了。

             大多數程式設計語言的另一個重要特性是包含條件語句。條件語句只是在某個條件為真時才允許執行另一條語句。下面是使用 A L G O L內部函式 s q r t的一個例子,用來計算平方根。s q r t函式不能用來處理負數,所以程式中應避免出現這種情況:

 

左尖括號<是小於號。如果使用者輸入的一個數小於 0,則執行第一個 p r i n t語句。否則,該數大於等於 0,則執行包含另一個 p r i n t語句的語句塊。

            到目前為此,本章程式中的每個變數只能存放一個值。用一個變數來存放多個值也是很方便的,這就是陣列。 A L G O L程式中宣告一個數組的方法如下所示:

           本例中,表明要用該變數來儲存 1 0 0個不同的浮點值,這些值稱作陣列元素。第一個為a [ 1 ],第二個為 a [ 2 ],最後一個為 a [ 1 0 0 ]。方括號中的數字稱作陣列下標。

           下例程式計算從 1 ~1 0 0的所有數的平方根,把結果存放在陣列中並顯示出來:

            程式中也聲明瞭一個整型變數,名為 i(因為它是 i n t e g e r的第一個字母,所以經常用來作為整型變數名) 。在第一個 for 迴圈中,陣列的每一個元素賦值為它的下標的平方根;第二個f o r迴圈中,輸出這些值。

             除了實型和整型外,變數還可以宣告為布林型(為了紀念第 1 0章提到的喬治·布林)。一個布林變數只有兩個可能的值,即 t r u e和f a l s e。本章的最後一個程式裡將用到布林陣列(和到目前為止學到的幾乎所有特性) 。該程式實現稱為“ E r a t o s t h e n e s漏勺”的用來找到素數的著名演算法。 E r a t o s t h e n e s(大約公元前 2 7 6-1 9 6年)是亞歷山大傳說中的圖書館的管理員,他由於精確地計算出了地球的圓周長而名垂史冊。

              素數是指只能被 1 和它本身整除的自然數。第一個素數是 2(唯一的偶數素數),此外,素數還有 3、 5、 7、 11 、 1 3、 1 7等等。

              E r a t o s t h e n e s方法是從以 2開始的正的自然數列表開始。因為 2是素數,則要刪除所有是 2的倍數的數(即除 2以外的所有偶數) ,這些數都不是素數。因為 3 是素數,則要刪除所有是 3的倍數的數。已經知道 4不是素數,因為它已被刪除了。下一個素數是 5,則要刪除所有是 5的倍數的數。依此類推,那些餘下的數就是素數。

             下面的 A L G O L程式用來確定 2~10 000的所有素數,通過宣告一個布林陣列來標識從 2 ~1 0 0 0 0的所有數來實現該演算法:

 

第一個 f o r迴圈把陣列所有元素的布林值設定為 true。這樣,程式一開始假設所有的數都是素數。第二個 for迴圈從 1 ~1 0 0(為 10 000的平方根) 。如果數是素數,意味著 a [ i ] 為真,則另一個f o r迴圈用來把該數的倍數設定為 f a l s e,這些數都不是素數。最後一個 f o r迴圈輸出所有的素數,即 a [ i ]為真時對應的 i值。

           有時人們在爭論程式設計到底是一門藝術還是一門科學。一方面需要在大學裡學習有關電腦科學的課程,另一方面又要看著名的如 Donald Knuth的《The Art of Computer Programmign》系列這樣的書。物理學家 Richard Feynman寫道“更確切的說,電腦科學更像工程—都是用一些東西來實現另一些東西”。

           如果讓 1 0 0個不同的人都來編寫輸出素數的程式,將會得到 1 0 0個不同的方法。即使這些程式設計師都有“ E r a t o s t h e n s漏勺”這種思想,也不會正好以同樣的方法實現。如果程式設計真的是一門科學,就不會有如此多的方法,而不正確的解決方法也是經常有的。偶爾程式設計問題會激起富有創造性和敏銳觀察力的火花,而這就是“藝術”的成分。但是,程式設計更多的是設計和組裝的過程,就像在架設一座大橋。

           早期的許多程式設計員都是科學家和工程師,他們利用 F O RT R A N和A L G O L所要求的數學演算法來闡述自己的問題。然而,縱觀程式設計語言的歷史可以發現,人們希望有能被更大範圍的人們所使用的語言。

           第一個為商務系統設計的成功語言是 C O B O L( common business oriented language) ,今天仍被廣泛使用。由美國工業和國防部組成的委員會於 1 9 5 9年早期推出了 C O B O L,它受到了Grace Hopper的早期編譯程式的影響。從某種意義上說, C O B O L使得管理人員—可能並不具體設計編碼— 至少可以看懂程式程式碼並且能夠檢查程式碼是否按所預定的去工作(在現實
生活中,這種情況很少發生)。

          C O B O L廣泛支援記錄和生成報表。記錄是按照一致方式組織的資訊的集合體,例如:保險公司可能要維持包含有它所賣的所有險種的一個大檔案,每一險種為一單獨記錄,包括客戶姓名、出生日期和其他資訊。早期的許多 C O B O L程式設計成能處理儲存在 I B M穿孔卡片上的 8 0列記錄,為了儘可能少地佔用卡片空間,日期中的年份通常用 2位編碼而不是 4位,這導致了隨著 2 0 0 0年的到來而普遍出現的“千年蟲”問題。

          2 0世紀6 0年代中期,伴隨著 S y s t e m / 3 6 0專案的開發, I B M公司開發了名為 P L / I的程式設計語言( I是羅馬數字 1 , P L / I表示programming language number one)。 P L / I試圖把A L G O L的塊結構、 F O RT R A N的科學和數學計算功能以及 C O B O L的記錄和報表能力結合起來。但是,它卻遠沒有像 F O RT R A N和C O B O L那樣流行。
            儘管F O RT R A N、 ALGOL 、 C O B O L和P L / I都有適用於家用計算機的版本,但是它們都不具備B A S I C所具備的那種對小計算機的影響力。

           B A S I C( b e g i n n e r’ s all-purpose symbolic instruction code)是 D a r t m o u t h數學系的 J o h nK e m e n y和 Thomas Kurtz在1 9 6 4年為 D a r t m o u t h的分時系統開發的。 D a r t m o u t h的許多學生並非主修數學或工程課程,所以他們不能在穿孔卡片和很難的程式設計語法上花費很多時間。D a r t m o u t h的學生坐在終端前,只需在數字之後簡單地敲入 BASIC語句,即可建立B A S I C程式。數字表明程式中語句的順序。沒有數字在前的語句是對系統的命令,如 S AV E(儲存 B A S I C程式到磁碟)、 L I S T(按順序顯示行)和 R U N(編譯和執行程式) 。第一批印刷的 B A S I C指令手冊中的第一個 B A S I C程式為:

           不同於 A L G O L, B A S I C不需要程式設計員來指定一個變數是按整數儲存還是浮點數儲存。不需要程式設計師操心,大多數數都是按浮點數儲存。

           許多後來的 B A S I C版本是解釋程式而不是編譯程式的。前面講過,編譯程式是讀取一個原始檔,併產生一個可執行檔案;而解釋程式讀取原始碼並在讀的過程中直接執行而不生成可執行檔案。解釋程式比編譯程式容易編寫,但是,解釋程式的執行時間卻比編譯程式的執行時間要慢。當比爾·蓋茨(生於 1 9 5 5年)和他的密友保羅·艾倫(生於 1 9 5 3 年)在 1 9 7 5年為Altair 8800編寫B A S I C解釋程式並創立他們的公司—微軟公司的時候, B A S I C才開始應用到家用計算機中。

            P a s c a l程式設計語言繼承了 A L G O L的許多結構,但也包括了 C O B O L的記錄處理程式。該語言由瑞士電腦科學教授 Niklaus Wi r t h(生於 1 9 3 4年)在 2 0世紀 6 0 年代後期設計而成。P a s c a l在IBM PC程式設計員中很受歡迎,但卻以一種特殊的形式—Turbo Pascal這種產品形式流行。該產品於 1 9 8 3 年由 B o r l a n d公司推出,售價為 $ 4 9 . 9 5 。 Turbo Pascal (由丹麥學生Anders Hejlsberg(生於 1 9 6 0年)編寫)是 P a s c a l的一個版本,提供了完整的 整合化開發環境。文字編輯器和編譯程式整合在一個程式裡,促進了快速程式設計。整合化開發環境在大型機上很流行,但 Turbo Pascal卻首先在小機器上實現了。

             P a s c a l對A d a也有很大影響。 A d a是為美國國防部開發使用的一種語言,是以 Augusta AdaB y r o n命名的。第 1 8章中已提到過這個人,他是查爾斯·巴貝芝的解析機的見證人。

             然後就有了 C語言,一種受到萬般寵愛的程式設計語言。它於 1 9 6 9年~ 1 9 7 3年產生,大部分是由貝爾電話實驗室的 Dennis M.Ritchie 完成的。人們常常問為什麼叫 C語言,簡單的回答是它來自於一種早期的語言 B, B是B C P L( Basic CPL)的一種簡單版本,而 B C P L又來自於C P L( combined programming language)。

             第2 2章曾提到過 U N I X作業系統被設計成可移植的形式。那時許多作業系統都是用匯編語言針對特定處理器而編寫的。 1 9 7 3 年, U N I X採用 C來編寫(更確切地說是重寫) 。從那時起,作業系統和 C語言的關係就開始緊密起來。

              C 是很簡潔的語言,例如, A L G O L和P a s c a l中用 b e g i n和end 來定義的塊,在 C語言中用{}來代替。下面是另一個例子,該例對程式設計員來說是很常見的,就是把一個常量與一個變數相加:

        i =i+5;

        在C語言中,可以簡寫為:

        i+=5;

        如果只需要把變數加 1 (即增量) ,甚至可以這樣來簡寫語句:

        i++;
        在1 6位或3 2位微處理器中,這樣一條語句可以由一條機器碼指令來實現。

        前面曾提到,許多高階語言不包括移位操作和按位邏輯操作,而這些是許多處理器所支援的操作, C語言是個例外。另外, C語言的另一重要特點是支援指標,指標實質上是數字化的記憶體地址。由於 C有許多操作類似於常見的處理器指令,因而有時候也把 C語言歸類於高階組合語言 。勝過於任何類 A L G O L語言, C更接近於常用的處理器指令集。

         然而,所有的類 A L G O L語言—即指常用的程式設計語言,是在馮·諾依曼計算機體系結構基礎上設計而成的。在設計計算機語言時,突破馮·諾依曼框架並不容易,而讓人們來使用這種語言則更加困難。一個非馮·諾依曼的語言是 L I S P( LISt Processing ),是由 J o h n   McCarthy 在2 0世紀5 0年代末設計而成的,可用在人工智慧領域。另一個與眾不同且與 L I S P完
全不同的語言是 A P L( A Programming Language),是由 Kenneth Iverson也在 2 0世紀5 0年代末開發而成的。 A P L採用了一個奇怪的符號集用來一次在整個數字陣列上執行操作。

 

           雖然類A L G O L語言仍保持著主導地位,最近幾年,出現了叫作面向物件的程式設計語言,使這類語言的地位得到加強。這些面嚮物件語言與圖形化作業系統一起使用,圖形化內容在下一章(即最後一章)將作介紹。