早期計算機如何編程?
打孔紙卡 -> 插線板 -> 面板拔開關。python
計算機的原理:程序員
程序如何「進入」計算機:
程序須要加載進內存,是計算機科學。(打孔紙卡,插線板,面板拔開關)編程
打孔紙卡 Punched card
需求:
給機器編程,早在計算機出現以前就有了,著名的就是紡織業。
若是隻想一塊紅色大桌布,能夠直接放紅線進織布機,可是若是想要圖案怎麼辦?好比條紋或方格。
須要沒隔一會,調整一次織布機,由於很是消耗勞動力,因此圖案紡織品很貴。網絡
可編程紡織機:
每一行的圖案由可穿孔紙卡決定,特定位置有沒有穿孔,決定了線是高是低。
橫線是從上/從下穿過,爲了讓每行圖案不一樣,紙片連成長條,造成連續指令。架構
不少人認爲雅卡爾織布機是最先的編程。app
事實證實,穿孔紙卡便宜,可靠,也易懂。
後面世代中,穿孔紙卡用於1890年美國人口普查。
例如:一張卡存一我的的信息,好比種族,婚姻情況,子女數量,出生國家等等。針對每一個問題,人口普查工做者會在對應位置打孔,當卡片插入彙總機,孔會讓對應總和值+1,能夠插入整個國家入口的卡片,在結束後獲得各個總值。
可是,早期的彙總機不算計算機。由於它們只作一件事:彙總數據。操做是固定的,不能編程。穿孔 紙卡存的是數據,不是程序。以後,這些機器被增強,能夠作減,乘,除。甚至能夠作一些小決定,決定什麼時候執行某指令。編程語言
插線板 Plugboard
爲了正確執行不一樣計算,程序員須要某種控制面板,面板有不少小插孔,程序員能夠插電線,讓機器的不一樣部分,互相傳數據和信號。所以也叫「插線板」。
可是,這意味着,運行不一樣程序要從新接線。因此到了1920年代,控制面板變成了可拔插。讓編程更方便,能夠給機器插入不一樣程序。好比,一個插線板算銷售稅,另外一個算工資單。但給插線板編程很複雜。
用插線板編程,不僅在機電計算機流行,世上第一臺通用電子計算機,ENIAC,完成於1946年。用了一大堆插線板。模塊化
程序在紙上設計好以後,給ENIAC連線,最多可能花三個星期。由於早期計算機很是昂貴,停機幾個星期只爲了換程序,徹底沒法接受,急須要更快,更靈活的新方式來編程。函數
幸運的是,到1940年代晚期1950年代初。內存變得可行,價格降低,容量上升。與其把程序存在插線板,存在內存變得可行,這樣易於修改,方便CPU快速讀取。這類機器叫「存儲程序計算機」。工具
馮諾依曼架構
若是內存足夠,不只能夠存要運行的數據,還能夠存程序須要的數據。包括程序運行時產生的新數據。
程序和數據都存在一個地方,叫「馮諾依曼結構」。將指令和數據混合存放到內存,穿孔紙片和插線板,都是分開。
馮諾依曼曾過:我在思考比炸彈重要得多的東西計算機。
馮諾依曼計算機的標誌是,一個處理器(有算術邏輯單元)+ 數據寄存器 + 指令寄存器 + 指令地址寄存器 + 內存(負責存數據和指令)。
第一臺馮諾依曼架構的「存儲程序計算機」,由曼徹斯特大學於1948年建造完成,綽號「寶寶」。
雖然有內存很棒,但程序和數據,依然須要某種方式輸入計算機,因此用穿孔紙卡。
到1980年代,幾乎全部的計算機都有穿孔紙卡讀取器,能夠吸入一張卡片,把卡片內容寫進內存,若是放了一疊卡片,讀取器會一個個寫進內存。一旦程序和數據寫入完畢,電腦會開始執行。即使簡單程序也有幾百條指令,要用一疊紙卡來存。
用紙卡的最大型程序是美國空軍的SAGE防空系統,於1955年完成,據稱頂峯時期,僱傭了世上20%程序員。
主控制程序用了62500張穿孔紙片,等同於大約5MB的數據。穿孔紙卡不只能夠往計算機放數據,還能夠取出數據,程序運行到最後,結果能夠輸到紙卡上,方式是打孔。而後人能夠分析結果,或者再次放進計算機,作進一步計算。
穿孔紙卡的親戚是紙帶,基本是一回事,只不過更連續,不是一張張卡。
如今存儲的方式,硬盤,只讀光盤,DVD,U盤等等。
面板編程 Panel programming
與其插一堆線到插線板,能夠用一大堆開關和按鈕,作到同樣的效果。面板上有指示燈,表明各類函數的狀態和內存中的值。
50和60年代的計算機,通常都有這樣巨大的控制檯。不多有人只用開關來輸入一整個程序,但技術上是可行的,早期針對計算機愛好者的家用計算機,大量使用了開關。由於大多數家庭用戶負擔不起昂貴的外圍設備,好比穿孔紙卡讀取器。
第一款取得商業成功的家用計算機是Altair 8800
有兩種版本能夠買:
爲了給8800編程,要撥動面板上的開關。輸入二進制操做碼,而後按「存儲鍵」把值存入內存。
而後會到下一次內存位置,能夠再次撥開關,寫下一個指令,重複這樣操做。(初代plc 原型)
把整個程序都寫入內存以後,能夠推進開關,回到內存地址0,而後按運行按鈕,燈會閃爍。
不論是插線板,開關或穿孔紙卡。早期編程都是專家活,不論是全職仍是技術控,都要很是瞭解底層硬件。好比 操做碼,寄存器等,才能寫程序。因此編程很難,很煩。
哪怕工程師和科學家都沒法徹底發揮計算機的能力,須要一種更簡單方式,告訴計算機要作什麼。一種更簡單的編程方式。
編程:二進制 -> 助記符(彙編器) -> A-0(編譯器) -> FORTRAIN
組成計算機的物理組件:
好比電
,電路
,寄存器
,RAM
, ALU
, CPU
。
在硬件層面編程很是麻煩,因此程序員想要一種更通用的方法編程。
一種「更軟的」媒介: 軟件。
第一條指令在內存地址0: 0010 1110
。前4位操做碼,簡稱OPCODE
對於這個假設CPU,0010
表明LOAD A
指令:把值從內存複製到寄存器A。
後4位是內存地址,1110
是十進制的14。
因此這8位表達的意思是:讀內存地址14,放到寄存器A。
只是用了兩種不一樣語言,能夠想成是英語和摩爾斯碼的區別。
「hello
」 -> 「.... . .-.. .-.. ---
」是一個意思:「hello
」
只是編碼方式不一樣,英語和摩爾斯碼的複雜度也不一樣,英語有26個字母以及各類發音。摩爾斯碼只有「點」和「線」但它們能夠傳達相同的信息,計算機語言也相似。
二進制寫程序
計算機能處理二進制,二進制是處理器的「母語」。事實上,它們只能理解二進制。這叫「機器語言」或「機器碼」。
在計算機早期階段,必須用機器碼寫程序。
具體來說,會先在紙上寫一個「高層次版」的僞代碼(PSEUDO-CODE)。
例如:從內存取下一個銷售額,而後加到天,周,年的總和,而後算稅。
寫好僞代碼後,用「操做碼錶」把僞代碼轉成二進制機器碼,翻譯完成後,程序能夠喂入計算機並運行。
助記符
在1940~1950年代,程序員開發出一種新語言,更可讀,更高層次。
每一個操做碼分配一個簡單名字,叫「助記符」(MNEMONICS)。
「助記符」後面緊跟數據,造成完整指令。與其用1和0寫代碼,程序員能夠寫「LOAD A 14」。它不能理解文字,只能理解二進制,因此程序員想了一個技巧,寫二進制程序來幫忙。它能夠讀懂文字指令,自動轉成二進制指令。這種程序叫「彙編器」。
彙編器讀取用「彙編語言」寫程序,而後轉成「機器碼」。「LOAD_A 14」是一個彙編指令的例子。
隨着時間的推移,彙編器有愈來愈多功能,讓編程更容易,其中一個功能是自動分析JUMP
地址。
例如:JUMP NEGATIVE
指令跳到地址5, JUMP 2
指令跳到地址2。
問題是,若是在程序開頭多加一些代碼,全部地址都會改變。更新程序會很痛苦。
因此彙編器不用固定跳轉地址,而是讓插入可跳轉的標籤。
當程序被傳入彙編器,彙編器會本身搞定跳轉地址。程序員能夠專心編程,不用管底層細節。隱藏沒必要要的細節來作更復雜的工做。
然而,即便彙編器有這些厲害的功能,好比自動跳轉。彙編只是修飾了一下機器碼。
通常來講,一條彙編指令對應一條機器指令。因此彙編碼和底層硬件的鏈接很緊密,彙編器仍然強迫程序員思考,用什麼寄存器和內存地址。
若是忽然要一個額外的數,可能要修改不少代碼。
A-0
哈佛1號在1944年戰時完成,幫助盟軍做戰,程序寫在打孔紙袋上,放進計算機執行,若是程序由漏洞,直接使用膠帶來補「漏洞」。
Mark 1的指令集很是原始,甚至沒有JUMP
指令,若是代碼要跑不止一次,得把帶子的兩端連起來,作成循環。(循環,物理,物理,循環)
給Mark 1編程簡直是噩夢,戰後,霍普繼續研究計算機,爲了釋放電腦的潛力,設計了一個高級編程語言,叫「算術語言版本 0」,簡稱「A-0」。
彙編與機器指令是一一對應的,但一行高級編程語言,可能會轉成幾十條二進制指令。爲了作到這種複雜的轉換,霍普在1952年創造了第一個編譯器,編譯器專門把高級語言,轉成低級語言,好比彙編或機器碼(CPU 能夠直接執行機器碼)
儘管「使編程更簡單」很誘人,可是不少人持懷疑態度。
霍普曾說:「我有能用的編譯器,但沒人願意用,他們告訴我計算機只能作算術,不能運行程序」。
不久,不少人嘗試創造新編程語言,到現代現在有上百種語言。
惋惜的是,沒有任何A-0
的代碼遺留下來。
使用Python舉例:
假設想相加兩個數字,保存結果,記住,若是用匯編代碼,得從內存取值,和寄存器打交道,以及其它底層細節。
不用管寄存器的內存位置,編譯器會搞定這些細節,不用管底層細節。
程序員只須要建立,表明內存地址的抽象,叫「變量」(給變量取名字)。
底層操做時,編譯器可能把變量A存在寄存器A,但程序員不須要知道這些,眼不見心不煩。
FORTRAN
但A-0
和以後的版本沒有普遍使用。FORTRAN
,名字來自「公式翻譯」。這門語言數年後由IBM在1957年發佈。主宰了早期計算機編程。
FORTRAN
項目總監John Backus
曾說:我作的大部分工做都是由於懶,我不喜歡寫程序,因此我寫這門語言,讓編程更容易。
FORTRAN
寫的程序,比等同的手寫彙編代碼短20倍,而後FORTRAN
編譯器會把代碼轉成機器碼。
對於FORTRAN
程序的性能是否比得上手寫代碼?但由於能讓程序員寫程序更快,因此成了一個更經濟的選擇。
運行速度慢一點點,編程速度大大加快。
當時IBM在賣計算機,所以最初的FORTRAN
代碼只能跑在IBM計算機上,1950年代大多數編程語言和編譯器,只能運行在一種計算機上。若是升級電腦,可能要重寫全部代碼。所以工業界,學術界,政府的計算機專家,在1959年組建了一個聯盟: 數據系統語言委員會,霍普擔任顧問。開發一種通用的編程語言,能夠在不一樣機器上通用。最後誕生了一門高級,易於使用:普通面向商業語言,簡稱COBOL
。
爲了兼容不一樣底層硬件,每一個計算機架構須要一個COBOL
編譯器,最重要的是,這些編譯器均可以接受相同的COBOL
代碼。不論是什麼電腦,這叫「一次編寫,處處運行」。現在的大多數編程語言都是這樣。沒必要接觸CPU特有的彙編碼和機器碼。
減下了使用門檻,在高級編程語言出現以前,編程只是計算機專家和愛好者纔會作的事,並且一般是主職。但如今,科學家,工程師,醫生,經濟學家,教師等等,均可以把計算機用於工做。
「解釋型語言」對應「解釋器」,編譯器是把語言編程二進制代碼再運行。
計算機科學從深奧學科,變成了大衆化工具,同時,編程的抽象也讓計算機專家,製做更復雜的程序。
1959年代,編程語言黃金時代開始,和硬件一塊兒飛速發展。
1960年代:ALGOL, LISP, BASIC
1970年代:Pascal C, Smalltalk
1980年代:C++, Object-C, Perl
1990年代:Python, Ruby, Java
2000年代:Swift, C#, Go
新語言想用更聰明的抽象,讓某些方面更容易或更強大,或利用新技術和新平臺帶來的優點。
用機器碼寫程序,還要處理那麼多底層細節,對寫大型程序是個巨大障礙。爲了脫離底層細節,開發了編程語言,讓程序員專心解決問題,不用管硬件細節。
變量,賦值語句
規定句子結構的一系列規則叫語法。
a=5
是一個編程語言語句,意思是建立一個叫a的變量,把數字5放裏面。這叫「賦值語句」,把一個值賦給一個變量。爲了表達更復雜的含義,須要更多語句。
變量名能夠隨便取。
程序由一個個指令組成,有點像菜譜:燒水,加面,等10分鐘,撈出來就能夠吃了。
程序也是這樣,從第一條語句開始,一句一句運行到結尾。
拍蟲子遊戲
阻止蟲子飛進計算機形成故障,關卡越高,蟲子越多。在蟲子損壞繼電器以前,抓住蟲子。
開始編寫時,須要一些值,來保存遊戲數據,好比當前關卡數,分數,剩餘蟲子數,還剩下幾個備用繼電器。
因此要「初始化」變量,「初始化」的意思是設置最開始的值。
level = 1 # 關卡=1 score = 0 # 分數=0 bugs = 0 # 蟲子=5 relays = 4 # 備用繼電器=4 name = 'andre' # 玩家
爲了作成交互式遊戲,程序的執行順序要更靈活,不僅是從上到下執行,所以用「控制流語句」。if
構成的語句叫: 「條件語句」
若是但願根據條件執行屢次,須要「條件循環」。
計算指數,代碼很經常使用。若是每次想用就複製粘貼,會很麻煩,每次都要修改變量名,若是代碼發現問題,要補漏洞時,要把每個複製粘貼過的地方都找出來修改,並且會讓代碼更難懂,少便是多。想要某種方法,把代碼「打包」,能夠直接使用,得出結果。不用管內部複雜度。
函數
爲了隱藏複雜度,能夠把代碼打包成「函數」也叫「方法」或「子程序」,其它地方想用到這個函數,直接寫函數名就能夠了。須要把結果,交給使用這個函數的代碼,因此用return
語句,指明返回什麼。
函數是,抽象的力量。
現在超過100行代碼的函數不多見,若是多於100行,應該有些東西能夠拆出來作成一個函數。
若是有第二次地方使用,就抽象出函數。
模塊化編程,不只可讓單個程序員獨立製做app,也讓團隊協做能夠寫更大型的程序。
現代編程語言,有不少預先寫好的函數集合,叫「庫」。由專業人員編寫,不只效率高,並且通過了仔細的檢查。幾乎作全部的事情,都有庫,網絡,圖像,聲音。