关于软件的基础知识

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

由 Richard E. Buckman 和 Joshua Gay 撰写

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

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

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

计算机程序是如何从源代码生成二进制可执行文件的{ width=100% }

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

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

在 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”变成法语。只需要做出简单的修改;新的程序如下:

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 操作系统的组成部分。

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


  1. 对于其他的编程语言,比如 Scheme,通常不从 Hello World 程序开始入门。在 Scheme 中,你通常会从这样的程序开始:

    (define (factorial n) (if (= n 0) 1 (* n (factorial (- n 1)))))

    这段程序是求一个数的阶乘;也就是运行(factorial 5)将会输出 120,即 5 乘以 4 乘以 3 乘以 2 乘以 1。