本系列記錄從零構建 TC2.0 編譯環境、探究編譯鏈接流程、驗證記憶體模型,到解析函數地址與變量存儲的真實機制。旨在透過動手實驗,建立對 C 語言底層運行模型的直觀理解。
從 TC2.0 安裝目錄提取核心檔案:
TCC.EXE - 編譯器TLINK.EXE - 連結器C0S.OBJ - 啟動代碼CS.LIB, EMU.LIB, MATHS.LIB - 標準庫將上述檔案置於同一目錄 (如 C:\C),即可獨立編譯連結。實驗證明:
TCC 內部自動調用 TLINK 完成連結TLINK 會導致連結失敗,確認其被 TCC 呼叫TLINK 可將單獨的 .OBJ 連結為 .EXETC2.0 Small Model 特性:
驗證程式:
#include
void f1() { int a=1; }
void f2() { int b=2; }
int main() {
printf("CS=%X DS=%X SS=%X\n", _CS, _DS, _SS);
printf("f1=%p f2=%p\n", f1, f2);
return 0;
}
結果顯示 DS == SS,CS 不同,印證 Small Model 記憶體佈局。函數名直接作為地址常量使用 (如 printf("%p", f1)) 可正常編譯輸出入口偏移地址。
&func 或函數名 func 取得 (近指標,16 位)_CS 讀取
// 顯示 CS 段地址
printf("CS = %X\n", _CS); // TC2.0 偽變量
// 或內嵌彙編
asm { mov ax, cs; mov [cs_val], ax; }
實驗發現:直接在 CMD 執行 .EXE 與在 DEBUG 載入執行時的 CS 值不同,因 DEBUG 會將程式載入固定段地址。
初步觀察到區域變量地址顯示為負值 (如 -28),後經驗證:
%d 格式輸出時,實為相對於當前堆疊頂 (SP) 的有號偏移量。實際地址 = SS:SP + 偏移量重要修正:原筆記結論有誤。使用 %p 或 %x 可見區域變量真實偏移地址為正值 (如 0xFFE4)。負值現象源於 %d 將無號 16 位值解釋為有號整數。區域變量地址本質仍是堆疊段內的偏移量,非相對位置編碼。
建議大一新生先啃完 K&R 並上機完成所有習題,再進階算法與資料結構。