forked from chenzomi12/AISystem
-
Notifications
You must be signed in to change notification settings - Fork 0
/
03.srt
755 lines (567 loc) · 13.4 KB
/
03.srt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
1
00:00:00,000 --> 00:00:04,840
[字幕生成:BLACK 字幕校对:志宇]
2
00:00:04,840 --> 00:00:06,840
嗨大家好我是ZOMI
3
00:00:06,840 --> 00:00:10,120
今天我给大家汇报一个刺激而又古老
4
00:00:10,120 --> 00:00:15,280
硬核中又代言乏味的GCC编译过程和它的原理
5
00:00:15,280 --> 00:00:18,600
在上一节里面我已经给大家汇报过一个
6
00:00:18,600 --> 00:00:21,000
关于什么是编译器的一个概念
7
00:00:21,000 --> 00:00:23,800
编译器的树是高级语言
8
00:00:23,800 --> 00:00:26,840
输出是机器能够识别的二进字码
9
00:00:26,840 --> 00:00:29,840
中间的黑盒子叫做编译器
10
00:00:30,560 --> 00:00:33,040
RetroArts丹麦在1987年的时候
11
00:00:33,040 --> 00:00:36,360
基于GNU开发了一个GNU的编程套装
12
00:00:36,360 --> 00:00:38,360
简称叫做GCC
13
00:00:39,120 --> 00:00:41,880
在上一节里面已经详细的去展开
14
00:00:41,880 --> 00:00:44,720
讲讲GCC的一个历史的发展情况
15
00:00:44,720 --> 00:00:47,200
还有跟LLVM的相爱和相杀
16
00:00:47,720 --> 00:00:51,120
今天来看看GCC的一个具体的编译过程
17
00:00:51,120 --> 00:00:52,880
那在看编译过程之前
18
00:00:52,880 --> 00:00:55,200
了解一下它的主要特征
19
00:00:55,200 --> 00:00:57,680
主要特征我就简单的给大家练一下
20
00:00:57,680 --> 00:00:59,640
也就是照本宣科
21
00:01:00,040 --> 00:01:02,360
GCC是一个可移植的编译器
22
00:01:02,480 --> 00:01:03,280
就是个编译器
23
00:01:03,440 --> 00:01:05,240
然后支持多个平台
24
00:01:05,240 --> 00:01:08,120
第二个GCC不仅仅是一个本地的编译器
25
00:01:08,120 --> 00:01:09,480
而且还是跨平台
26
00:01:09,840 --> 00:01:12,000
交叉编译这个给我的印象很深的
27
00:01:12,000 --> 00:01:14,120
在我上大学08年的时候
28
00:01:14,120 --> 00:01:15,840
做飞思卡尔智能车
29
00:01:15,840 --> 00:01:17,840
当时候ZOMI就是基于X86
30
00:01:17,840 --> 00:01:19,680
把C语言编译成飞思卡尔
31
00:01:19,680 --> 00:01:22,120
这块MCU可以执行的二进字码
32
00:01:22,120 --> 00:01:24,600
那这种叫做跨平台交叉编译
33
00:01:24,600 --> 00:01:27,040
就是我在X86上面去编译
34
00:01:27,040 --> 00:01:28,800
另外芯片体系架构的
35
00:01:28,920 --> 00:01:29,920
二经济咨询
36
00:01:30,240 --> 00:01:33,400
另外GCC支持多种语言的前端
37
00:01:33,400 --> 00:01:37,200
例如C, C++, Swift, Java等不同的语言
38
00:01:37,400 --> 00:01:40,360
另外GCC进行了一个模块化的设计
39
00:01:40,360 --> 00:01:41,600
那这个模块化的设计
40
00:01:41,600 --> 00:01:43,680
其实可以保留一个问号
41
00:01:44,000 --> 00:01:45,600
因为GCC的模块化
42
00:01:45,600 --> 00:01:47,520
其实做的并不是很好
43
00:01:47,800 --> 00:01:49,320
最后一个就是GCC
44
00:01:49,440 --> 00:01:51,200
是一个开源自由的软件
45
00:01:51,200 --> 00:01:52,520
可以免费使用
46
00:01:52,520 --> 00:01:55,720
也就是对应到RetroStorm非常支持
47
00:01:56,000 --> 00:01:58,240
Free Software Foundation
48
00:01:59,800 --> 00:02:01,160
下面来看看
49
00:02:01,160 --> 00:02:03,560
GCC的一个整体的编译流程
50
00:02:03,560 --> 00:02:06,480
首先来讲一个基础的流程概念
51
00:02:06,480 --> 00:02:10,720
然后手把手的一起去实现这整套流程
52
00:02:10,720 --> 00:02:13,720
首先会把一些高级的语言作为输入
53
00:02:13,720 --> 00:02:15,200
然后给预处理
54
00:02:15,200 --> 00:02:17,400
预处理就会去生成.i文件
55
00:02:17,400 --> 00:02:19,400
接着需要对这些.i文件
56
00:02:19,520 --> 00:02:20,360
进行编译
57
00:02:20,360 --> 00:02:22,040
编译成.s的文件
58
00:02:22,040 --> 00:02:23,280
编译成.s的文件
59
00:02:23,280 --> 00:02:25,040
其实现在已经把它
60
00:02:25,040 --> 00:02:26,520
变成一个汇编程序了
61
00:02:26,520 --> 00:02:27,360
通过汇编器
62
00:02:27,680 --> 00:02:30,560
把.s文件从定向为目标的程序
63
00:02:30,560 --> 00:02:31,480
.o文件
64
00:02:31,480 --> 00:02:34,080
最后把一些需要依赖用到的链接
65
00:02:34,080 --> 00:02:34,960
打包进去
66
00:02:34,960 --> 00:02:37,160
形成了一个可执行的目标程序
67
00:02:37,640 --> 00:02:39,640
这就是GCC的整套流程
68
00:02:39,640 --> 00:02:41,520
现在来逐个打开看一看
69
00:02:41,760 --> 00:02:43,680
首先第一个就是预处理
70
00:02:43,800 --> 00:02:45,760
预处理的工作是非常多的
71
00:02:45,760 --> 00:02:47,240
包括宏定义文件定义
72
00:02:47,240 --> 00:02:48,560
还有条件编译
73
00:02:48,560 --> 00:02:49,440
预处理的过程
74
00:02:49,560 --> 00:02:51,960
还会删除程序当中的一些注释
75
00:02:51,960 --> 00:02:54,160
就是例如写了大量的文档注释
76
00:02:54,160 --> 00:02:56,400
为了方便自己人看
77
00:02:56,440 --> 00:02:57,760
为了坑兄弟
78
00:02:57,760 --> 00:02:59,240
然后多写了点注释
79
00:03:01,360 --> 00:03:04,600
另外还会去删掉一些空余的字符串
80
00:03:04,600 --> 00:03:06,960
预处理这个阶段都会把这些删除
81
00:03:06,960 --> 00:03:08,680
然后加上一些宏定义
82
00:03:08,680 --> 00:03:11,320
把宏定义文件全都包含在一起
83
00:03:11,320 --> 00:03:13,280
形成一个.i的文件
84
00:03:13,280 --> 00:03:15,280
下面来看看具体的操作
85
00:03:15,680 --> 00:03:18,160
首先创建一个hello.c文件
86
00:03:21,760 --> 00:03:25,640
把stu.dio.h头文件引进来
87
00:03:26,240 --> 00:03:27,680
定一个宏,hello world
88
00:03:38,760 --> 00:03:41,960
接着在组程序里面把hello world打印出来
89
00:03:55,800 --> 00:03:56,800
打开shell
90
00:04:03,160 --> 00:04:04,000
有个错误
91
00:04:04,000 --> 00:04:05,160
来修复一下
92
00:04:26,640 --> 00:04:27,640
下面的这些代码
93
00:04:27,640 --> 00:04:30,800
可以看到预处理将图文件包含进来了
94
00:04:30,800 --> 00:04:35,080
并且会将很多刚才定义的宏的定义进行替换
95
00:04:35,920 --> 00:04:40,040
543行已经把宏定义替换成为程序中的代码
96
00:04:40,040 --> 00:04:44,240
而537行就把程序里面的实际的stu.dio
97
00:04:44,240 --> 00:04:46,080
头文件的地址直接引进来了
98
00:04:48,440 --> 00:04:49,520
到了编译的阶段
99
00:04:49,520 --> 00:04:53,440
编译器会将预先处理好的.i文件进行替换
100
00:04:53,440 --> 00:04:56,840
将预先处理好的.i文件进行一些语法分析
101
00:04:56,840 --> 00:04:57,840
词法分析
102
00:04:57,840 --> 00:04:59,640
还有一些大量的优化
103
00:04:59,640 --> 00:05:03,840
在优化之后就会生成对应的汇编代码
104
00:05:05,040 --> 00:05:07,040
下面来具体看看怎么执行的
105
00:05:08,720 --> 00:05:10,520
接下来执行编译的过程
106
00:05:11,400 --> 00:05:13,520
不要看编译的过程只是一行命令
107
00:05:13,520 --> 00:05:16,320
实际上编译的过程是最复杂最漫长的
108
00:05:17,000 --> 00:05:17,960
当程序越大
109
00:05:18,200 --> 00:05:20,400
整个编译的流程就会变得非常的长
110
00:05:23,640 --> 00:05:28,640
编译完之后
111
00:05:28,640 --> 00:05:32,440
可以看到Hello.s文件里面全都是汇编指令
112
00:05:32,440 --> 00:05:35,040
这个时候就说明已经编译成功了
113
00:05:39,040 --> 00:05:39,840
在汇编阶段
114
00:05:40,040 --> 00:05:42,840
就会把刚才生成的汇编代码
115
00:05:42,840 --> 00:05:45,440
逐行的翻译成机器语言
116
00:05:45,440 --> 00:05:47,440
机器指令或者二进字码
117
00:05:47,440 --> 00:05:50,240
现在来看看具体的二进字码有什么不一样
118
00:05:50,240 --> 00:05:53,040
二进字码实现的过程当中也是有点特别的
119
00:05:53,440 --> 00:06:12,440
下面用od-b hello.o来看看
120
00:06:13,840 --> 00:06:16,440
这个二进字文件的八进字表示
121
00:06:16,440 --> 00:06:18,640
二进字实际是0101
122
00:06:18,640 --> 00:06:21,640
现在把它变成一个八进字进行查看
123
00:06:24,440 --> 00:06:26,840
在最后一个阶段就是链接
124
00:06:26,840 --> 00:06:27,840
链接这个阶段
125
00:06:27,840 --> 00:06:30,840
会把程序所要用到的所有的目标文件
126
00:06:30,840 --> 00:06:33,240
还有相对应依赖的系统的库
127
00:06:33,240 --> 00:06:34,240
都打包起来
128
00:06:34,240 --> 00:06:36,440
变成一个可执行的文件
129
00:06:36,440 --> 00:06:38,240
这个文件就可以马上去执行
130
00:06:38,240 --> 00:06:40,040
也可以存放在磁盘当中
131
00:06:40,040 --> 00:06:41,240
下一次调用的时候
132
00:06:41,240 --> 00:06:42,840
就可以去执行了
133
00:06:42,840 --> 00:06:44,040
等我想到想用的时候
134
00:06:44,040 --> 00:06:46,040
我就可以从磁盘里面调出来
135
00:06:46,040 --> 00:06:47,240
然后去使用了
136
00:06:53,440 --> 00:07:18,840
诶 宗明老师我这里面有一个疑问
137
00:07:18,840 --> 00:07:21,240
刚才不是说编译器分成三个阶段
138
00:07:21,240 --> 00:07:22,640
一个是前端优化
139
00:07:22,640 --> 00:07:23,840
一个是后端
140
00:07:23,840 --> 00:07:27,840
为什么GCC它变成四五个阶段呢
141
00:07:27,840 --> 00:07:30,040
诶 这位同学上课非常认真的
142
00:07:30,040 --> 00:07:32,040
虽然这位同学还是我
143
00:07:32,040 --> 00:07:34,040
在GCC里面所谓的预处理
144
00:07:34,040 --> 00:07:36,240
就是对应到编译器的前端
145
00:07:36,240 --> 00:07:39,440
而编译的过程就是整个优化的过程
146
00:07:39,440 --> 00:07:41,440
后端就是对应汇编
147
00:07:41,440 --> 00:07:43,240
还有链接的过程
148
00:07:43,240 --> 00:07:45,840
这里面实际上是有明确的边界的
149
00:07:45,840 --> 00:07:48,240
只是GCC的定义
150
00:07:48,240 --> 00:07:51,040
跟编译器通用的定义有一些差别
151
00:07:51,040 --> 00:07:52,040
但是总体来说
152
00:07:52,040 --> 00:07:56,440
还是遵照整个编译器的基本构成体系来去展开的
153
00:07:56,440 --> 00:07:58,440
最后看看GCC的一些好处
154
00:07:58,440 --> 00:07:59,840
再看看它的坏处
155
00:07:59,840 --> 00:08:01,240
通过了解这些坏处
156
00:08:01,240 --> 00:08:04,440
大家就会知道为什么会诞生LLVM了
157
00:08:04,440 --> 00:08:07,240
第一个GCC支持非常多的不同的语言
158
00:08:07,240 --> 00:08:10,240
第二个是它支持多平台可以进行交叉编译
159
00:08:10,240 --> 00:08:12,240
第三个GCC比较流行
160
00:08:12,240 --> 00:08:17,240
所有的Linux的系统都会广泛的去用到或者绑架
161
00:08:18,240 --> 00:08:22,440
最后一个就是GCC是基于C语言进行编译的
162
00:08:22,440 --> 00:08:24,040
它不需要C++编译器
163
00:08:24,040 --> 00:08:26,240
也就是说它非常的原始或者难易
164
00:08:26,240 --> 00:08:28,840
下面看看它的坏处
165
00:08:28,840 --> 00:08:30,840
坏处其实还是挺多的
166
00:08:30,840 --> 00:08:33,640
第一个就是GCC的代码的偶合度非常高
167
00:08:33,640 --> 00:08:35,040
代码偶合度非常高
168
00:08:35,040 --> 00:08:38,640
就意味着它很难进行独立或者模块化拆分
169
00:08:38,640 --> 00:08:41,440
例如Apple之前就提到了一个要求
170
00:08:41,440 --> 00:08:45,840
就是希望能够把GCC集成到它的S-Code IDE上面
171
00:08:45,840 --> 00:08:49,240
但是因为GCC没有进行很好的模块化
172
00:08:49,240 --> 00:08:53,040
所以在IDE上面去调用GCC其实是比较困难的
173
00:08:53,040 --> 00:08:56,840
第二个就是GCC被构造成一个单一的静态编译器
174
00:08:56,840 --> 00:08:59,040
就是你可以整体的去使用它
175
00:08:59,040 --> 00:09:03,240
但是很难把它作为API集成到你想要的工具
176
00:09:03,240 --> 00:09:06,040
第三个就有点历史的那味儿
177
00:09:06,040 --> 00:09:08,440
GCC发展了35年了
178
00:09:08,440 --> 00:09:12,040
越到后期的版本代码的质量就越差
179
00:09:12,040 --> 00:09:14,640
最后一个也是最致命的一条
180
00:09:14,840 --> 00:09:18,040
GCC已经有15000多行代码
181
00:09:18,040 --> 00:09:20,440
核心的代码有500多万行
182
00:09:20,440 --> 00:09:23,040
是现存最大的自由软件
183
00:09:23,040 --> 00:09:24,840
看着这个数说实话
184
00:09:24,840 --> 00:09:26,440
虽然它开源
185
00:09:26,440 --> 00:09:29,440
但是估计我不会随便的去把它下载下来
186
00:09:29,440 --> 00:09:32,040
或者随便的打开它的代码来看
187
00:09:32,040 --> 00:09:34,240
因为一看人都傻了
188
00:09:34,240 --> 00:09:35,440
基于这些缺点
189
00:09:35,440 --> 00:09:39,640
将会在下一节里面去分享LLVM的到来