LCC編譯器的源程式分析 1 C編譯器的目標
阿新 • • 發佈:2018-12-23
先從簡單的目標來分析這個大規模的
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