summaryrefslogtreecommitdiff
path: root/docs/appendix-a.md
blob: 2e6f631ad2aacdffbde3d0d1364b4c87c0d8850a (plain)
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
## 附录A:关于软件的基础知识

> Copyright © 2002 Richard E.Buckman and Joshua Gay. 此文最早发布于 2002 年。

由 Richard E. Buckman 和 Joshua Gay 撰写

本节内容是特意为对计算机科学技术了解不多的人准备的。这节内容对于理解书中的文章和演讲并不是必须的,不过,它可以帮助那些不熟悉编程和计算机的人理解一些术语。

计算机*程序员*来写软件或者计算机程序。而程序可以认为是告诉计算机如何完成特定任务的一系列*指令*。你应该熟悉许多不同类型的应用程序:比如你的网页浏览器、你的文字处理器和你的邮件客户端等等。

程序最初的形态通常是*源代码*。这一系列高级指令由*编程语言*(比如 C 或者 Java)编写而成。之后会被一个名为*编译器*的工具编译为一种更底层的语言——*汇编语言*。另一种被称为*汇编器*的工具会将汇编代码分解为最终的*机器语言*——计算机可以*原生*理解的最底层代码。

![code](code.png)

例如,“Hello World”这个程序,通常是人们学习 C 语言时的第一个程序,编译和执行后会在屏幕上打印出“Hello World”[^ap-1]。

```C
int main(){
	printf("Hello World!");
    return 0;
} 
```

在 Java 语言中,同样的程序会是这么写:

```Java
public class hello {
	public static void main(String args[]) {
		System.out.println("Hello World!");
    }
} 
``` 

然而用机器码表示,其中的一小部分可能会类似这样:

```
1100011110111010100101001001001010101110
0110101010011000001111001011010101111101
0100111111111110010110110000000010100100
0100100001100101011011000110110001101111
0010000001010111011011110111001001101100
0110010000100001010000100110111101101111
```

上面这段机器码就是基本的二进制形式。计算机中所有的数据都是由 0 或 1 组成的,但是人们很难理解这些数据。如果想要对二进制的值进行一个简单的更改,就不得不对特定计算机编译机器语言的原理了如指掌。这对于类似于上面这种小程序来说或许是可行的,但是对于任何有趣的程序,做一个简单的修改就需要耗费大量的精力。

比如说,如果我们想让让 C 语言编写的“Hello World”程序输出的英语“Hello World”变成法语。只需要做出简单的修改;新的程序如下:

```C
int main() {
    printf("Bonjour, monde!");
    return 0; 
}
```

可以肯定地说,我们可以很容易的推断出如何修改 Java 代码以达到同样的效果。然而更多的程序员不懂如何修改二进制形式。当我们说“源代码”的时候,不是指只有机器可以理解的机器语言——我们指的是一些高级语言比如 C 和 Java。还有一些其他的比较流行的编程语言,比如 C++、Perl 和 Python。或许有些在理解或编程时比较难以理解,但都比理解编译和汇编以后的机器语言简单多了。

另一个重要概念是理解什么是*操作系统*。操作系统是控制输入输出,内存分配和任务调度的软件。通常点说,一些更常见且更有用的程序,比如*图形用户界面*(*Graphical User Interface*,GUI),也是操作系统的一部分。GNU/Linux 操作系统包括 GNU 和非 GNU 软件,以及一个被称为*Linux*的*内核*。内核负责处理底层任务比如输入输出和任务调度。GNU 软件包含了操作系统其余的大部分,比如 GCC,一款支持多种语言的通用编译器;GNU Emacs,一款可扩展的并且有很多很多特性的文本编辑器;GNOME,GNU 桌面环境;GNU libc,一个程序库,除内核外所有其他程序与内核通讯时都必须使用的库;以及 Bash,GNU 命令行解释器可以读取你的命令行。这些程序很多都是早期由理查德·斯托曼在 GNU 工程里开发,并成为现代 GNU/Linux 操作系统的组成部分。

重要的是理解即使*你*没有修改程序源代码或直接使用所有这些工具的能力,找到一个可以做到的人也是相对容易的。因此,有源代码的程序你就有权力去修改、修复、定制和学习编程——而如果得不到源代码就没有这些权力。源代码是让一个软件变*自由*的必要条件之一,而其他必要条件可从本书的哲学和理想中找到答案。

[^ap-1]: 
    对于其他的编程语言,比如 Scheme,通常不从 Hello World 程序开始入门。在 Scheme 中,你通常会从这样的程序开始:
    
    ```
      (define (factorial n) 
          (if (= n 0) 
          1
          (* n (factorial (- n 1)))))
    ```
    
    这段程序是求一个数的阶乘;也就是运行`(factorial 5)`将会输出 120,即 5 乘以 4 乘以 3 乘以 2 乘以 1。