1 00:00:07,200 --> 00:00:09,100 [Powered by Google Translate] ROB BOWDEN:讓我們談談編譯器。 2 00:00:09,100 --> 00:00:11,490 直到此時,你剛剛打完了你的源代碼 3 00:00:11,490 --> 00:00:14,260 一些文件,送他們通過這個大黑盒子, 4 00:00:14,260 --> 00:00:16,890 鐺,和你的可執行文件,它出來 5 00:00:16,890 --> 00:00:19,430 正是你寫在你的源代碼。 6 00:00:19,430 --> 00:00:22,170 神奇的,我們要仔細 7 00:00:22,170 --> 00:00:23,590 看看實際上發生了什麼 8 00:00:23,590 --> 00:00:25,220 當我們編譯的文件。 9 00:00:25,220 --> 00:00:28,580 所以,這是什麼意思編譯的東西嗎? 10 00:00:28,580 --> 00:00:31,150 >> 那麼,在最一般的意義上說,它只是意味著 11 00:00:31,150 --> 00:00:32,580 轉換代碼寫在一 12 00:00:32,580 --> 00:00:34,680 編程語言到另一個。 13 00:00:34,680 --> 00:00:37,550 但是,通常當人們說他們編譯的東西,他們 14 00:00:37,550 --> 00:00:39,660 意思是,他們把它從一個高級編程 15 00:00:39,660 --> 00:00:42,460 語言來編程語言的一個較低的水平。 16 00:00:42,460 --> 00:00:44,960 這些可能看起來很主觀的。 17 00:00:44,960 --> 00:00:48,090 例如,您可能沒有想到C為高 18 00:00:48,090 --> 00:00:51,440 高級編程語言,但你編譯它。 19 00:00:51,440 --> 00:00:52,730 但是,它是相對的。 20 00:00:52,730 --> 00:00:55,790 正如我們將要看到的,彙編代碼,並最終機 21 00:00:55,790 --> 00:00:59,270 ,我們編譯的代碼無疑是一個較低的水平 22 00:00:59,270 --> 00:01:00,700 比C 23 00:01:00,700 --> 00:01:03,310 雖然我們將使用鏘在今天的演示, 24 00:01:03,310 --> 00:01:06,360 很多的想法在這裡進行其他的編譯器。 25 00:01:06,360 --> 00:01:09,160 >> 鐺,有四個主要步驟的整體 26 00:01:09,160 --> 00:01:10,200 編譯。 27 00:01:10,200 --> 00:01:15,430 這些,預處理,通過預處理器; 2, 28 00:01:15,430 --> 00:01:19,530 編譯,由編譯器完成;三,組裝 29 00:01:19,530 --> 00:01:22,010 由彙編程序完成;和四個 30 00:01:22,010 --> 00:01:24,640 連接的連接器。 31 00:01:24,640 --> 00:01:27,600 這可能會造成混淆的整體的一個的子步驟 32 00:01:27,600 --> 00:01:30,980 鏘編譯器被稱為編譯器,但 33 00:01:30,980 --> 00:01:32,530 我們會得到。 34 00:01:32,530 --> 00:01:35,050 我們的例子中,我們將使用一個簡單的Hello World程序 35 00:01:35,050 --> 00:01:36,270 此視頻。 36 00:01:36,270 --> 00:01:38,380 讓我們一起來看看。 37 00:01:38,380 --> 00:01:40,330 >> 第一個步驟是預處理。 38 00:01:40,330 --> 00:01:42,520 預處理器做什麼? 39 00:01:42,520 --> 00:01:45,560 在幾乎每一個你曾經讀或寫C程序, 40 00:01:45,560 --> 00:01:48,310 你已經開始用哈希的代碼行。 41 00:01:48,310 --> 00:01:51,730 我把它叫做哈希,但您也可以撥打磅,數 42 00:01:51,730 --> 00:01:53,280 簽署,或尖銳。 43 00:01:53,280 --> 00:01:56,840 任何這樣的行預處理器指令。 44 00:01:56,840 --> 00:02:00,650 #define和#include之前,你可能已經看到,但有 45 00:02:00,650 --> 00:02:03,690 有幾個預處理器能夠識別。 46 00:02:03,690 --> 00:02:07,340 讓我們添加一個#define我們的Hello World的例子。 47 00:02:07,340 --> 00:02:11,690 現在讓我們運行預處理程序,這個文件。 48 00:02:11,690 --> 00:02:16,150 你通過clage-E標誌,指示它運行 49 00:02:16,150 --> 00:02:17,880 只是預處理器。 50 00:02:17,880 --> 00:02:19,130 讓我們看看會發生什麼。 51 00:02:22,250 --> 00:02:24,020 它看起來像鏘剛剛吐出來的一切 52 00:02:24,020 --> 00:02:25,200 在命令行中。 53 00:02:25,200 --> 00:02:27,800 為了保存這個輸出到一個新文件 54 00:02:27,800 --> 00:02:33,850 hello2.c,我們將追加> hello2.c對我們的命令。 55 00:02:33,850 --> 00:02:37,800 現在,讓我們來看看在我們的預處理文件。 56 00:02:37,800 --> 00:02:40,810 >> 哇,那發生在我們短暫的小程序? 57 00:02:40,810 --> 00:02:43,890 如果我們去這個文件的底部,我們可以看到 58 00:02:43,890 --> 00:02:46,070 一些我們寫的代碼。 59 00:02:46,070 --> 00:02:49,800 請注意,在#define消失了,所有實例的名稱 60 00:02:49,800 --> 00:02:51,950 正是我們所指定的已被取代 61 00:02:51,950 --> 00:02:53,590 #define行。 62 00:02:53,590 --> 00:02:56,530 那麼,什麼是所有這些類型定義和函數聲明 63 00:02:56,530 --> 00:02:58,140 在上面的文件嗎? 64 00:02:58,140 --> 00:03:00,820 請注意的#define是不是唯一的預處理 65 00:03:00,820 --> 00:03:02,390 指令,我們指定。 66 00:03:02,390 --> 00:03:05,280 我們還包括stdio.h中。 67 00:03:05,280 --> 00:03:09,560 因此,所有的瘋狂線實際上只是stdio.h中複製 68 00:03:09,560 --> 00:03:11,810 並粘貼到該文件的頂部。 69 00:03:11,810 --> 00:03:14,110 這就是為什麼頭文件非常有用的功能 70 00:03:14,110 --> 00:03:15,160 聲明。 71 00:03:15,160 --> 00:03:17,740 而不需要複製和粘貼的功能 72 00:03:17,740 --> 00:03:21,050 聲明您打算使用在文件的開頭, 73 00:03:21,050 --> 00:03:22,990 預處理器將其複製並粘貼的標頭 74 00:03:22,990 --> 00:03:24,140 文件為您。 75 00:03:24,140 --> 00:03:26,480 >> 現在,我們已經完成了預處理,我們移動到 76 00:03:26,480 --> 00:03:27,680 編譯。 77 00:03:27,680 --> 00:03:30,725 我們所說的這一步編譯的原因是因為這是 78 00:03:30,725 --> 00:03:34,130 鐺的步驟實際上是從C編譯 79 00:03:34,130 --> 00:03:35,370 彙編代碼。 80 00:03:35,370 --> 00:03:38,280 為了鐺編譯文件集會,但 81 00:03:38,280 --> 00:03:42,030 繼續沒有進一步的,通過-S標誌 82 00:03:42,030 --> 00:03:43,560 在命令行中。 83 00:03:43,560 --> 00:03:44,790 讓我們來看看在大會上 84 00:03:44,790 --> 00:03:47,390 文件輸出。 85 00:03:47,390 --> 00:03:49,740 它看起來像一個完全不同的語言。 86 00:03:49,740 --> 00:03:52,660 彙編代碼是非常特定的處理器。 87 00:03:52,660 --> 00:03:55,440 在這種情況下,由於CS50的設備上運行的 88 00:03:55,440 --> 00:04:00,470 虛擬x86處理器,這是x86彙編代碼。 89 00:04:00,470 --> 00:04:03,450 很少有人直接寫在彙編代碼,這些天, 90 00:04:03,450 --> 00:04:06,490 但你寫的每一個C程序被轉化 91 00:04:06,490 --> 00:04:07,940 成彙編。 92 00:04:07,940 --> 00:04:11,440 同樣,我們稱這個步驟的C編譯成彙編 93 00:04:11,440 --> 00:04:14,170 從一個更高的水平,因為我們要到一個較低的水平 94 00:04:14,170 --> 00:04:15,480 編程語言。 95 00:04:15,480 --> 00:04:17,880 >> 是什麼使裝配較低的水平比C? 96 00:04:17,880 --> 00:04:21,660 那麼,組裝,我們都非常有限,我們能做些什麼。 97 00:04:21,660 --> 00:04:25,120 有沒有如果,是,是,或任何形式的循環。 98 00:04:25,120 --> 00:04:27,560 但是你可以完成同樣的事情,這些控制 99 00:04:27,560 --> 00:04:30,270 結構提供了利用有限的操作, 100 00:04:30,270 --> 00:04:32,350 裝配提供。 101 00:04:32,350 --> 00:04:35,960 但要看到確實是低層次的裝配是如何,讓我們去 102 00:04:35,960 --> 00:04:39,320 在我們編譯了一步,組裝。 103 00:04:39,320 --> 00:04:41,890 這是彙編器的工作轉換的彙編代碼 104 00:04:41,890 --> 00:04:44,740 成目標代碼或機器代碼。 105 00:04:44,740 --> 00:04:47,610 請記住,彙編程序不輸出組件; 106 00:04:47,610 --> 00:04:51,080 更確切地說,它需要在組件和輸出機器代碼。 107 00:04:51,080 --> 00:04:54,040 機器代碼是1和0的實際,CPU可以 108 00:04:54,040 --> 00:04:57,290 明白了,雖然我們仍然有一點點離開工作 109 00:04:57,290 --> 00:04:59,380 之前,我們可以運行我們的程序。 110 00:04:59,380 --> 00:05:01,400 讓我們來組裝我們的彙編代碼通過 111 00:05:01,400 --> 00:05:04,080 。鏗鏘-C標誌。 112 00:05:04,080 --> 00:05:06,410 現在,讓我們來看看什麼在組裝的文件。 113 00:05:06,410 --> 00:05:09,220 >> 嗯,這不幫助我們非常感謝。 114 00:05:09,220 --> 00:05:11,340 請記住,機器代碼的和零 115 00:05:11,340 --> 00:05:13,240 您的計算機可以理解的。 116 00:05:13,240 --> 00:05:16,080 這並不意味著它容易讓我們理解。 117 00:05:16,080 --> 00:05:19,160 那麼究竟如何低電平組裝? 118 00:05:19,160 --> 00:05:21,480 這是幾乎相同的目標代碼。 119 00:05:21,480 --> 00:05:24,300 從組裝到目標代碼是更是一個 120 00:05:24,300 --> 00:05:27,540 翻譯不是轉型,這就是為什麼 121 00:05:27,540 --> 00:05:29,310 人們可能不考慮彙編 122 00:05:29,310 --> 00:05:31,400 做任何實際編譯。 123 00:05:31,400 --> 00:05:34,110 事實上,這是很容易的手動翻譯 124 00:05:34,110 --> 00:05:36,050 組裝成機器代碼。 125 00:05:36,050 --> 00:05:39,040 在裝配的主要功能,即第一行 126 00:05:39,040 --> 00:05:42,100 恰好對應為十六進制的0x55的。 127 00:05:42,100 --> 00:05:45,470 在二進制中,這是1010101。 128 00:05:45,470 --> 00:05:49,300 第二行恰好對應十六進制的0x895。 129 00:05:49,300 --> 00:05:51,290 而接下來,0X56。 130 00:05:51,290 --> 00:05:53,730 給定一個相對簡單的表格,你可以翻譯 131 00:05:53,730 --> 00:05:57,130 的代碼組裝成機器可以理解太。 132 00:05:57,130 --> 00:05:58,810 >> 因此,有一個剩餘的步驟 133 00:05:58,810 --> 00:06:01,150 編譯,鏈接。 134 00:06:01,150 --> 00:06:04,530 一堆鏈接結合成一個大文件的目標文件 135 00:06:04,530 --> 00:06:06,380 實際上,你可以執行。 136 00:06:06,380 --> 00:06:08,570 鏈接是非常依賴於系統。 137 00:06:08,570 --> 00:06:11,030 所以最簡單的方式來獲得鐺只是鏈接對象 138 00:06:11,030 --> 00:06:13,920 文件在一起是調用的鐺上所有的文件 139 00:06:13,920 --> 00:06:15,190 你想連接到一起。 140 00:06:15,190 --> 00:06:18,740 如果您指定的o文件,然後將需要重新處理, 141 00:06:18,740 --> 00:06:21,680 編譯和裝配所有的源代碼。 142 00:06:21,680 --> 00:06:23,960 讓我們把一個數學函數到我們的文件,所以我們必須 143 00:06:23,960 --> 00:06:25,210 東西進行連接。 144 00:06:34,220 --> 00:06:37,010 現在讓我們來編譯它回落到目標代碼和 145 00:06:37,010 --> 00:06:38,260 叫鐺就可以了。 146 00:06:40,560 --> 00:06:41,420 哎呀。 147 00:06:41,420 --> 00:06:43,790 由於我們的數學函數,我們需要鏈接 148 00:06:43,790 --> 00:06:46,610 數學庫使用-lm。 149 00:06:46,610 --> 00:06:48,990 >> 如果我們想聯繫到一起一堆。o文件,我們 150 00:06:48,990 --> 00:06:51,420 寫我們自己的,我們只是指定所有這些在 151 00:06:51,420 --> 00:06:52,460 命令行。 152 00:06:52,460 --> 00:06:55,320 該限制是,只有一個,這些文件 153 00:06:55,320 --> 00:06:57,790 指定一個主函數,否則, 154 00:06:57,790 --> 00:06:59,930 生成的可執行文件,不知道從哪裡開始 155 00:06:59,930 --> 00:07:00,910 運行你的代碼。 156 00:07:00,910 --> 00:07:03,360 指定的文件鏈接之間的區別是什麼 157 00:07:03,360 --> 00:07:06,600 與-l,只是直接指定一個文件? 158 00:07:06,600 --> 00:07:07,440 什麼也沒有。 159 00:07:07,440 --> 00:07:09,850 這是剛剛發生,鐺確切地知道什麼文件 160 00:07:09,850 --> 00:07:12,560 類似LM發生來稱呼。 161 00:07:12,560 --> 00:07:14,700 如果你知道自己該文件,你可以指定它 162 00:07:14,700 --> 00:07:15,930 明確。 163 00:07:15,930 --> 00:07:18,990 請記住,所有的-l標誌來結束時 164 00:07:18,990 --> 00:07:20,770 你的客戶需求。 165 00:07:20,770 --> 00:07:22,300 >> 而這一切就是這麼簡單。 166 00:07:22,300 --> 00:07:24,940 當你剛剛運行鐺上的一些文件,這是它的 167 00:07:24,940 --> 00:07:26,350 其實這樣做。 168 00:07:26,350 --> 00:07:29,490 我的名字是羅布·波頓,這是CS50。