1. 日常生活中使用自然語言
顧名思義,計算機語言類似于漢語、英語,是一種用來傳遞信息的工具。
例如日常生活中,使用漢語將自己想表達的思想傳遞給他人。
來百度APP暢享高清圖片
2. 能否用自然語言和計算機“說話”?
我們知道計算機最初的用途就是用于計算數據,我們以一個最簡單的例子來看。
例如我想知道123+456等于多少?
我可以用漢語對計算機進行提問嗎?
你肯定會回答說,可以啊,現在的語音助手完全可以實現這種功能。例如,apple的siri,小米的小愛同學,百度的小度,淘寶的天貓精靈。
看似簡單的一問一答,事實上,卻在計算機內部,卻經歷了一個非常復雜的步驟。下面是一個非常概括的流程圖,大概說明這里面經歷了哪些步驟。
這其中的一個非常重要的環節是:通過自然語言識別和理解算法,讓計算機知道了我們需要運行加法程序。接著把123和456放到計算程序里面,讓它們相加。
得益于現代的人工智能學科的發展,讓計算機看起來似乎可以理解我們日常生活中使用的自然語言了。然而實際上,計算機卻只是忠實地執行了固定的程序。
3. 怎樣直接和計算機“說話”?
我們暫時不探討怎樣讓計算機理解自然語言,我們把中間的步驟去掉,怎樣讓計算機能夠直接理解我們想表達的內容呢?
很簡單,答案就是:通過編程語言。
通過編程語言,我們可以鍵入對應語法,讓機器通過代碼來理解我們的意圖。
4. 探究CPU內部工作原理
要和計算機直接溝通,那么我們就必須知道計算機是如何思考的。讓我們進入計算機的內部,看一看被稱為計算機的核心CPU(中央處理器,central processing unit),是如何工作的。
CPU由三部分構成:
- 算術、邏輯單元:對數據執行運算(例如加法、減法)的電路。
- 控制單元:協調機器活動的電路。
- 寄存器組 :數據臨時存儲。
然而,寄存器能夠存儲的信息量很少,僅僅是當前工作所必要的。話說魚的記憶只有7秒,CPU的記憶恐怕是更短。總不能,CPU做一步操作,就把上一步操作的結果給忘了吧。
因此,我們需要內存來配合CPU進行數據操作。
數據大部分幾乎都存儲在內存上,僅有當前正在處理的數據,才放到CPU的寄存器組上,數據通過數據總線,在CPU和內存上進行傳輸。
接下來,我們來看看,將兩個數據相加會經歷哪些步驟。
- 從內存中取出一個加數放到一個寄存器中。
- 從內存取出另一個加數,放到另一個寄存器中。
- 激活算術、邏輯單元中的加法電路,以前面兩步的寄存器作為輸入,用另一個寄存器存放結果。
- 將結果存放到內存中。
5. 最接近計算機運行本質的語言——機器語言
在上一節中,我們知道了讓計算機運行兩個數的加法需要進行4個步驟。那我們把這4個步驟告訴計算機,就可以實現加法操作了。但是,計算機內部就是一大堆晶體管,每個晶體管有開和關兩個狀態。一般我們用1來表示開,用0來表示關。也就是說,計算機能存儲的是只兩種狀態的數據,而十進制擁有0到9十種狀態。很顯然,十進制數據的狀態太多,沒法在計算機內表示。所以,首先我們把123和456轉換為二進制吧。
123的二進制為1111011 456的二進制為111001000
現在123和456被只有兩種狀態的二進制所表示了,滿足計算機內部也只有兩種狀態的情景了。簡化得來說,123在計算機內部,被存儲為晶體管狀態---開開開開關開開。456被存儲為晶體管狀態---開開開關關開關關關關。
歸根結底,計算機能存儲和操作的是晶體管的狀態組合,而這種狀態組合中,每一個晶體管只有兩種狀態,與二進制數據一一對應。而二進制又可以被轉換為十進制。因此,計算機間接地計算了十進制數據。
數據在計算機中被存儲為了晶體管狀態,要完成運算,必須對數據進行操作。 在前面的步驟中,我們做了兩類操作。
一類操作是移動數據。例如,將加數放入寄存器1。 另一類是激活加法電路。例如,將寄存器1,寄存器2的數據相加,并放入寄存器3。
很顯然,要執行什么操作也必須以晶體管的開關狀態來表示。我們很自然地會把它們也寫成二進制形式,稱之為操作碼。
而操作數指明操作的更詳細信息,例如,需要操作的數據本身,或者哪個寄存器包含需要操作的數據,哪個存儲單元用于接收該數據。
操作碼+操作數為一條指令。
操作碼與操作數在數據上沒有本質上的區別,它們都是二進制的數據。例如:CPU每次讀取16位二進制,將前3個二進制,當作操作碼。其后都作為操作數。
這種以二進制表示對應的晶體管狀態的方式,我們將其稱之為機器語言。
當然,在紙上寫好二進制之后,我們必須讓其轉化為晶體管狀態。這里就設計到輸入輸出設備了,在早期人們會在紙帶上打孔,用是否打孔來代表一個晶體管狀態。之后,將打好孔的紙帶放到機器中讀取,將其轉換為晶體管狀態。如今,我們直接使用鍵盤在屏幕上輸入即可。
6. 用助記詞來優化機器語言——匯編語言
單純用0和1來寫程序非常的困難。一是操作碼難于記憶,二是二進制的數據十分冗長。 于是,人們把操作碼用一系列的英文單詞來表示,將二進制寫成十六進制。這就產生了匯編語言。
例如,把移動操作碼,用單詞mov來替代。把激活加法電路,用單詞add來替代。
這樣程序更易于人們理解。
這樣也必然衍生出一個問題,計算機無法直接處理英語和十進制。因此,需要一個匯編器來作為“翻譯”,將匯編語言“翻譯”成由二進制表示的晶體管狀態。
7. 低級語言依賴CPU的具體實現
在編寫機器語言或匯編語言時必須要注意:不同類型的CPU內部工作細節不盡相同。個人電腦采用的是Intel、AMD出品CPU。而移動設備常常采用ARM系列的CPU。
在寫機器語言時,會遇到很多差異性的問題。例如,寄存器的數量、作用不同,操作碼的二進制表示不一致。或者,在一種CPU上有某種類型的操作碼,但是在另一種CPU上卻沒有這種類型的操作碼。而對應效果的操作,在后者上是由其他幾種操作碼+操作數組成的指令,分幾步完成。
再看看匯編語言的情況呢? 匯編語言是通過注記詞來替代二進制表示的,如果用面向不同類型CPU的匯編器來“翻譯”,確實可以解決一部分的操作碼二進制不一樣的差異。例如,兩類CPU上均有mov操作,但是二進制表示不同,一個是0010,一個是1001。那么使用對應的匯編器來“翻譯”,可以解決這個問題。但是,這僅僅是一小部分差異。因此,匯編語言也必須嚴格按照目標CPU來差異化編寫程序,并且用對應的匯編器來“翻譯”。
不管是機器語言還是匯編,在寫程序前必須關注CPU的內部細節。運行在一種類型CPU上的代碼,不能直接在另一種類型的CPU上直接運行。需要將其根據另一類CPU的工作細節進行修改,才能正常運行。
8. 不依賴具體指令集的語言——高級語言
現在你可以用機器語言或匯編語言寫計算機程序了。 如果你覺得為什么計算機語言如此復雜,那就對了。機器語言或匯編語言忠實地描述了計算機的詳細工作狀態。 因此,用機器語言或匯編寫出來的計算機代碼,詳細操作了太多的細節了。 對人來說是十分不友好的,難以編寫,調試。并且,也難以在多種類型的CPU上移植。
那怎么辦呢?能不能有一個更好的辦法,這時候高級語言運應而生。在機器上建立一個抽象層,通過抽象層表達意圖。而避免直接描述具體的CPU工作細節。
我們用C語言來示例寫上面討論的加法問題。代碼如下:
int a, b, c;a = 123;b = 456;c = a + b;printf("%d\n", c);
在C語言中,我們聲明了3個變量。將a賦值為123,b賦值為456。將a、b相加,加法的結果賦值給c。 可以看到,在C語言中,我們不關心a,b,c存在內存上的哪個地方。也不用加法操作碼add那些的。反而,C語言的表述方法和人類的認知十分接近。
和匯編一樣,計算機也無法直接理解高級語言,并且C語言不描述CPU具體工作細節,而是描述了一個抽象過程。沒法像匯編那樣簡單的把英文根據目標CPU替換成二進制狀態了。而是通過兩個更為復雜的過程,將高級語言轉換為機器語言,這兩個步驟分別為“編譯”和“鏈接”。
這樣一來,高級語言與計算機的硬件結構及指令系統無關。在個人電腦上編寫好的程序,也可以拿到移動設備上來使用。并且,它有更強的表達能力,可方便地表示數據的運算和程序的控制結構,能更好的描述各種算法,
特別聲明:以上內容(如有圖片或視頻亦包括在內)為自媒體平臺“網易號”用戶上傳并發布,本平臺僅提供信息存儲服務。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.