1. 程式人生 > >LCC編譯器的源程式分析 1 C編譯器的目標

LCC編譯器的源程式分析 1 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 編譯器是可以大大地提高生產效率的,並且更容易理解,這樣就容易降低軟體的成本,容易開發大規模的軟體工程。    

再分享一下我老師大神的人工智慧教程吧。零基礎!通俗易懂!風趣幽默!還帶黃段子!希望你也加入到我們人工智慧的隊伍中來!https://www.cnblogs.com/captainbed