新聞中心
我是編程語言翻譯家族的一員, 我們這個家族最重要的工作就是將一個語言描述的源程序翻譯成另外一種語言描述的目標程序, 聽起來有些抽象, 通俗一點就是把你們碼農寫的源碼變成可以執(zhí)行的程序。

我們這個家族可以說是伴隨這計算機的發(fā)展而不斷發(fā)展壯大的, 現(xiàn)在已經成為計算機軟件系統(tǒng)不可缺少的一部分, 如果回顧一下發(fā)家史, 還是挺有趣的。
1.機器語言
我聽說計算機剛發(fā)明那會兒, 人們就是撥弄各種開關、操作各種電纜把程序給“輸入”到計算機中去。
這所謂的程序, 可真的是0110000111這樣的二進制, 我真是佩服這些程序的設計者和操作員們, 太不可思議了。
這種原始的方式也決定了難于誕生超大型程序, 因為太復雜了,遠遠能過人腦能思考的極限。
后來人們做了點改進, 把程序打到穿孔紙帶上, 讓機器直接讀穿孔紙帶, 這下子就好多了, 終于不用撥弄開關了。
但程序的本質還是沒有變化, 依然是在使用二進制來編程。
如果這個樣子一直持續(xù)下去, 估計這個世界上的程序員會少的可憐: 編程的門檻太高了。
比如說你的腦子里得記住這樣的指令:
- 0000 表示從內存中往CPU寄存器裝載數據
- 0001 表示把CPU寄存器的值寫入內存
- 0010 表示把兩個寄存器的值相加
你還得記住每個寄存器的二進制表示:
- 1000 表示寄存器A
- 1001 表示寄存器B
綜合起來就像這樣:
- 0000 1000 000000000001 它的意思是說, 把編號為1的內存中的值裝載到寄存器A當中
- 0010 1000 1001 的意思是把寄存器A和寄存器B的值加起來,放到寄存器A中。
整天生活在這樣的世界里, 滿腦子都是0和1, 要是我估計就抑郁了。
當時的程序員像熊貓一樣稀少, 不, 肯定比熊貓更少, 他們都要二進制寫程序, 對我們翻譯家族沒有任何的需求。
2. 匯編語言
既然二進制這么難記, 人們很快就想到: 能不能給這些指令起個好聽的名稱呢?
- 0000 : LOAD
- 0001 : STORE
- 0010 : ADD
寄存器也是一樣的:
- 1000 : AX
- 1001 : BX
這下讀來容易多了:
- ADD AX BX
人們給這些幫助記憶的助記符起了個名字: 匯編語言。
但是計算機是無法執(zhí)行匯編語言的, 因為計算機這個笨家伙只認二進制, 所以還得翻譯一下才行。
于是我們家族的一個重要成員: 匯編器 隆重登場了, 他專門負責匯編語言寫的程序翻譯為機器語言, 這個翻譯的過程比較簡單,幾乎就是一一對應的關系。
匯編語言解放了人們的部分腦力, 可以把更多的精力集中在程序邏輯上了。 越來越多的人學會了使用匯編來編程, 寫出了很多偉大的軟件。
匯編的優(yōu)點是貼近機器, 運行效率極高, 但是缺點也是太貼近機器, 直接操作內存和CPU寄存器, 不能結構化編程, 每次函數調用還得把手動把棧幀給管理好, 這對于一般的程序員來講太難了!
我的祖先們把穿孔紙帶和匯編語言都稱為低級語言, 把這個時代稱為機器語言編程時代。
生活在這個時代的祖先們是很幸福的, 因為翻譯工作十分簡單。
但是用匯編寫程序的人還是太少, 找我們做翻譯的也很少, 翻譯家族也只是溫飽而已。
3.高級語言
人類的欲望是無止境的, 他們一直在探索用一種更高級的語言來寫程序的可能性, 這種高級語言應該面向人類編寫和閱讀, 而不是面向機器去執(zhí)行。
人類想要的高級語言是這樣的:
聲明各種類型的變量來表示數據,而不是用寄存器。 例如 :
- int value = 100
能使用復雜的表達式來告訴電腦自己的意圖:
- salary = 1000 + salary * 12
可以用各種控制語句來控制流程:
- if .. else , while(....) ....
還可以定義函數來封裝、復用一段業(yè)務邏輯:
- int get_primes(int max) {.....}
但是高級語言和低級語言之間存在著巨大的鴻溝, 怎么把高級語言翻譯成可以執(zhí)行的機器語言是個非常難的問題!
人類在黑暗中摸索了很久,這才迎來一絲光明, 1957年,第一個高級語言的編譯器才在IBM704的機器上運行成功。 更重要的是喬姆斯基對自然語言結構的研究, 把語言文法做了分類,有了0型文法,1型文法, 2型文法,3型文法, 這一下子給我們的翻譯工作奠定了理論基礎。
由于翻譯的復雜性, 除了匯編器之外, 很多新成員加入進來, 我們的家族迅速發(fā)展壯大, 甚至形成了一個專門翻譯的流水線, 這個流水線的家族成員分工合作, 把高級語言翻譯成低級語言。
我主要做的工作就是第一步詞法分析, 大家經常給我開玩笑說: 你這是大刀向源程序頭上砍去。
這其實挺形象的,比如高級語言的源程序是這樣:
total = 1000 + salary * 12
我拿著“大刀”, 唰唰唰把他們砍成一個個的片段, 每個片段叫做Token。
1. 標識符 total
2. 賦值符號 =
3. 數字 1000
4. 加號 +
5. 標識符 salary
6. 乘號 *
7. 數字12
程序中的空格就被我無情的刪除了, 我還會建立一個符號表讓后面的人去使用:
接下來我二叔就會接管, 他非常厲害, 會做語法分析,據說他用了一個叫什么上下文無關語法的理論, 竟然能把我生成的Token 按照語法規(guī)則組建成一棵樹
然后三舅就做語法分析, 他會看看這些標志符的類型,作用域是不是正確,運算是否合法, 取值范圍有沒有問題等等。
我大舅的工作最重要, 把中間代碼生成, 代碼優(yōu)化,以及最后的代碼生成都給承包了。
比如大舅根據語法樹生成的中間代碼如下:
- temp1 = id2 * 12
- temp2 = 1000 + temp1
- id1 = temp2
(注意:id2 就是salary, id1 就是 total)
然后他再優(yōu)化一下:
- temp1 = id2 * 12
- id1 = 1000 + temp1
然后翻譯成匯編:
- MOV id2 AX
- MUL 12 AX
- ADD 1000 AX
- MOV AX id1
已經非常接近運行了!
但是等等, 這id1 (total), id2 (salary) 只是兩個符號, 計算機根本不知道是什么東西, 計算機只關心內存和寄存器, 所以還得給這兩個家伙分配空間, 得到他們的地址。
如果這兩個變量是在別的文件中定義的, 還需要做一件特別的事情: 鏈接!
通過鏈接的方式,把變量的真正地址獲取到, 然后修改上面的id1, id2, 這樣才能形成一個可以執(zhí)行的程序。
在翻譯的過程中,如果有任何步驟出了錯誤, 我們就會通知程序員, 告訴他哪個地方寫錯了, 改正后重新再來。
這就是我們家族的工作, 非常重要,沒有我們的翻譯工作, 人類就無法使用高級語言來編程, 像C, C++,Pascal, C#, Java 這樣影響力巨大的語言就不會出現(xiàn), 現(xiàn)在的軟件編程行業(yè)也不會這么興旺發(fā)達。
我們家族和操作系統(tǒng)、數據庫、網絡協(xié)議棧等軟件一起,成為了計算機世界底層的基礎軟件。
其實我們都明白,現(xiàn)在所謂的高級語言一點也不高級,只有經過訓練的專業(yè)人士才能使用 , 也許在未來會出現(xiàn)完全用自然語言來寫程序, 到那個時候我們家族會是什么樣子? 估計只有上天才知道了。
【本文為專欄作者“劉欣”的原創(chuàng)稿件,轉載請通過作者微信公眾號coderising獲取授權】
戳這里,看該作者更多好文
當前文章:編程語言翻譯家族的發(fā)家史
標題路徑:http://fisionsoft.com.cn/article/djjgedi.html


咨詢
建站咨詢
