[Translation] [Quora]How exactly does a computer program work?

2013年1月29的的Quora文摘的一篇文章还蛮有趣的,为非专业同学大致解释了下计算机程序如何运行。为了强迫自己多读多写,试着翻译看看,也为我在墨尔本的面试生涯增加些生趣和意义,全当自娱自乐或者苦衷做了好了。请允许我在总重原作者的前提下,自由放浪的发挥。

[题目]

计算机程序具体是如何工作的?换句人类听得懂的话来说,以行行五颜六色的字儿,怎么就能让一个插满线的盒子工作了呢?我觉得计算机是基于0和1的,但到底他们是怎么他妈翻译过去的呢?

[Artem Boytsov的答案]

这真是一个好问题。如果你想完全知道怎么回事,你必须要阅读计算机体系结构的相关书籍。计算机确实是通过操作0和1来实现这些的。让我们从非常非常基本的开始吧。

  1. 计算机的核心部分叫做中央处理器(CPU),现代CPU包括很多东西,但是简单来说,CPU是由很多微电子组成的,可以运行指令的东东,如下图,小方盒儿和它带刺儿的背面。



     

  2. 你也可以认为CPU是一大堆逻辑晶体管门(What the F!),超多的。这些门由晶体管和其他电子器件组成,只实现了非常简单的逻辑操作:AND(与),OR(或),NOT(非)。就算是非常简单的CPU也需要使用上千个晶体管。而对复杂的现代CPU,也许有超过25亿个晶体管。也许你会说他们很小,但其实有一些也不是特别小,如图(三个小腿儿中,两个是输入,一个是输出)

     

  3. 晶体管的操作时基于电流的,简单来讲,这就是0和1的来源,1代表有电流,0代表没有电流。逻辑操作时基于这些电流的。比如:
    1. AND(与)两个输入都是1时,output才是1
    2. OR(或)两个输入中,有一个是1,output就是1
    3. NOT(非)反转输入,1变0,0变1

       

  4. 当你组合这三个操作时,你可以表达所有的逻辑,四则运算和其他一切。无论您相不相信,反正我相信。你唯一需要做的,只是把他们重复组合在一起。也可以这样理解,数字用1和0表示,及二进制,其他的只是一些1和0的逻辑操作组合。下图是一个组合的例子,可以计算两位相加。如果想实现更大的数字相加,只需要加更多地组合而已。

     

  5. 以上是CPU及其逻辑。但是,我们从那里得到指令呢?我们已经知道了如何操作,现在我们讲讲该如何获取一系列指令呢。比如,我们可以和CPU达成协议,把45当成两个数相加,87当作两个数相处。然后CPU需要做的就是,读取这些数字然后执行相应的指令。

     

  6. 在现代CPU中,我们把这些指令叫做微指令(microcode),它包含了大多数的基本指令。微指令被用来实现更复杂的机器指令(machine code),机器指令仍然是数字,只不过更复杂。想象一下这个例子:机器指令为”76 2 3 4″, 意思是 将内存上2号位和3号位的 两个数字相加(指令代号76),结果写到内存4号位。微指令则更简单,比如”读取内存2号位的数字”,CPU就会执行它了。

     

  7. 上文提到了内存,比较好理解。它包含了很多个0和1,并且可以被改变。就长这么个样子。

在几乎所有的已存计算机体系中(感谢这家伙 – 冯诺伊曼),上文提到的指令代码存放在内存中,就像其他数据一样。指令(76 2 3 4)也被存放在内存中。开启CPU后,需要把它指向一个存着走起(GO)!的内存地址。CPU就会一条条的读取指令。

  1. 当然,因为计算机只懂得1和0,所以指令和数据都以二进制形式存储。二进制其实很好理解,平时我们用十进制,0,1,2,3,4,5,6,7,8,9.你可以想想,也许只有8个手指的ET会用8进制0,1,2,3,4,5,6,7. 我国古代也有16进制所以半斤才是8两。

     

  2. 累死个人,不想翻了。。。76 2 3 4这指令太他妈难懂了,谁知道76时啥意思,我必须得查指令代码手册好伐,又不是内战时期,干嘛秘密成这样。好吧,现在又来了汇编语言,你妈我脖子疼。它会把指令表达的更人性化一点。
  • 汇编语言:ADD [2], [3] -> [4] (伪汇编语言,大概是这么个意思)
  • 机器指令:76 2 3 4

     

  1. 第一个汇编器Assembler(编语言翻译成机器指令),当然必须得用纯数字指令写。但其实不难,因为基本上汇编语言和机器指令是一比一的相互对应的。

     

  2. 好歹汇编语言不需要查字典也能看得弄,事情好弄多了。但是用起来仍然麻烦。比如,实现读取用户的输入,加1以后,输出结果。也就是用户输入4,输出5即可。就这么一个简单操作,你妈要写很多条汇编语言啊有没有。它实在是他底层了,太缺乏高一层次的抽象了。

     

  3. OK,进入编程语言Programming Languages。比起汇编,它简直太高层了,哈哈哈,可以很简单的表达复杂逻辑。比如:

     

    R=2.0

    Print “2.0 + 1 = %f” (R+1)

    就这么两行代码,能翻译成居多汇编语言,但是编译器compiler会帮我们做,它会把编程语言Programming Language翻译成汇编语言Assembly Language,其实大多数时候是到了机器指令的。总之他就是把人写的东西翻译成机器懂的

     

  4. 现在我们有了编译器,可以将我写的程序,翻译成机器指令,结果是一个可执行文件Executable File。它其实是一堆1和0,存放在硬盘的某个地方。如果想运行它,CPU需要把它读取到内存中,将CPU指向程序的最开端,然后走起!
  5. 最后来说说操作系统Operating System。它基本上是一个随着电脑启动而启动的程序。它会处理一些复杂的内容,比如磁盘,文件,显示器,键盘,鼠标等等。所以你的程序就不需要担心这些了。你可以让操作系统去读取刚刚键入的键盘按键,而不必担心要如何和键盘通信。

     

    流行的桌面操作系统:Windows,Linux,Mac。。。

    流行的移动操作系统:iOS,Androd,Windows Phone,Symbian(卒于2013),Win8。。。

     

    文件和文件夹其实是伴随操作系统而来的。是操作系统读取你可执行文件到内存,然后将CPU指向程序头,然后说:走起!

恭喜你,你已经大致了解了计算机体系结构,一点点,一点点。。。。。

Richard Feynman Computer Heuristics Lecture

Youtube的视频,一个多小时,有点长,很古老。