第8章 從源文件到可執行文件

源代碼完成後,就可以編譯生成可執行文件了。負責實現該功能的是編譯器。本章圍繞編譯器的功能,詳細介紹從程序編寫到運行爲止的流程。首先,看一下源文件是如何通過編譯轉化爲可執行文件的。接下來,我們會繼續關注可執行文件被加載到內存後的運行機制。此外,還會對程序運行時內存中的棧及堆進行說明。由於篇幅有限,本章只介紹了C語言編譯器來編寫Windows用的可執行文件(EXE文件),不過其他環境及編程語言基本上是同樣的機制。

8.1 計算機只能運行本地代碼

# include <windows.h>
# include <stdio.h>

//消息框的標題
char* title = "示例程序1"

// 返回兩個參數的平均值函數
double Average (double a, double b) {----------------------------------------(1)
    return (a + b) / 2
}

//程序啓動位置的函數
int WINAPI WinMain (HINSTANCE h, HINSTACE d,  LPSTR s, int m) {--------------(2)
    double ave;
    char buff[80];
	
	//求解123,456的平均值
	ave = Average(123, 456);
	
	//編寫顯示在消息框中的字符串
	sprintf(buff, "平均值 = %f", ave);---------------------------------------(3)

	//打開消息框
	MessageBox(NULL, buff, title, MB_OK);-----------------------------------(4)

	return 0;
}

類似於代碼清單8-1這樣,用某種編程語言編寫得程序就是源代碼,保存源代碼的文件稱爲源文件。源代碼是無法直接運行的,因爲CPU能直接解析並運行的不是源代碼而是本地代碼的程序。用任何編程語言編寫的代碼,最後都要翻譯成本地代碼(見下圖)。

8.2 本地代碼的內容

Windows中EXE文件的控制內容,使用的就是本地代碼。本地代碼的內容就是各種數值的羅列,而計算機就是把所有的信息作爲數值的集合來處理的。於此同時,計算機指令也是數值的羅列。

8.3 編譯器負責轉換源代碼

能夠把C語言等高級編程語言編寫的源代碼轉換成本地代碼的程序稱爲 編譯器。每個編寫源代碼的編程語言都需要其專用的編譯器。編譯器首先讀入代碼的內容,然後再把源代碼轉換成本地代碼。編譯器中就好像有一個源代碼同本地代碼的對應表。

根據CPU不同,本地代碼的類型也不同。因而,編譯器不僅和編程語言的種類有關,和CPU的類型也是相關的。編譯器的選擇有三大關鍵詞:

  1. 何種語言
  2. 用於哪種CPU
  3. 什麼環境下使用

8.4 僅靠編譯無法得到可執行文件

編譯器轉換爲源代碼後,就會生成本地文件。不過本地文件是無法直接運行的。爲了得到可以運行的EXE文件,編譯之後還需要進行“鏈接”處理。Borland C++編譯器是bcc32.exe

bcc32 -W -c Sample1.c

上面這條命令就是編譯Sample1.c的命令行命令。“-W -c”是用來指定編譯Windows用的程序的選項。編譯後生成的不是EXE文件,而是擴展名爲“.obj”的目標文件。雖然目標文件的內容是本地代碼,但卻無法直接運行。原因就是當前程序還處於未完成狀態。
(3)處sprintf()函數和(4)處的MessageBox()函數在源代碼中沒有記述這兩個函數的處理內容。sprintf()是通過指定格式把數值變換成字符串的函數,MessageBox()是消息框函數。源代碼中沒有記述這些函數的處理內容。因此,必須將這兩個函數的處理內容同Sample1.obj結合。

把多個目標文件結合,生成1個EXE文件的處理就是鏈接,運行鏈接的程序就稱爲連接器。Borland C++的鏈接器就是ilink32.exe工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章