1. 程式人生 > 其它 >程式是如何在計算機上被執行的?(上篇:軟體部分)

程式是如何在計算機上被執行的?(上篇:軟體部分)

我們用兩篇文章說明“程式是如何在計算機上被執行的?”,本文是第一部分,著重說明軟體部分——從程式到機器語言,下一篇文章說明硬體部分,即機器語言到邏輯閘

本文又拆分成三個部分,分別是:

  • 寫在前面,關於思考認知
  • 程式到組合語言解析
  • 組合語言到機器語言解析

寫在前面

作為前端程式設計師,最開始在html,css,js中間打轉。

後來,應用react、vue等框架,以及前端工程化,效能優化。我發現做的工作較重複圍繞在應用層,最近思考了很多,發現框架,語言,其實都是工具,為產品服務,產品為使用者服務,去解決現實中的問題。

於是我從圖靈機,馮諾伊曼結構,計算機系統……一個個體系來梳理。本文著重介紹我們寫的程式,經歷了哪些過程,最終如何跑在計算機核心硬體上被執行的。

流程如下:

程式 => 高階程式語言 => 組合語言 => 機器指令 => 邏輯閘 => 電晶體

整個流程,是從下往上的抽象,是為了讓系統方便和易用

從這個角度看,語言,框架,都是工具,類似鉗子,起子,不同的語言,不同的框架,針對不同場景,著重解決特定問題。

從程式到機器語言

下面,我用一個c語言例項來說明以上整個解析過程。

i=1,sum=0,count=100; 
//計數器設為100,累加計算結果設為0
while(count-->0){ 
//計數器大於0時,計數器減1並迴圈執行{}中內容
sum=sum+i;
//每次將sum和i值相加,結果存在sum中;
i++;
//i的值增加1
}

為了在機器上實現以上c語言編寫的程式,我們需要能夠實現語言之間轉換的編譯器。編譯器,指能將一種語言翻譯成另一種目標語言的程式

。在上述程式中,我們需要實現兩個編譯器:

  1. 高階語言編譯成組合語言
  2. 組合語言編譯成機器語言

1、高階語言編譯成組合語言

此過程較為複雜,首先會對原語言進行多次掃描,經過中間程式碼生成和程式碼優化,最終生成目的碼。

用虛擬碼解釋一下這個過程:

P(原始碼){
迴圈(掃描原始碼片段,掃描完停止){
 詞法分析;
 語法分析;
 語義分析;
 目的碼
}
}

組合語言目的碼= P(高階語言原始碼)

下面分別說明:

  • 詞法分析
  • 語法分析
  • 語義分析
  • 目的碼

詞法分析

詞法分析,主要是把原始碼裡面所有字串讀進來,然後進行掃描和分解,把常量、變數名、運算子、關鍵字等標識出來。例如對於上達例子中的語句i=1,sum=O,count=100

需要將其正確地識別成如下的序列 i=1sum=0count=100而不會犯把 100識別成1 0 0三個字元這樣的錯誤。

js中建立詞法環境和變數環境也是在這個階段。

語法分析

此階段主要是在詞法分析的基礎上將識別出來的單詞序列按照該語言的語法要素識別出相應的語法單位。如上句中一共有三個表示式,而且表示式本身可以巢狀遞迴,如count--是表示式,count-->0同樣是表示式。

語義分析語義分析主要作用是判斷整個源程式程式碼裡面是否有錯誤,如變數是否已經宣告,語句是否以分號結束,運算物件是否合理等進行審查。

每一種語言都有其規則,根據規則進行檢查。

目的碼生成將原始碼轉換成目的碼是最重要也最複雜的階段。如上例所示,

  • i=1;sum=0,count=100語句中三個賦值表示式轉換成3條Mov彙編指令,存在三個暫存器中,
  • 然後把while語句的範圍轉換成loop和end之間的程式碼,
  • sum=sum+i轉換成 add A,R1
  • i++轉換成inc R1
  • count--轉換成 dec RO
  • while(count-->0)轉換成jgz RO,Loop

js上下文解析,確定作用域鏈,確定this指標在這一階段。

通過以上過程,就把這段c語言生成了組合語言程式碼。

2、組合語言編譯成機器語言

從組合語言轉換成機器指令基本過程也差不多,而且這個過程比將高階語言轉換成組合語言要簡單。因為在設計cpu的時候,人們對於相應操作以及給出了相應的操作碼(工具,封裝,易用)。

例如上述舉的 Intel 8080 晶片的例子,其 mov操作就是最終生成的機器指令:從40到5F 的一系列數字。因此機器語言完全就是數字的序列。這樣就完成了從高階語言到計算機能夠執行的程式碼的過程。

其實對於程式語言來說,語言的關鍵字元、書寫形式等構成的是語言的語法,但語言的強大與否並不在於語法,而在於提供的相應操作函式的數量,一般語言提供的大量相關的數稱為“類庫”。(工具性)

在實現自已的程式語言時,除了需要實現語言的編譯器以外,更至的是需要提供強大的、適用的函式類庫。

例如前面的語言,如果提供一個叫sum 的累積求和函式,只需要一行語句 sum(1,100)就可以實現從 1加到 100 的加法計算功能。

由於不同的語言設計目的不同,函式庫側重不同,因此不同的語言適用於不同的功能。

如進行快速 Windows視窗開發,C#或者 Visual Basic.NET 更適合;web開發用html,css,js;服務端用Java 和 Python(由於其開源的特性,有大量的第三方類庫能夠支援特定的功能)。

這也就是我前面說的,所有的語言都是等價的,任何語言都可以通過編譯器實現從一種語言到另一種語言的轉換

以上說明了程式是如何在計算機上被解析成機器語言的,以及對語言框架新的認知。

總結一下:計算機所做的工作是由程式規定的。程式是由程式語言編寫的。程式語言是由解釋程式或編譯程式,通過預定義子程式集,即作業系統,轉化為機器語言指令序列的。這些指令儲存在計算機的儲存器中。有限狀態機取出並執行這些指令。指令和資料都是用二進位制位組來表示的。有限狀態機和儲存器都是由暫存器和布林邏輯塊來構造的。布林邏輯塊建立在與、或、非這些簡單邏輯功能的基礎上。這些邏輯功能又是通過開關來實現的。

下一篇文章會著重講後一部分,即機器語言如何在計算機硬體上執行,關於邏輯閘,加法器,布林運算,感謝您的閱讀。