到如今,我们的hello.c源程序已经已经被编译系统翻译为可运行对象文件了,这个可运行对象文件叫做hello,被存储在磁盘上。为了在Unix系统上运行可运行文件,我们在一个叫做shell的应用程序中输入它的名字:
unix> ./hello
hello, world
unix>
shell程序是一个命令行解释器,它打印出一条提示,等着你输入一条命令行。然后运行命令。如果输入的命令行的第一个单词没有匹配到内建的shell命令。那么shell如果这个单词是一个可运行文件的名字。这个文件应该被载入进内存然后运行。在我们的样例中。shell载入并运行hello程序,并等待着它结束。hello程序打印它的消息到屏幕上,然后结束。
然后,shell打印一条提示。等待着下一条命令行的输入。
1.4.1 一个系统的硬件组织
为了理解当我们执行hello程序时。系统都对它做了什么,我们须要理解一个典型系统的硬件组织,假设1.4所看到的。这张图是依据英特尔的奔腾系统家族制作的。可是全部系统都是相似的。如今不用操心这张图的复杂性。在本书中,我们将分阶段地讲诉它的细节。
总线
连接系统中各个部件的是被叫做总线的电子导线集合,总线带着几字节的信息在系统各个部件中穿梭。
总线通常被设计成传送固定长度的字结块。这种字结块被称为字。一个字的字节数是一个主要的系统參数,各个系统有所不同。如今大部分的机器的字长是4字节或者8字节。为了便于讨论。我们如果字长为4字节,而且总线一次仅仅传送一个字长的数据。
输入输出设备
输入输出设备连接这系统和外部世界。我们的演示样例系统有四个输入输出设备:用于用户输入的键盘和鼠标。用于用户输出的显示器。用于数据和程序的长期存储的磁盘。最初。hello程序待在磁盘上。
每个输入输出设备通过控制器或者适配器连接到输入输出总线上。控制器和适配器最大的不同是被集成进系统的方式。控制器是集成在设备自身里或者主板上的芯片集。适配器是一个插在主板插槽里的卡片。但它们的目的都是在输入输出设备和输入输出总线之间传送信息。
第六章会将很多其他关于输入输出设备怎样工作的内容,像磁盘。第十章,你将学到怎样在自己的程序中通过Unix IO接口訪问设备。我们关注十分有趣的网络设备,可是技术对其他设备也是一样的。
内存
当处理器执行程序时。内存是一个暂时存储设备,存储着程序和程序操作的数据。物理上。内存由一组DRAM组成。
逻辑上。内存被组织为一维的字节数组。每一字节有唯一的地址(数组索引),地址从0開始。
通常,组成程序的机器指令由不同数量的字节组成。
相应着C程序变量的数据项大小依据数据类型不同而变化。比如,在一个执行Linux的IA32机器上。short类型的数据须要2字节,int,float和long须要4字节,double须要8字节。
第六章有很多其它关于存储技术(比如DRAM芯片)怎样工作以及它们怎样组合在一起形成内存的内容。
处理器
中央处理单元(CPU)。或者简单地称为处理器,是解释(或者运行)存储在内存中的指令的引擎。
它的核心是一个字长的存储设备(或者叫做寄存器),这个存储设备叫做程序计数器。不论什么时刻。程序计数器都指向内存中的机器语言指令。
从系统打开到系统关闭,处理器不断地运行程序计数器指向的指令并更新程序计数器的值让它指向下一条指令。处理器通过一个很easy的指令运行模型来操作。指令运行模型由指令集结构定义。在这个模型中,指令以严格的顺序运行。而且运行单条命令也涉及到多个步骤。处理器从内存中读取被程序计数器指向的命令,用指令解释这些位。运行一些被运行指示的简单操作,然后更新程序计数器使之指向下一条指令,下一条指令和刚刚运行的指令在内存中可能是挨着的。也可能不是挨着的。
这里有几个这种简单操作。它们环绕着内存,寄存器文件和算术逻辑单元。
寄存器文件是一个小的存储设备,由一些字长大小的寄存器组成,每一个寄存器都有自己唯一的名字。算术逻辑单元计算新的数据和地址值。这里有一些简单操作的样例。CPU可能在一条指令请求的时候运行这些操作:
Load:从内存中复制一个字节或字到寄存器中,覆盖掉寄存器中之前的内容。
Store:从寄存器中复制一个字节或字到内存中某个位置,覆盖掉这个位置之前的值。
Operate:复制两个寄存器中的值到算术逻辑单元,在两个字上运行算术操作。然后把结果存入一个寄存器,覆盖该寄存器之前的值。
Jump:从指令中抽取出一个字,然后复制这个字到程序计数器中,覆盖掉程序计数器之前的值。
我们看到。一个处理器似乎就是它的指令集结构的简单实现,可是,其实。现代处理器用了复杂得多的机制去加快程序运行。因此,我们可以分辨处理器的指令集结构(描写叙述每条机器码指令的影响)和微处理器结构(描写叙述一个处理器的实际实现)。当我们在第三章学习机器码的时候。我们将考虑机器指令集结构提供的抽象。第四章讲了很多其它关于处理器被实际实现的内容。
1.4.2执行hello程序
在对系统的硬件的组织和操作有了大概了解之后,我们開始可以理解当我们执行我们的演示样例程序时到底发生了些什么了。我们这里必须忽略大量细节,这些细节将在后面具体介绍,可是如今,我们能对发生的事情有个整体的了解。
最初,shell程序运行它的指令,等待我们输入命令。
当我们通过键盘输入字符串./hello后,shell读取每一个字符进寄存器,然后把它们存进内存。如图1.5。
当我们在键盘上敲击enter键时,shell便知道我们已经完毕了我们的命令的输入。
shell通过运行一系列指令载入可运行hello文件,这些指令从磁盘中复制hello对象文件里程序和数据到内存中。数据包含终于会被打印出来的字符串“hello, world\n”。
使用直接内存訪问技术((DMA, 将在第六章讨论),数据直接从磁盘到达内存,而不用经过处理器。
这一步在图1.6中描写叙述。
一旦hello对象文件里的代码和数据被载入进内存,处理器便開始运行hello程序的main方法中的机器语言指令。
这些指令从内存中复制表示“hello, world\n”字符串的字节到寄存器文件里。然后再拷贝到显示设备,然后被显示到屏幕上。这一步在图1.7中显示。