程序环境——翻译环境与执行环境
本篇重點:
程序的翻譯環境和執行環境
在ANSI的任何一種實現中,存在兩個不同的環境。
?
1、翻譯環境
?
^ 組成一個程序的每個源文件通過編譯過程分別轉換成目標文件(object code)
^ 每個目標文件由鏈接器(linker)捆綁在一起,形成一個單一而完整的可執行程序(.exe)。
^ 鏈接器同時也會引入標準C函數庫中任何被該程序所用到的函數,而且它可以搜索程序員個人的程序庫,將其需要的函數也鏈接到程序中。
?
?
編譯+鏈接
我們把翻譯環境分為兩個部分,分別是編譯和鏈接。而編譯部分又可分為三個部分,分別是預編譯、編譯和匯編。
?
接下來我們就分別來看看這幾個階段。(Linux操作系統下演示)
?
預處理 ? (gcc test.c -E > test.i)
看這段代碼:
經過預處理后變成了這樣:
本來只有幾行的代碼變成了幾百行,是哪里變了呢?
1. #include包含的函數stdio.h顯示出來了。
2. 注釋被刪除了。?
3. #include符號替換了。 ?
這些就是預編譯階段所完成的內容。?
?
編譯 ? ? ??(gcc test.i -S)
經過編譯之后,代碼已經成這樣了:
已經把C語言代碼轉換為匯編代碼。
在轉換的過程中還要經歷下面這幾個內容:?
1.語法分析:
例
若是源代碼寫成這樣 #define MAX = 100,那么編譯時會報錯,報錯如下
2.詞法分析:判斷源程序中單詞符號的合法性。
3.語義分析:檢測例如類似于for循環有沒有使用錯誤。
4.符號匯總:(本例)g_val ?Add ?main 。 ?(后面來介紹符號匯總有什么用)
?
匯編 ? ? (gcc test.s -c)
把匯編代碼轉換成機器指令。
轉換過程中的內容:
形成符號表(readelf test.o -s):給每個匯總的符號一個地址。
?
鏈接
我們把源文件中的Add函數改成extern int Add(int x, int y),然后再創建一個新的源文件sum.c,內容如下圖,匯編后,Add會有一個地址。?
我們假設 ? sum.c中 ?Add地址是 ?0x100
? ? ? ? ? ? ? ? ?test.c中 ?Add ? ? ? ? ? ? 0x000 (無意義地址)
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?g_val ? ? ? ? ? 0x200
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? main ? ? ? ? ? ?0x300
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? printf ? ? ? ? ? 0x400
每個目標文件由鏈接器捆綁在一起,形成一個單一而完整的可執行程序。所以Add也將合并在一起,用有效的地址。即
所以鏈接過程中主要的操作有以下兩點:
1.符號表的合并和重定位。
2.合并段表。
?
以上就是翻譯環境的主要內容,為了方便記憶,給大家一幅圖來幫助記憶。
? ? ? ??
?
?
2、執行環境
程序執行的過程:
1. 程序必須載入內存中。在有操作系統的環境中:一般這個有操作系統完成。在獨立的環境中,程序的載入必須由手工安排,也可能是通過可執行代碼置入只讀內存來完成。
2. 程序的執行開始。接著便調用main函數。
3. 開始執行程序代碼。這個時候程序將使用一個運行時堆棧(stack),存儲函數的局部變量和返回地址。程序同時也可以使用靜態(static)內存,存儲在靜態內存中的變量在程序的整個執行過程一直保留他們的值。
4. 終止程序。正常終止main函數;也有可能是意外終止。
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的程序环境——翻译环境与执行环境的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 有关数组的运算 (sizeof)(str
- 下一篇: 实现strcpy