-
Notifications
You must be signed in to change notification settings - Fork 154
/
Copy path1.1.html
1187 lines (670 loc) · 80.1 KB
/
1.1.html
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
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!DOCTYPE HTML>
<html lang="" >
<head>
<meta charset="UTF-8">
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<title>在开始愉快的PA之旅之前 · GitBook</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="description" content="">
<meta name="generator" content="GitBook 3.2.3">
<link rel="stylesheet" href="gitbook/style.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-intopic-toc/style.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-page-footer-ex/style/plugin.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-callouts/plugin.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-highlight/website.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-search/search.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-fontsettings/website.css">
<link rel="stylesheet" href="gitbook/gitbook-plugin-theme-comscore/test.css">
<link rel="stylesheet" href="styles.css">
<meta name="HandheldFriendly" content="true"/>
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="gitbook/images/apple-touch-icon-precomposed-152.png">
<link rel="shortcut icon" href="gitbook/images/favicon.ico" type="image/x-icon">
<link rel="next" href="1.2.html" />
<link rel="prev" href="PA1.html" />
</head>
<body>
<div class="book">
<div class="book-summary">
<div id="book-search-input" role="search">
<input type="text" placeholder="Type to search" />
</div>
<nav role="navigation">
<ul class="summary">
<li class="chapter " data-level="1.1" data-path="index.html">
<a href="index.html">
Introduction
</a>
</li>
<li class="chapter " data-level="1.2" data-path="PA0.html">
<a href="PA0.html">
PA0 - 世界诞生的前夜: 开发环境配置
</a>
<ul class="articles">
<li class="chapter " data-level="1.2.1" data-path="0.1.html">
<a href="0.1.html">
Installing GNU/Linux
</a>
</li>
<li class="chapter " data-level="1.2.2" data-path="0.2.html">
<a href="0.2.html">
First Exploration with GNU/Linux
</a>
</li>
<li class="chapter " data-level="1.2.3" data-path="0.3.html">
<a href="0.3.html">
Installing Tools
</a>
</li>
<li class="chapter " data-level="1.2.4" data-path="0.4.html">
<a href="0.4.html">
Configuring vim
</a>
</li>
<li class="chapter " data-level="1.2.5" data-path="0.5.html">
<a href="0.5.html">
More Exploration
</a>
</li>
<li class="chapter " data-level="1.2.6" data-path="0.6.html">
<a href="0.6.html">
Getting Source Code for PAs
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.3" data-path="PA1.html">
<a href="PA1.html">
PA1 - 开天辟地的篇章: 最简单的计算机
</a>
<ul class="articles">
<li class="chapter active" data-level="1.3.1" data-path="1.1.html">
<a href="1.1.html">
在开始愉快的PA之旅之前
</a>
</li>
<li class="chapter " data-level="1.3.2" data-path="1.2.html">
<a href="1.2.html">
开天辟地的篇章
</a>
</li>
<li class="chapter " data-level="1.3.3" data-path="1.3.html">
<a href="1.3.html">
RTFSC
</a>
</li>
<li class="chapter " data-level="1.3.4" data-path="1.4.html">
<a href="1.4.html">
基础设施
</a>
</li>
<li class="chapter " data-level="1.3.5" data-path="1.5.html">
<a href="1.5.html">
表达式求值
</a>
</li>
<li class="chapter " data-level="1.3.6" data-path="1.6.html">
<a href="1.6.html">
监视点
</a>
</li>
<li class="chapter " data-level="1.3.7" data-path="1.7.html">
<a href="1.7.html">
如何阅读手册
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.4" data-path="PA2.html">
<a href="PA2.html">
PA2 - 简单复杂的机器: 冯诺依曼计算机系统
</a>
<ul class="articles">
<li class="chapter " data-level="1.4.1" data-path="2.1.html">
<a href="2.1.html">
不停计算的机器
</a>
</li>
<li class="chapter " data-level="1.4.2" data-path="2.2.html">
<a href="2.2.html">
RTFSC(2)
</a>
</li>
<li class="chapter " data-level="1.4.3" data-path="2.3.html">
<a href="2.3.html">
程序, 运行时环境与AM
</a>
</li>
<li class="chapter " data-level="1.4.4" data-path="2.4.html">
<a href="2.4.html">
基础设施(2)
</a>
</li>
<li class="chapter " data-level="1.4.5" data-path="2.5.html">
<a href="2.5.html">
输入输出
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.5" data-path="PA3.html">
<a href="PA3.html">
PA3 - 穿越时空的旅程: 批处理系统
</a>
<ul class="articles">
<li class="chapter " data-level="1.5.1" data-path="3.1.html">
<a href="3.1.html">
最简单的操作系统
</a>
</li>
<li class="chapter " data-level="1.5.2" data-path="3.2.html">
<a href="3.2.html">
穿越时空的旅程
</a>
</li>
<li class="chapter " data-level="1.5.3" data-path="3.3.html">
<a href="3.3.html">
用户程序和系统调用
</a>
</li>
<li class="chapter " data-level="1.5.4" data-path="3.4.html">
<a href="3.4.html">
文件系统
</a>
</li>
<li class="chapter " data-level="1.5.5" data-path="3.5.html">
<a href="3.5.html">
精彩纷呈的应用程序
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.6" data-path="PA4.html">
<a href="PA4.html">
PA4 - 虚实交错的魔法: 分时多任务
</a>
<ul class="articles">
<li class="chapter " data-level="1.6.1" data-path="4.1.html">
<a href="4.1.html">
多道程序
</a>
</li>
<li class="chapter " data-level="1.6.2" data-path="4.2.html">
<a href="4.2.html">
虚实交错的魔法
</a>
</li>
<li class="chapter " data-level="1.6.3" data-path="4.3.html">
<a href="4.3.html">
超越容量的界限
</a>
</li>
<li class="chapter " data-level="1.6.4" data-path="4.4.html">
<a href="4.4.html">
来自外部的声音
</a>
</li>
<li class="chapter " data-level="1.6.5" data-path="4.5.html">
<a href="4.5.html">
编写不朽的传奇
</a>
</li>
</ul>
</li>
<li class="chapter " data-level="1.7" data-path="blank.html">
<a href="blank.html">
杂项
</a>
<ul class="articles">
<li class="chapter " data-level="1.7.1" data-path="FAQ.html">
<a href="FAQ.html">
常见问题(FAQ)
</a>
</li>
<li class="chapter " data-level="1.7.2" data-path="why.html">
<a href="why.html">
为什么要学习计算机系统基础
</a>
</li>
<li class="chapter " data-level="1.7.3" data-path="linux.html">
<a href="linux.html">
Linux入门教程
</a>
</li>
<li class="chapter " data-level="1.7.4" data-path="man.html">
<a href="man.html">
man入门教程
</a>
</li>
<li class="chapter " data-level="1.7.5" data-path="git.html">
<a href="git.html">
git入门教程
</a>
</li>
<li class="chapter " data-level="1.7.6" data-path="nemu-isa-api.html">
<a href="nemu-isa-api.html">
NEMU ISA相关API说明文档
</a>
</li>
<li class="chapter " data-level="1.7.7" data-path="changelog.html">
<a href="changelog.html">
更新日志
</a>
</li>
<li class="chapter " data-level="1.7.8" data-path="i386-intro.html">
<a href="i386-intro.html">
i386手册指令集阅读指南
</a>
</li>
<li class="chapter " data-level="1.7.9" data-path="exec.html">
<a href="exec.html">
指令执行例子
</a>
</li>
</ul>
</li>
<li class="divider"></li>
<li>
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
Published with GitBook
</a>
</li>
</ul>
</nav>
</div>
<div class="book-body">
<div class="body-inner">
<div class="book-header" role="navigation">
<!-- Title -->
<h1>
<i class="fa fa-circle-o-notch fa-spin"></i>
<a href="." >在开始愉快的PA之旅之前</a>
</h1>
</div>
<div class="page-wrapper" tabindex="-1" role="main">
<div class="page-inner">
<div id="book-search-results">
<div class="search-noresults">
<section class="normal markdown-section">
<h2 id="在开始愉快的pa之旅之前">在开始愉快的PA之旅之前</h2>
<div class="panel panel-danger"><div class="panel-heading"><h5 class="panel-title" id="pa是一种全新的训练"><i class="fa fa-bullhorn"></i> PA是一种全新的训练</h5></div><div class="panel-body"><p>我们从以下方面对不同的作业/实验/问题进行比较:</p><table>
<thead>
<tr>
<th>基本原理</th>
<th>做事方案</th>
<th>正确性风险</th>
<th>代表例子</th>
</tr>
</thead>
<tbody>
<tr>
<td><font color="green">阐述</font></td>
<td><font color="green">明确</font></td>
<td><font color="green">基本正确</font></td>
<td>高中物理实验</td>
</tr>
<tr>
<td><font color="green">阐述</font></td>
<td><font color="green">明确</font></td>
<td><font color="red">可能出错</font></td>
<td>程序设计作业</td>
</tr>
<tr>
<td><font color="green">阐述</font></td>
<td><font color="red">需要思考</font></td>
<td><font color="green">基本正确</font></td>
<td>数学证明/算法设计题</td>
</tr>
<tr>
<td><font color="green">阐述</font></td>
<td><font color="red">需要思考</font></td>
<td><font color="red">可能出错</font></td>
<td><u>PA</u>, OSlab</td>
</tr>
<tr>
<td><font color="red">需要探索</font></td>
<td><font color="red">需要思考</font></td>
<td><font color="red">可能出错</font></td>
<td>业界和科研的真实问题</td>
</tr>
</tbody>
</table><p>做PA的终极目标是通过构建一个简单完整的计算机系统, 来深入理解程序如何在计算机上运行.
和那些"用递归实现汉诺塔"的程序设计作业不同, 计算机系统比汉诺塔要复杂得多.
这意味着, 通过程序设计作业的训练方式是不足以完成PA的,
只有去尝试理解并掌握计算机系统的每一处细节, 才能一步步完成PA.</p><p>所以, 不要再用程序设计作业的风格来抱怨PA讲义写得不清楚, 之所以讲义的描述点到即止,
是为了强迫大家去理清计算机系统的每一处细节, 去推敲每一个模块之间的关系,
也是为了让大家积累对系统足够的了解来面对未知的bug.</p><p>这对你来说也许是一种前所未有的训练方式, 所以你也需要拿出全新的态度来接受全新的挑战.</p></div></div>
<!-- -->
<div class="panel panel-danger"><div class="panel-heading"><h5 class="panel-title" id="做pa的正确姿势---从今天开始-不要偷懒了-这是一碗鸡汤-当你将来觉得迷茫的时候-回来这里看看吧"><i class="fa fa-bullhorn"></i> 做PA的正确姿势 - 从今天开始, 不要偷懒了 (这是一碗鸡汤, 当你将来觉得迷茫的时候, 回来这里看看吧)</h5></div><div class="panel-body"><p><del><font color="red">我们先列举一些错误做法:</font></del></p><ul>
<li><del>遇到问题了, 随便改改试试, 说不定就过了</del></li>
<li><del>随便改改过不了, 赶紧找大腿/助教/老师来搞定</del><ul>
<li><del>也不想多花时间精力按照<a href="https://github.com/ryanhanwu/How-To-Ask-Questions-The-Smart-Way/blob/master/README-zh_CN.md" target="_blank">提问的智慧</a>和<a href="https://github.com/tangx/Stop-Ask-Questions-The-Stupid-Ways/blob/master/README.md" target="_blank">别像弱智一样提问</a>中建议的方式来提问</del></li>
</ul>
</li>
<li><del>这个函数/文件/命令看不懂, 反正也不是我写的, 算了就这样吧</del></li>
<li><del>宁愿在百度中舒服地浪费生命, 也不想用谷歌快速解决问题</del></li>
<li><del>蓝框题不算分, 不看也没关系</del></li>
<li><del>反正大阶段有一个月的时间, 最后一周开始做, 应该还能赶上</del></li>
</ul><p><del>如果你采用了以上做法, 你也许真的能很快完成前期的实验内容,
但这是以放弃训练机会为代价的. 随着实验进度的推进,
你会感觉PA对你来说越来越吃力.</del></p><p><font color="green">正确的做法是:</font></p><ul>
<li>多思考为什么<ul>
<li>从问题开始着手理解系统也是个不错的方法</li>
</ul>
</li>
<li>独立解决问题<ul>
<li>即使是调一个很弱智的bug, "顺带"能学到的东西也比你想象中多得多</li>
<li>换句话说, 如果你选择抱大腿, 你失去的机会也比你想象中多得多</li>
</ul>
</li>
<li>尝试尽可能理解每一处细节<ul>
<li>将来调bug的时候, 这些细节就是你手中强有力的工具</li>
<li>换句话说, 当你在调bug的时候感到无从下手, 一定是你不了解其中的细节</li>
</ul>
</li>
<li>用正确的工具做事情<ul>
<li>这才是节省时间的科学方法, 而不是偷懒</li>
</ul>
</li>
<li>多读讲义, 彩蛋很多<ul>
<li>讲义中特地设置了不少"不合时宜"的提示, 有的彩蛋要多次阅读才能明白其中的奥妙</li>
<li>多看一道蓝框题, 也许能少调几天bug</li>
</ul>
</li>
<li>按时完成, 拒绝拖延<ul>
<li>这样你才有时间做到上面几点</li>
</ul>
</li>
</ul><p>事实上, 这些做法就是PA中的最本质的能力训练,
而这样的训练, 在PA0就已经开始了: PA0之所以让大家白手装机,
就是希望让大家在解决小问题的过程中收获经验, 用来解决更大的问题;
同时也给大家传播"我可以通过STFW和RTFM独立解决问题"的最初原的信念,
这种信念可以帮助大家驱散对未知的恐惧.</p><p>你用来应付程序设计作业的心态, 在PA这里是混不过去的, 问题暴露的速度比你想象中快得多.
所以, 从今天开始, 不要偷懒了.</p></div></div>
<h3 id="nemu是什么">NEMU是什么?</h3>
<p>PA的目的是要实现NEMU, 一款经过简化的全系统模拟器. 但什么是模拟器呢?</p>
<p>你小时候应该玩过红白机, 超级玛丽, 坦克大战, 魂斗罗...
它们的画面是否让你记忆犹新? (希望我们之间没有代沟...)
随着时代的发展, 你已经很难在市场上看到红白机的身影了.
当你正在为此感到苦恼的时候, 模拟器的横空出世唤醒了你心中尘封已久的童年回忆.
红白机模拟器可以为你模拟出红白机的所有功能.
有了它, 你就好像有了一个真正的红白机, 可以玩你最喜欢的红白机游戏.
我们移植了一个<a href="https://github.com/NJU-ProjectN/fceux-am" target="_blank">红白机模拟器项目FCEUX</a>, 你在PA0中已经克隆了它.
你可以在如今这个红白机难以寻觅的时代, 再次回味你儿时的快乐时光, 这实在是太神奇了!</p>
<div class="panel panel-info"><div class="panel-heading"><h5 class="panel-title" id="不来玩一下吗"><i class="fa fa-comment-o"></i> 不来玩一下吗?</h5></div><div class="panel-body"><p>我们在<a href="https://jyywiki.cn/ICS/2021/labs/PA1.html" target="_blank">这里</a>(可能需要在校园网内部访问)提供了一些游戏的ROM用于测试,
阅读并根据<code>fceux-am/README.md</code>中的内容进行操作, 即可在弹出的新窗口中运行超级玛丽.</p><p>你也可以将自己STFW获得的其它ROM文件放进来, 这样就可以运行其它游戏了.</p></div></div>
<div class="panel panel-danger"><div class="panel-heading"><h5 class="panel-title" id="检查画面-按键和声音"><i class="fa fa-exclamation"></i> 检查画面, 按键和声音</h5></div><div class="panel-body"><p>在运行游戏的过程中, 你需要顺便检查一下是否可以看到画面, 响应按键并听到声音.
超级玛丽在初始界面中不会播放声音, 但会在正式进入关卡时播放声音.
如果没有声音, 会影响PA的部分选做内容, 但不会影响成绩;
但如果画面不能正常显示, 可能会影响PA必做部分的实验内容, 请自行搜索解决方案.</p><p>为了检查按键, 你需要克隆一个新的子项目<code>am-kernels</code>, 里面包含了一些测试程序:</p><pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ics2024
bash init.sh am-kernels
</code></pre><p>然后运行其中的按键测试程序:</p><pre><code class="lang-bash"><span class="hljs-built_in">cd</span> am-kernels/tests/am-tests
make ARCH=native mainargs=k run
</code></pre><p>运行后会弹出一个新窗口, 在新窗口中按下按键,
你将会看到程序在终端输出相应的按键信息, 包括按键名, 键盘码, 以及按键状态.
如果你发现输出的按键信息与按下的按键不符, 请自行搜索解决方案(可采用关键字"SDL keystroke"等).
有网友提示问题可能与<a href="https://github.com/NJU-ProjectN/fceux-am/issues/1" target="_blank">中文输入法兼容性问题</a>相关, 供参考.</p></div></div>
<!-- -->
<div class="panel panel-success"><div class="panel-heading"><h5 class="panel-title" id="觉得编译有点慢"><i class="fa fa-lightbulb-o"></i> 觉得编译有点慢?</h5></div><div class="panel-body"><p><code>make</code>程序默认使用单线程来顺序地编译所有文件,
而FCEUX的源文件又非常多, 你可能需要等待十几秒来完成编译.
但现在的CPU都是多核多线程了, 不把这些计算能力用起来也是白白浪费.
为了加快编译的过程, 我们可以让<code>make</code>创建多个线程来并行地编译文件.</p><p>具体地, 首先你需要通过<code>lscpu</code>命令来查询你的系统中有多少个CPU.
然后在运行<code>make</code>的时候添加一个<code>-j?</code>的参数, 其中<code>?</code>为你查询到的CPU数量.
例如<code>-j4</code>表示创建4个线程来并行编译, 如果系统中CPU的数量大于等于4,
那么操作系统就可以将这4个线程调度到4个CPU上同时执行, 达到加速的效果;
但如果系统中只有2个CPU, 那操作系统最多能将2个线程调度到2个CPU上同时执行,
这时候的加速效果就和<code>-j2</code>差不多了.</p><p>为了查看编译加速的效果, 你可以在编译的命令前面添加<code>time</code>命令,
它将会对紧跟在其后的命令的执行时间进行统计, 你只需要关注<code>total</code>一栏的时间即可.
你可以通过<code>make clean</code>清除所有的编译结果, 然后重新编译并统计时间,
对比单线程编译和多线程编译的编译时间;
你也可以尝试不同的线程数量进行编译, 并对比加速比.</p></div></div>
<!-- -->
<div class="panel panel-success"><div class="panel-heading"><h5 class="panel-title" id="还是觉得编译有点慢"><i class="fa fa-lightbulb-o"></i> 还是觉得编译有点慢?</h5></div><div class="panel-body"><p>我们清除所有编译结果之后重新编译, 源文件并没有发生任何变化,
按道理编译出来的目标文件也应该和上一次编译结果完全相同.
既然这样, 那我们能不能把这些目标文件以某种方式存起来,
下次编译的时候如果发现源文件没有变化, 就直接取出之前的目标文件作为编译结果,
从而跳过编译的步骤呢?</p><p>还真有工具专门做这件事! 这个工具叫<code>ccache</code>:</p><pre><code class="lang-bash">apt-get install ccache
</code></pre><p>如果你通过<code>man</code>阅读<code>ccache</code>的手册, 你会发现<code>ccache</code>是一个<code>compiler cache</code>.
<code>cache</code>是计算机领域中的一个术语, 你将会在后续的ICS课程中学习相关的内容.</p><p>为了使用<code>ccache</code>, 你还需要进行一些配置的工作.
首先运行如下命令来查看一个命令的所在路径:</p><pre><code class="lang-bash"><span class="hljs-built_in">which</span> gcc
</code></pre><p>它默认会输出<code>/usr/bin/gcc</code>, 表示当你执行<code>gcc</code>命令时, 实际执行的是<code>/usr/bin/gcc</code>.
作为一个RTFM的练习, 接下来你需要阅读<code>man ccache</code>中的内容, 并根据手册的说明,
在<code>.bashrc</code>文件中对某个环境变量进行正确的设置.
如果你的设置正确且生效, 重新运行<code>which gcc</code>, 你将会看到输出变成了<code>/usr/lib/ccache/gcc</code>.
如果你不了解环境变量和<code>.bashrc</code>, STFW.</p><p>现在就可以来体验<code>ccache</code>的效果了. 首先先清除编译结果, 然后重新编译并统计时间.
你会发现这次编译时间反而比之前要更长一些, 这是因为除了需要开展正常的编译工作之外,
<code>ccache</code>还需要花时间把目标文件存起来.
接下来再次清除编辑结果, 重新编译并统计时间, 你会发现第二次编译的速度有了非常明显的提升!
这说明<code>ccache</code>确实跳过了完全重复的编译过程, 发挥了加速的作用.
如果和多线程编译共同使用, 编译速度还能进一步加快!</p><p>在开发项目的过程中, 有时确实会需要在清除编译结果后进行全新的编译(fresh build).
到了PA的后期, 你可能会多次编译一些包含数百个文件的库,
在这些场合下, <code>ccache</code>能够极大地节省编译的时间, 从而提高项目开发的效率.</p></div></div>
<p>你被计算机强大的能力征服了, 你不禁思考, 这到底是怎么做到的?
你学习完程序设计基础课程, 但仍然找不到你想要的答案.
但你可以肯定的是, 红白机模拟器只是一个普通的程序, 因为你还是需要像运行Hello World程序那样运行它.
但同时你又觉得, 红白机模拟器又不像一个普通的程序,
它究竟是怎么模拟出一个红白机的世界, 让红白机游戏在这个世界中运行的呢?</p>
<p>事实上, NEMU就是在做类似的事情!
它模拟了一个硬件的世界, 你可以在这个硬件世界中执行程序.
换句话说, <font color="red">你将要在PA中编写一个用来执行其它程序的程序!</font>
为了更好地理解NEMU的功能, 下面将</p>
<ul>
<li>在GNU/Linux中运行Hello World程序</li>
<li>在GNU/Linux中通过红白机模拟器玩超级玛丽</li>
<li>在GNU/Linux中通过NEMU运行Hello World程序</li>
</ul>
<p>这三种情况进行比较.</p>
<pre><code> +---------------------+ +---------------------+
| Super Mario | | "Hello World" |
+---------------------+ +---------------------+
| Simulated NES | | Simulated |
| hardware | | hardware |
+---------------------+ +---------------------+ +---------------------+
| "Hello World" | | NES Emulator | | NEMU |
+---------------------+ +---------------------+ +---------------------+
| GNU/Linux | | GNU/Linux | | GNU/Linux |
+---------------------+ +---------------------+ +---------------------+
| Real hardware | | Real hardware | | Real hardware |
+---------------------+ +---------------------+ +---------------------+
(a) (b) (c)
</code></pre><p>图中(a)展示了"在GNU/Linux中运行Hello World"的情况.
GNU/Linux操作系统直接运行在真实的计算机硬件上, 对计算机底层硬件进行了抽象, 同时向上层的用户程序提供接口和服务.
Hello World程序输出信息的时候, 需要用到操作系统提供的接口,
因此Hello World程序并不是直接运行在真实的计算机硬件上, 而是运行在操作系统(在这里是GNU/Linux)上.</p>
<p>图中(b)展示了"在GNU/Linux中通过红白机模拟器玩超级玛丽"的情况.
在GNU/Linux看来, 运行在其上的红白机模拟器NES Emulator和上面提到的Hello World程序一样, 都只不过是一个用户程序而已.
神奇的是, 红白机模拟器的功能是负责模拟出一套完整的红白机硬件, 让超级玛丽可以在其上运行.
事实上, 对于超级玛丽来说, 它并不能区分自己是运行在真实的红白机硬件之上,
还是运行在模拟出来的红白机硬件之上, 这正是"模拟"的障眼法.</p>
<p>图中(c)展示了"在GNU/Linux中通过NEMU执行Hello World"的情况.
在GNU/Linux看来, 运行在其上的NEMU和上面提到的Hello World程序一样, 都只不过是一个用户程序而已.
但NEMU的功能是负责模拟出一套计算机硬件, 让程序可以在其上运行.
事实上, 上图只是给出了对NEMU的一个基本理解, 更多细节会在后续PA中逐渐补充.</p>
<div class="panel panel-info"><div class="panel-heading"><h5 class="panel-title" id="nemu是什么"><i class="fa fa-comment-o"></i> NEMU是什么?</h5></div><div class="panel-body"><p>上述描述对你来说也许还有些晦涩难懂, 让我们来看一个ATM机的例子.</p><p>ATM机是一个物理上存在的机器, 它的功能需要由物理电路和机械模块来支撑.
例如我们在ATM机上进行存款操作的时候, ATM机都会吭哧吭哧地响, 让我们相信确实是一台真实的机器.
另一方面, 现在第三方支付平台也非常流行, 例如支付宝.
事实上, 我们可以把支付宝APP看成一个模拟的ATM机,
在这个模拟的ATM机里面, 真实ATM机具备的所有功能,
包括存款, 取款, 查询余额, 转账等等, 都通过支付宝APP这个程序来实现.</p><p>同样地, NEMU就是一个模拟出来的计算机系统,
物理计算机中的基本功能, 在NEMU中都是通过程序来实现的.
要模拟出一个计算机系统并没有你想象中的那么困难.
我们可以把计算机看成由若干个硬件部件组成, 这些部件之间相互协助, 完成"运行程序"这件事情.
在NEMU中, 每一个硬件部件都由一个程序相关的数据对象来模拟, 例如变量, 数组, 结构体等;
而对这些部件的操作则通过对相应数据对象的操作来模拟.
例如NEMU中使用数组来模拟内存, 那么对这个数组进行读写则相当于对内存进行读写.</p><p>我们可以把实现NEMU的过程看成是开发一个支付宝APP.
不同的是, 支付宝具备的是真实ATM机的功能, 是用来交易的;
而NEMU具备的是物理计算机系统的功能, 是用来执行程序的.
因此我们说, NEMU是一个用来执行其它程序的程序.</p></div></div>
<!--
>
> 你或许还对虚拟机和模拟器这两个相似的概念感到疑惑, 毕竟它们都表示用程序的功能来实现某些东西.
> 虚拟机就是用程序虚拟出来的机器;
> 而模拟器的范围则更加广泛, 可以用程序来模拟天体运动, 大气环流, 分子碰撞等等,
> 然而这些模拟的对象并不是一个计算机系统.
> 当我们用模拟器来模拟一个计算机系统的时候, 它和虚拟机在本质上并没有太大的差异.
> 所以我们说NEMU是个x86模拟器, 或者说NEMU是个x86的虚拟机, 其实可以认为是同一个意思:
> NEMU是用程序来实现一个计算机系统的功能, 并不是一个物理上的计算机.
-->
<p>NEMU的威力会让你感到吃惊!
它不仅仅能运行Hello World这样的小程序, 在PA的后期,
你将会在NEMU中运行经典RPG游戏<a href="https://baike.baidu.com/item/%E4%BB%99%E5%89%91%E5%A5%87%E4%BE%A0%E4%BC%A0/5129500#viewPageContent" target="_blank">仙剑奇侠传</a>(很酷! %>_<%).
如果你完成了所有的选做编程内容, 你甚至可以在NEMU中运行现代文字冒险游戏<a href="https://baike.baidu.com/item/CLANNAD/25452" target="_blank">CLANNAD</a>!
完成PA之后, 你在程序设计课上对程序的认识会被彻底颠覆,
你会觉得计算机不再是一个神秘的黑盒, 甚至你会发现创造一个属于自己的计算机不再是遥不可及!</p>
<h3 id="选择你的角色">选择你的角色</h3>
<div class="panel panel-info"><div class="panel-heading"><h5 class="panel-title" id="新特性---多主线"><i class="fa fa-comment-o"></i> 新特性 - 多主线</h5></div><div class="panel-body"><p>PA有一个多主线的特性.
具体地, 你需要从<a href="https://en.wikipedia.org/wiki/X86" target="_blank">x86</a>/<a href="https://en.wikipedia.org/wiki/MIPS_architecture" target="_blank">mips32</a>/<a href="https://en.wikipedia.org/wiki/RISC-V" target="_blank">riscv32(64)</a>这三种<a href="https://en.wikipedia.org/wiki/Instruction_set_architecture" target="_blank">指令集架构(ISA)</a>中选择一种,
来实现"创造属于自己的计算机"这一梦想.</p><p>但无论选择哪种ISA, 你最终都会体会到"软硬件共同协助来支持程序执行"的机理:
所谓的tradeoff, 只不过是决定将一件事情交给硬件来做, 还是交给软件来做.
但三种ISA毕竟各有特色, 它们对不同章节的攻略难度如下表所示(5星 - 容易, 1星 - 困难)</p><table style="text-align:center" id="ISA-COMP">
<thead><th></th><th>x86</th><th>mips32</th><th>riscv32(64)</th></thead>
<tbody>
<tr>
<td>PA1 - 简易调试器</td>
<td colspan="3">与ISA选择关系不大</td>
</tr>
<tr>
<td>PA2 - 冯诺依曼计算机系统</td>
<td star-1=""></td><td star-3=""></td><td star-5=""></td>
</tr>
<tr>
<td>PA3 - 批处理系统</td>
<td star-5=""></td><td star-3=""></td><td star-5=""></td>
</tr>
<tr>