C++ 編譯器將高級語言源碼翻譯為目標機器指令(或中間表示)。現代編譯器採用前端-中端-後端三階段架構:
// test.c
#include <stdio.h>
int main(void) {
int nTest1 = 1, nTest2 = 2, nTest3, i;
nTest3 = nTest1 + nTest2;
printf("nTest3 = %d\n", nTest3);
for (i = 0; i < 5; i++)
printf("%d\n", nTest3 + i);
printf(__TIME__ " " __DATE__ "\nhello world\n");
return 0;
}
使用 LCC 編譯器生成 x86 NASM 匯編(關鍵片段):
; 函數序言
$main:
push ebx; push esi; push edi; push ebp
mov ebp, esp
sub esp, 16 ; 分配棧幀空間
; 變量初始化
mov dword [ebp-12], 1 ; nTest1
mov dword [ebp-16], 2 ; nTest2
; nTest3 = nTest1 + nTest2
mov edi, [ebp-12]
mov esi, [ebp-16]
lea edi, [esi+edi] ; 加法
mov [ebp-8], edi ; 存 nTest3
; printf("nTest3 = %d\n", nTest3)
mov edi, [ebp-8]
push dword edi
lea edi, [$L2] ; 格式字符串地址
push dword edi
call $printf
add esp, 8
; for 循環
mov dword [ebp-4], 0 ; i = 0
$L3:
mov edi, [ebp-8]
mov esi, [ebp-4]
lea edi, [esi+edi] ; nTest3 + i
push dword edi
lea edi, [$L7] ; "%d\n"
push dword edi
call $printf
add esp, 8
$L4:
inc dword [ebp-4] ; i++
cmp dword [ebp-4], 5
jl near $L3 ; i < 5 跳轉
; 打印編譯時間與 hello world
lea edi, [$L8]
push dword edi
call $printf
add esp, 4
; 函數尾聲
mov eax, 0 ; 返回值
mov esp, ebp
pop ebp; pop edi; pop esi; pop ebx
ret
ebp 作為基址指針,局部變量用負偏移訪問。cdecl,參數右至左入棧,調用者清棧。.data 段,__TIME__/__DATE__ 編譯期展開。-O2 會展開循環、消除冗餘載入。| 編譯器 | 前端 | 中端 IR | 後端 | 特點 |
|---|---|---|---|---|
| GCC | C/C++/Fortran 等 | GIMPLE → RTL | 多目標 | 成熟、支持最全標準 |
| Clang/LLVM | Clang (C/C++/ObjC) | LLVM IR | LLVM 後端 | 模塊化、診斷優秀、易擴展 |
| MSVC | 自研 | 內部 IL | x86/x64/ARM | Windows 原生、PDB 調試最佳 |
| ICX (Intel) | Clang 基礎 | LLVM IR | LLVM + Intel 優化 | 數值計算極致優化 |
gcc -E / cl /Egcc -S -masm=intel / cl /FA /FAs-Werror / /WXCompiler Explorer (godbolt.org) 交互式對比輸出。