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。