From b95c221d0d0af79350db1d1454f6422bd42aaafd Mon Sep 17 00:00:00 2001 From: Hagb Date: Sat, 2 Jun 2018 12:50:43 +0800 Subject: =?UTF-8?q?=E5=AE=89=E8=A3=85pdf2svg?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/appendix-a.md | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) create mode 100644 docs/appendix-a.md (limited to 'docs/appendix-a.md') diff --git a/docs/appendix-a.md b/docs/appendix-a.md new file mode 100644 index 0000000..35b53ea --- /dev/null +++ b/docs/appendix-a.md @@ -0,0 +1,72 @@ +# 关于软件的基础知识 + +> Copyright © 2002 Richard E.Buckman and Joshua Gay. 此文最早发布于 2002 年。 + +由 Richard E. Buckman 和 Joshua Gay 撰写 + +本节内容是特意为对计算机科学技术了解不多的人准备的。这节内容对于理解书中的文章和演讲并不是必须的,不过,它可以帮助那些不熟悉编程和计算机的人理解一些术语。 + +计算机*程序员*来写软件或者计算机程序。而程序可以认为是告诉计算机如何完成特定任务的一系列*指令*。你应该熟悉许多不同类型的应用程序:比如你的网页浏览器、你的文字处理器和你的邮件客户端等等。 + +程序最初的形态通常是*源代码*。这一系列高级指令由*编程语言*(比如 C 或者 Java)编写而成。之后会被一个名为*编译器*的工具编译为一种更底层的语言——*汇编语言*。另一种被称为*汇编器*的工具会将汇编代码分解为最终的*机器语言*——计算机可以*原生*理解的最底层代码。 + +![计算机程序是如何从源代码生成二进制可执行文件的](code-zh.svg) + +例如,“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。 -- cgit v1.2.3