計算機系統->Hello World的一生 | 程序如何運行


2021年11月27日准備發在基地微信公眾號上的推文。

綜合了多篇大佬的博客,以及自己已經知道的知識,對一些疑惑進行了現階段我認為還算滿意的解答。

不過又產生了很多疑問:

  1. 內存和磁盤的關系
  2. CPU是如何運行機器指令的(雖然大概想過去會是數字邏輯上的電路的組合)
  3. ......

========================================================================================================================================

我寫的上一篇推文是:Vscode里的多文件編譯,本來這一篇計划是多語言混編,可是還沒玩太明白,就來補充講一講程序的運行過程,對上一篇也是一種補充。

當我們要讓一個程序運行起來,如下面這段代碼:

1 #include <stdio.h>
2 int main()
3 {
4     printf("Hello World\n");
5     return 0;
6 }

需要以下過程:

1. 預處理

 gcc -E hello.c -o hello.i 

這一過程主要是處理源代碼文件中:

  • 以”#”開始的預編譯指令

    如”#include”、”#define”等

    將include的文件插入進來,將所有define的宏定義展開。

  • 刪除注釋

  • 添加行號和文件名標識。

    以便編譯時編譯器產生調試用的行號信息及用於編譯時產生編譯錯誤或警告時能夠顯示行號

2. 編譯

 gcc -S hello.i -o hello.s 

編譯程序(Compiler)把預處理完的文件進行一系列詞法分析、語法分析、語義分析及優化后生產相應的匯編代碼文件。

當然,預處理和編譯可以合二為一,直接一步到位:

 1 gcc -S hello.c -o hello.s 

這里提一下這個gcc,這只是后台編譯程序(compiler)的控制台,會根據不同參數去調用不同的預處理、編譯程序,來處理不同的語言。

3. 匯編

 1 gcc -c hello.c -o hello.o 

.o文件就是“目標文件”(Object File),將匯編語句轉換為機器語言,機器語言是CPU可以執行的命令。

4. 鏈接

在上面的過程中,原本的一個文件會生成若干個目標模塊,這些模塊是割裂的。

由鏈接程序(Linker)將這些目標模塊(程序段),以及它們所需要的庫函數鏈接在一起,形成一個完整的裝入模塊(Load Module);這是完整的執行命令的可執行文件exe(此時已經是二進制文件)。

鏈接分為靜態鏈接和動態鏈接。不展開了。

DLL文件就是Dynamic Link Library文件.

5. 裝入

可執行文件只有裝載到內存以后才能被CPU執行。

裝入過程就是由裝入程序(Loader)將裝入模塊裝入物理內存。物理內存就是真實存在的內存條。

物理內存是由若干個存儲單元組成的,每個存儲單元有一個編號,這種編號可唯一標識一個存儲單元,稱為內存地址(或物理地址)。

可以簡單理解成類數組的一個結構。

這個過程進行了地址重定位,主要是將邏輯地址轉換成物理內存的絕對地址(相當於拿考號找座位)。這個過程只有在程序將要被運行的時候才會發生。

圖片

6. 執行

執行不是一個嚴格的概念,只是我用來描述裝入到輸出“Hello World”這個過程的一個名詞。

當計算機要運行該程序時,二進制文件中相關的指令會發送給CPU,經過CPU的操作,顯示到了顯示器上。

7. GCC

補充GCC的工具鏈

img

8 復習

  1. 程序從按下“編譯”到裝入內存需要哪些過程?
  2. GCC工具鏈有哪些?

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM