干貨 | 新手經常忽略的嵌入式基礎知識點
為解決各種問題,人們發明了不計其數的機器。嵌入式設備種類繁多,從嵌入火星漫游機器人的計算機到為操縱核潛艇導航系統的系統,不一而足。
馮? 諾伊曼在1945 年提出第一種計算模型,無論筆記本電腦還是電話,幾乎所有計算機都遵循與這種模型相同的工作原理。
那么你們了解計算機是如何工作的嗎?本文將討論這些內容:
◎ 理解計算機體系結構的基礎知識
◎ 選擇編譯器將代碼轉換為計算機可以執行的指令
◎ 根據存儲器層次結構提高數據的存儲速度
畢竟,在非程序員看來,編程要像魔法一樣神奇,我們程序員不會這么看。
體系結構
計算機是一種根據指令操作數據的機器,主要由處理器與存儲器兩部分組成。存儲器又稱RAM(隨機存取存儲器),用于存儲指令以及需要操作的數據。處理器又稱CPU(中央處理器),它從存儲器獲取指令與數據,并執行相應的計算。接下來,我們將討論這兩部分的工作原理。
存儲器
存儲器被劃分為許多單元,每個單元存儲少量數據,通過一個數字地址加以標識。在存儲器中讀取或寫入數據時,每次對一個單元進行操作。
為讀寫特定的存儲單元,必須找到該單元的數字地址。
由于存儲器是一種電氣元件,單元地址作為二進制數通過信號線傳輸。
二進制數以 2 為基數表示,其工作原理如下:

每條信號線傳輸一個比特,以高電壓表示信號“1”,低電壓表示信號“0”,如圖7-1 所示。

對于某個給定的單元地址,存儲器可以進行兩種操作:獲取其值或存儲新值,如圖7-2 所示。存儲器包括一條用于設置操作模式的特殊信號線。
每個存儲單元通常存儲一個 8 位二進制數,它稱為字節。設置為“讀”模式時,存儲器檢索保存在單元中的字節,并通過8 條數據傳輸線輸出,如圖7-3 所示。
設置為“寫”模式時,存儲器從數據傳輸線獲取一個字節,并將其寫入相應的單元,如圖7-4 所示。
傳輸相同數據的一組信號線稱為總線。用于傳輸地址的8 條信號線構成地址總線,用于在存儲單元之間傳輸數據的另外8 條信號線構成數據總線。地址總線是單向的(僅用于接收數據),而數據總線是雙向的(用于發送和接收數據)。
在所有計算機中,CPU 與RAM 無時無刻不在交換數據:CPU 不斷從RAM 獲取指令與數據,偶爾也會將輸出與部分計算存儲在RAM 中,如圖7-5 所示。

