下面深度講解C++中的大規模C++編譯器,C++編譯器具有很強的復雜性,並且源程序的行數也是非常多,所以,在進行C++編譯器編譯時,一定要定一個計劃表,這樣才能更好的對C++編譯器進行操作。
接著再跟著編譯運行的主線來分析它的源程序。下面先看一下簡單的C++例子,如下:
- #001 #include <stdio.h>
- #002
- #003 int main(void)
- #004 {
- #005 int nTest1 = 1;
- #006 int nTest2 = 2;
- #007 int nTest3;
- #008 int i;
- #009
- #010 nTest3 = nTest1 + nTest2;
- #011 printf("nTest3 = %d\r\n",nTest3);
- #012
- #013 for (i = 0; i < 5; i++)
- #014 {
- #015 printf("%d\r\n",nTest3+i);
- #016 }
- #017
- #018 printf(__TIME__" "__DATE__"\r\nhello world\n");
- #019 return 0;
- #020 }
- #021
上面的程序就是用來說明編譯器工作的例子,它在第一行裡包含了頭文件stdio.h,由於後面調用printf函數輸出顯示到屏幕裡。第二行空行,第三行是main函數,它是C程序的入口函數。在main函數裡,定義了幾個局部變量,分別第5,6,7,8行的變量。第10行作兩個變量nTest1和nTest2的加法,然後賦值給變量nTest3。第11行顯示變量nTest3的值,是用10進制輸出顯示。在第13到16行是5次輸出nTest3+i值。在第18行裡輸出編譯這個程序的時間和hello world的字符串。
C++編譯器的任務,就是把上面的源程序變換到匯編代碼輸出,或者變成其它中間代碼輸出。在這裡LCC編譯器是輸出匯編代碼的,所以就不介紹其它的中間代碼輸出。那麼LCC把上面的源程序變成什麼樣的匯編輸出呢?下面就先把它的目標代碼看一下,如下:
- #001 [global $main]
- #002 [section .text]
- #003 $main:
- #004 push ebx
- #005 push esi
- #006 push edi
- #007 push ebp
- #008 mov ebp, esp
- #009 sub esp, 16
- #010 mov dword [ebp + -12], 1
- #011 mov dword [ebp + -16], 2
- #012 mov edi, dword [ebp + -12]
- #013 mov esi, dword [ebp + -16]
- #014 lea edi, [esi + edi]
- #015 mov dword [ebp + -8], edi
- #016 mov edi, dword [ebp + -8]
- #017 push dword edi
- #018 lea edi, [$L2]
- #019 push dword edi
- #020 call $printf
- #021 add esp, 8
- #022 mov dword [ebp + -4], 0
- #023 $L3:
- #024 mov edi, dword [ebp + -8]
- #025 mov esi, dword [ebp + -4]
- #026 lea edi, [esi + edi]
- #027 push dword edi
- #028 lea edi, [$L7]
- #029 push dword edi
- #030 call $printf
- #031 add esp, 8
- #032 $L4:
- #033 inc dword [ebp + -4]
- #034 cmp dword [ebp + -4], 5
- #035 jl near $L3
- #036 lea edi, [$L8]
- #037 push dword edi
- #038 call $printf
- #039 add esp, 4
- #040 mov eax, 0
- #041 $L1:
- #042 mov esp, ebp
- #043 pop ebp
- #044 pop edi
- #045 pop esi
- #046 pop ebx
- #047 ret
- #048 [extern $printf]
- #049 [section .data]
- #050 times ($-$$) & 0 nop
- #051 $L8:
- #052 db '00:30:28 Apr 07 2007', 13, 10, 'hello world', 10, 0
- #053 times ($-$$) & 0 nop
- #054 $L7:
- #055 db '%d', 13, 10, 0
- #056 times ($-$$) & 0 nop
- #057 $L2:
- #058 db 'nTest3 = %d', 13, 10, 0
- #059
LCC是可以生成很多目標代碼的C++編譯器,在這裡主要介紹生成X86的NASM匯編的代碼。上面的匯編代碼就是NASM的匯編格式,可以使用NASM編譯生成目標文件,然後再用連接程序生成可執行文件。如果不能看懂上面的NASM匯編,就需要去看NASM手冊了,這個手冊在網上有下載。如果想更深入理解匯編生成機器碼的過程,當然也可以深入分析NASM的程序實現。
從上面的C++和匯編也可以看出,匯編代碼比C++代碼要復雜,行數也比較多,還分了數據段和代碼段。所以使用C++編譯器是可以大大地提高生產效率的,並且更容易理解,這樣就容易降低軟件的成本,容易開發大規模的軟件工程。