彙編快速入門

腳板發表於2019-03-03

本文是 WebAssembly 系列文章的第三部分。如果你還沒有閱讀過前面的文章,我們建議你 從頭開始

理解彙編和編譯器如何生成它的有助於你後續理解 WebAssembly 的工作原理,

介紹 JIT 的文章裡,我談到了與機器交流的方式和與外星人通訊是相似的。

彙編快速入門
一個人用原始碼示意,外星人以二進位制迴應

我現在真想看看外星人大腦的思考方式——即機器大腦解析和理解通訊的機制。

大腦中有一部分專門用來思考(例如做加減或其他邏輯運算),一部分提供短期記憶儲存,還有一部分提供長期記憶儲存。

這幾個不同的部分都有各自的名稱:

  • 負責思維的部分稱為算術邏輯單元 (ALU)。
  • 短期儲存由暫存器提供。
  • 長期儲存由隨機存取儲存器 (RAM) 提供。

彙編快速入門
圖為 CPU,包含 ALU、暫存器和 RAM

機器碼中的句子被稱為指令。

當一條指令進入大腦時會發生什麼?它會被分解成帶不同含義的不同部分。

指令分解的方式是特定於當前大腦構造的。

例如,這種結構的大腦可能總是將前六個位元組傳送給 ALU。ALU 根據接收到的序列中 1 和 0 的排列,就會明白需要將兩個東西加在一起。

這個欄位稱為操作碼(opcode),它的作用是告訴 ALU 要執行的操作。

彙編快速入門
從 16 位元組指令中取出 6 個位元組並傳送給 ALU

接下來大腦會取後續兩個三位元組的欄位來確定要相加的兩個數。這兩個數會儲存在暫存器中。

彙編快速入門
兩個 3 位元組欄位被解碼用以確定源暫存器

注意這裡機器碼上方的註釋,有助於我們理解這個過程。這就叫做彙編。這段程式碼稱為符號機器碼。符號機器碼是人類理解機器碼的一種方式。

你會發現彙編和這臺機器的機器碼有很直接的關係。因此不同的機器架構對應有不同的彙編方式。當你遇到使用不同架構的機器時,可能就得按它們自己的方式進行彙編。

因此,我們的翻譯物件並不止一個。機器碼不止一種語言,有許多不同種類的機器碼。就像我們人類會說不同的語言一樣,機器也會使用不同的語言。

隨著人類和外星人之間的翻譯問題解決,你也可以將英語、俄語、普通話等語言轉化成外星文A、外星文B了。對程式設計而言,就是將 C、C++、Rust 等語言轉化成 x86、ARM。

如果你想將任意一種高階語言編譯成對應任意體系結構的組合語言,一種方法是建立一整套不同語言到不同彙編的轉化器。

彙編快速入門
圖中左側為程式語言 C、C++ 和 Rust,右側為組合語言 x86 和 ARM,各組合分別以箭頭連線

但這樣的做法非常低效。大部分編譯器會在中間放置至少一箇中間層。編譯器接收高階程式語言並將其轉化成相對底層的形式,轉化結果也不能和機器碼一樣直接執行。這類形式稱為(IR)。

彙編快速入門
圖中解釋了高階語言和組合語言以及中間表示(IR)的關係,箭頭由高階程式語言指向 IR,又由 IR 指向組合語言

這意味著編譯器可以將任意一種高階程式語言翻譯成一種 IR 語言。編譯器的另一部分將得到的 IR 內容編譯成特定於目標架構的語言。

編譯器的前端部分將高階程式語言翻譯成 IR 語言,再由後端將它們從 IR 語言編譯成目標架構的彙編程式碼。

彙編快速入門
與上圖相同,增加了前端和後端的註釋

總結

以上就是彙編的簡要說明,以及編譯器將高階程式語言轉成彙編的過程。在下一篇文章裡,我們將會看到 WebAssembly 是如何實現的。


掘金翻譯計劃 是一個翻譯優質網際網路技術文章的社群,文章來源為 掘金 上的英文分享文章。內容覆蓋 AndroidiOSReact前端後端產品設計 等領域,想要檢視更多優質譯文請持續關注 掘金翻譯計劃

相關文章