CPU
CPU 包括若干稱為寄存器的內部存儲單元,它能對存儲在這些寄存器中的數字執行簡單的數學運算,也能在RAM 與寄存器之間傳輸數據。可以指示CPU 執行以下典型的操作:
◎ 將數據從存儲位置 220 復制到寄存器 3;
◎ 將寄存器 3 與寄存器 1 中的數字相加。
CPU 可以執行的所有操作的集合稱為指令集,指令集中的每項操作被分配一個數字。計算機代碼本質上是表示CPU 操作的數字序列,這些操作以數字的形式存儲在RAM 中。輸入/ 輸出數據、部分計算以及計算機代碼都存儲在RAM 中。
通過在RAM 中包含重寫部分代碼的指令,代碼甚至可以對自身修改,這是計算機病毒逃避反病毒軟件檢測的慣用手法。與之類似,生物病毒通過改變自身的DNA以躲避宿主免疫系統的打擊。
圖7-6 取自Intel 4004 操作手冊,顯示了部分CPU 指令映射為數字的方法。隨著制造工藝的發展,CPU 支持的操作越來越多。現代CPU 的指令集極為龐大,但最重要的指令在幾十年前就已存在。
CPU 的運行永無休止,它不斷從存儲器獲取并執行指令。這個周期的核心是PC 寄存器,PC (program counter)是“程序計數器”的簡稱。PC 是一種特殊的寄存器,用于保存下一條待執行指令的存儲地址。CPU 的工作流程如下:
(1) 從PC 指定的存儲地址獲取指令;
(2) PC 自增;
(3) 執行指令;
(4) 返回步驟1。
PC 在CPU 上電時復位為默認值,它是計算機中第一條待執行指令的地址。這條指令通常是一種不可變的內置程序,用于加載計算機的基本功能。
在許多個人計算機中,這種程序稱為BIOS(基本輸入輸出系統)。
CPU 上電后將繼續執行這種“獲取- 執行”周期直至關機。然而,如果CPU 只能遵循有序、順序的操作列表,那么它與一個花哨的計算器并無二致。CPU 的神奇之處在于可以指示它向PC 中寫入新值,從而實現執行過程的分支,或“跳轉”到存儲器的其他位置。這種分支可以是有條件的。以下面這條CPU 指令為例:“如果寄存器1 等于0,將PC設置為地址200”。該指令相當于:
if x = 0
compute_this()
else
compute_that()
僅此而已。無論是打開網站、玩計算機游戲抑或編輯電子表格,所涉及的計算并無區別,都是一系列只能對存儲器中的數據求和、比較或移動的簡單操作。
大量簡單的操作組合在一起,就能表達復雜的過程。以經典的《太空侵略者》游戲為例,其代碼包括大約3000 條機器指令。
CPU 時鐘 早在20 世紀80 年代,《太空侵略者》就已風靡一時。這個游戲在配備2 MHz CPU 的街機上運行。“2 MHz”表示CPU 的時鐘,即CPU 每秒可以執行的基本操作數。時鐘頻率為200 萬赫茲(2 MHz)的CPU 每秒大約可以執行200 萬次基本操作。完成一條機器指令需要5到10 次基本操作,因此老式街機每秒能運行數十萬條機器指令。
隨著現代科技的進步,普通的臺式計算機與智能手機通常配備2 GHzCPU,每秒可以執行數億條機器指令。時至今日,多核CPU 已投入大規模應用,如四核2 GHz CPU 每秒能執行近10 億條機器指令。展望未來,CPU 配備的核心數量或許會越來越多。
CPU 體系結構 讀者是否思考過,PlayStation 的游戲CD 為何無法在臺式計算機中運行?iPhone 應用為何無法在Mac 中運行?原因很簡單,因為它們的CPU 體系結構不同。
x86 體系結構如今已成為行業標準,因此相同的代碼可以在大部分個人計算機中執行。但考慮到節電的要求,手機采用的CPU 體系結構有所不同。不同的CPU 體系結構意味著不同的CPU 指令集,也意味著將指令編碼為數字的方式各不相同。臺式計算機CPU 的指令并非手機CPU的有效指令,反之亦然。
32 位與64 位體系結構 第一種CPU 是Intel 4004,它采用4 位體系架構。換言之,這種CPU 在一條機器指令中可以對最多4 位二進制數執行求和、比較與移動操作。Intel 4004 的數據總線與地址總線均只有4 條。
不久之后,8 位CPU 開始廣為流行,這種CPU 用于運行DOS 的早期個人計算機。20 世紀八九十年代,著名的便攜式游戲機Game Boy 就采用8 位處理器。這種CPU 可以在一條指令中對8 位二進制數進行操作。
技術的快速發展使16 位以及之后的32 位體系結構成為主導。CPU 寄存器隨之增大,以容納32 位數字。更大的寄存器自然催生出更大的數據總線與地址總線:具有32 條信號線的地址總線可以對232 字節(4 GB)的內存進行尋址。
人們對計算能力的渴求從未停止。計算機程序越來越復雜,消耗的內存越來越多,4 GB 內存已無法滿足需要。使用適合32 位寄存器的數字地址對超過4 GB 內存進行尋址頗為棘手,這成為64 位體系結構興起的動因,這種體系結構如今占據主導地位。64 位CPU 可以在一條指令中對極大的數字進行操作,而64 位寄存器將地址存儲在海量的存儲空間中:264 字節相當于超過170 億吉字節(GB)。
大端序與小端序 一些計算機設計師認為,應按從左至右的順序在RAM 與CPU 中存儲數字,這種模式稱為小端序。另一些計算機設計師則傾向于按從右至左的順序在存儲器中寫入數據,這種模式稱為大端序。因此,根據“字節序”的不同,二進制序列1-0-0-0-0-0-1-1 表示的數字也有所不同。
◎ 大端序:27 + 21 + 20 = 131
◎ 小端序:20 + 26 + 27 = 193
目前的大部分CPU 采用小端序模式,但同樣存在許多采用大端序模式的計算機。如果大端序CPU 需要解釋由小端序CPU 產生的數據,則必須采取措施以免出現字節序不匹配。程序員直接對二進制數進行操作,在解析來自網絡交換機的數據時尤其需要注意這個問題。雖然目前多數計算機采用小端序模式,但由于大部分早期的網絡路由器使用大端序CPU,所以因特網流量仍然以大端序為基礎進行標準化。以小端序模式讀取大端序數據時將出現亂碼,反之亦然。
模擬器 某些情況下,需要在計算機上運行某些為不同CPU 設計的代碼,以便在沒有iPhone 的情況下測試iPhone 應用,或玩膾炙人口的老式超級任天堂游戲。這是通過稱為模擬器的軟件來實現的。
模擬器用于模仿目標機器,它假定與其擁有相同的CPU、RAM 以及其他硬件。模擬器程序對指令進行解碼,并在模擬機器中執行。可以想見,如果兩臺機器的體系結構不同,那么在一臺機器內部模擬另一臺機器絕非易事。好在現代計算機的速度遠遠超過之前的機器,因此模擬并非無法實現。我們可以利用Game Boy 模擬器在計算機中創建一個虛擬的Game Boy,然后就能像使用實際的Game Boy 那樣玩游戲。
編譯器
通過對計算機進行編程,可以完成核磁共振成像、聲音識別、行星探索以及其他許多復雜的任務。值得注意的是,計算機執行的所有操作最終都要通過簡單的CPU 指令完成,即歸結為對數字的求和與比較。而Web 瀏覽器等復雜的計算機程序需要數百萬乃至數十億條這樣的機器指令。
但我們很少會直接使用CPU 指令來編寫程序,也無法采用這種方式開發一個逼真的三維計算機游戲。為了以一種更“自然”且更緊湊的方式表達命令,人們創造了編程語言。我們使用這些語言編寫代碼,然后通過一種稱為編譯器的程序將命令轉換為CPU 可以執行的機器指令。
我們用一個簡單的數學類比來解釋編譯器的用途。假設我們向某人提問,要求他計算5 的階乘。
5! = ?
但如果回答者不了解什么是階乘,則這樣提問并無意義。我們必須采用更簡單的操作來重新表述問題。
5×4×3×2×1 = ?
不過,如果回答者只會做加法怎么辦?我們必須進一步簡化問題的表述。
5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 +5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 + 5 = ?
可以看到,表達計算的形式越簡單,所需的操作數量越多。計算機代碼同樣如此。編譯器將編程語言中的復雜指令轉換為等效的CPU 指令。結合功能強大的外部庫,就能通過相對較少的幾行代碼表示包含數十億條CPU 指令的復雜程序,而這些代碼易于理解和修改。
計算機之父艾倫? 圖靈發現,簡單的機器有能力計算任何可計算的事物。如果機器具有通用的計算能力,那么它必須能遵循包含指令的程序,以便:
◎ 對存儲器中的數據進行讀寫;
◎ 執行條件分支:如果存儲地址具有給定的值,則跳轉到程序的另一個點。
我們稱具有這種通用計算能力的機器是圖靈完備的。無論計算的復雜性或難度如何,都可以采用簡單的讀取/ 寫入/ 分支指令來表達。只要分配足夠的時間與存儲空間,這些指令就能計算任何事物。
人們最近發現,一種稱為MOV(數據傳送)的CPU 指令是圖靈完備的。這意味著僅能執行MOV 指令的CPU 與完整的CPU 在功能上并無不同:換言之,通過MOV 指令可以嚴格地表達任何類型的代碼。
這個重要概念在于,無論簡單與否,如果程序能采用編程語言進行編碼,就可以重寫后在任何圖靈完備的機器中運行。編譯器是一種神奇的程序,能自動將代碼從復雜的語言轉換為簡單的語言。
操作系統
從本質上講,編譯后的計算機程序是CPU 指令的序列。如前所述,為臺式計算機編譯的代碼無法在智能手機中運行,因為二者采用不同的CPU體系結構。不過,由于程序必須與計算機的操作系統通信才能運行,編譯后的程序也可能無法在共享相同CPU 架構的兩臺計算機中使用。
為實現與外界的通信,程序必須進行輸入與輸出操作,如打開文件、在屏幕上顯示消息、打開網絡連接等。但不同的計算機采用不同的硬件,因此程序不可能直接支持所有不同類型的屏幕、聲卡或網卡。
這就是程序依賴于操作系統執行的原因所在。借助操作系統的幫助,程序可以毫不費力地使用不同的硬件。程序創建特殊的系統調用,請求操作系統執行所需的輸入/ 輸出操作。編譯器負責將輸入/ 輸出命令轉換為合適的系統調用。
然而,不同的操作系統往往使用互不兼容的系統調用。例如,與macOS或Linux 相比,Windows 在屏幕上打印信息所用的系統調用有所不同。
因此,在使用x86 處理器的Windows 中編譯的程序,無法在使用x86處理器的Mac 中運行。除針對特定的CPU 體系結構外,編譯后的代碼還會針對特定的操作系統。
編譯優化
優秀的編譯器致力于優化它們生成的機器碼。如果編譯器認為可以通過修改部分代碼來提高執行效率,則會處理。在生成二進制輸出之前,編譯器可能嘗試應用數百條優化規則。
因此,應使代碼易于閱讀以利于進行微優化。編譯器最終將完成所有細微的優化。例如,一些人對以下代碼頗有微詞。
function factorial(n)if n > 1return factorial(n - 1) * nelsereturn 1
他們認為應該進行以下修改:
function factorial(n)result ← 1while n > 1result ← result * nn ← n - 1return result
i ← x + y + 1j ← x + y
t1 ← x + yi ← t1 + 1j ← t1
對于時鐘頻率為1 GHz 的CPU,一個周期的持續時間約為十億分之一秒,這是光線從本書進入讀者眼中所需的時間。
在兩個面對面的人之間,聲波傳播需要大約10 微秒。
標準照片在大約4 毫秒內捕捉光線。
本文來自:電子工程世界
工程師必備
- 項目客服
- 培訓客服
- 平臺客服
TOP




















