计算机组成原理(基于x86-64架构)

978-7-115-63960-8
作者: [美]罗伯特·G.普兰茨(Robert G. Plantz)
译者: 门佳朱西方
编辑: 郭泳泽
分类: 其他

图书目录:

详情

了解计算机软硬件的工作原理可以为理解复杂代码打下坚实的基础,从而提升对代码的控制力。本书围绕如何将高级语言代码翻译成汇编语言、操作系统硬件资源管理、数据的编码、硬件的十进制数据处理、程序代码和机器代码等主题,解释了现代计算机的工作原理;从内存组织、二进制逻辑和数据类型等基本概念开始,逐步探讨它们在汇编语言层面的实现方式。全书共21章,涵盖了数据存储、逻辑门和晶体管、中央处理器、汇编和机器代码、数据结构、面向对象编程等内容。 本书适合作为高等院校计算机组成原理相关课程的参考教材,也适合有编程基础的人阅读。

图书摘要

版权信息

书名:计算机组成原理(基于x86-64架构)

ISBN:978-7-115-63960-8

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

版  权

著    [美] 罗伯特·G.普兰茨(Robert G. Plantz)

译    门 佳 朱西方

责任编辑 郭泳泽

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315

内容提要

了解计算机软硬件的工作原理可以为理解复杂代码打下坚实的基础,从而提升对代码的控制力。本书围绕如何将高级语言代码翻译成汇编语言、操作系统硬件资源管理、数据的编码、硬件的十进制数据处理、程序代码和机器代码等主题,解释了现代计算机的工作原理;从内存组织、二进制逻辑和数据类型等基本概念开始,逐步探讨它们在汇编语言层面的实现方式。全书共21章,涵盖了数据存储、逻辑门和晶体管、中央处理器、汇编和机器代码、数据结构、面向对象编程等内容。

本书适合作为高等院校计算机组成原理相关课程的参考教材,也适合有编程基础的人阅读。

前  言

本书从程序员的角度介绍了计算机硬件的工作原理及其相关概念。硬件由一组机器指令控制。这些指令控制硬件的方式称为指令集架构(Instruction Set Architecture,ISA)。程序员的工作是设计这些指令的序列,使硬件执行操作来解决问题。

几乎所有的计算机程序都是用高级语言编写的,其中有些语言是通用的,有些则面向特定类型的应用。但它们都旨在为程序员提供一套编程结构,使其更适合用人类的语言解决问题,而不是直接涉及指令集架构和硬件细节。

目标读者

当你使用高级语言编写程序的时候,你有没有想过幕后发生了什么?你知道计算机可以通过编程来做出判断,但这是怎么实现的呢?你可能知道数据是以比特存储的,但是存储一个十进制数意味着什么呢?本书的目标是回答这些和其他很多关于计算机如何工作的问题。我们将着眼于硬件组件和用于控制硬件的机器指令。

我假设你了解高级语言编程的基本知识,但你不必是专业的程序员。在讨论了硬件组件之后,我们讲解并编写大量汇编语言程序,汇编语言是一种能够直接翻译成机器指令的语言。

与大多数汇编语言图书不同,本书没有把重点放在使用汇编语言编写应用程序上。诸如C++、Java、Python这样的高级语言在创建应用程序时效率更高。使用汇编语言编程是一个乏味、容易出错且耗时的过程,应该尽可能避免。我们的目标是学习编程概念,而不是创建应用程序。

关于本书

在创作本书的过程中,我秉持以下观点:

在已知概念的基础上学习会更容易;

现实世界中的硬件和软件为学习理论概念提供了一个更有趣的平台;

学习工具应该便宜且容易获得。

书中的编程

本书基于x86-64指令集架构,这是x86指令集架构的64位版本,也称为AMD64、x86_64、x64或Intel 64。本书所有的编程都是在Linux操作系统Ubuntu下的GNU编程环境中完成的。这些程序稍作修改(如果需要),应该就可以在大多数常用的Linux发行版中运行。

本书使用C作为高级语言,后续会用到一些C++。不过就算不懂C/C++也不用担心。本书展示的所有C/C++编程都非常简单,在编程过程中我会给出必要的讲解。

学习汇编语言时有一个重要问题是要在程序中使用键盘和终端屏幕。对键盘输入和屏幕输出进行编程不是件容易事,远远超出了初学者的专业知识范围。GNU编程环境提供了C标准库。为了符合本书的“现实世界”标准,我们会用到标准库中的函数,这些库函数从汇编语言中调用起来非常方便,能够帮助我们在应用程序中使用键盘和屏幕。

x86-64指令集架构包括大约1500条指令。确切的数量取决于对“怎样算是不同的指令”的界定,但是要记住的指令实在太多了。一些汇编语言图书通过发明一种“理想化的”指令集架构来阐述概念,从而解决了这个问题。同样,为了保持本书的“现实世界”性质,我将使用标准的x86-64指令集,但只从中选择了足以说明基本概念的一个指令子集。

为什么要阅读本书

鉴于有许多优秀的高级语言可供你编写程序,同时也不必关心机器指令如何控制硬件,你可能会好奇为什么还要阅读本书。所有高级语言最终都会被翻译成控制硬件的机器指令。熟悉硬件的功能以及指令如何控制硬件有助于你理解计算机的功能和局限性。我相信这种理解可以让你成为更优秀的程序员,哪怕你使用的是高级语言。

如果你的主要兴趣是硬件,理解程序如何使用硬件也很重要。

你可能喜欢汇编语言编程,并希望继续学习下去。例如,如果你对系统编程感兴趣——编写部分操作系统、编写编译器,甚至设计另一种更高级的语言——通常也离不开汇编语言层面的知识。

在嵌入式系统编程领域也存在很多具有挑战性的机会,在这些系统中,计算机承担着专门的任务。手机,家用电器,汽车,供暖、通风与空调系统,医疗设备等,都是我们日常生活中不可或缺的一部分。嵌入式系统是物联网技术的重要组成部分。对嵌入式系统进行编程通常需要理解计算机如何在汇编语言层面与各种硬件设备进行交互。

如果你已经学过其他处理器的汇编语言,本书可以作为参考手册。

章节组织

本书大致分为3部分——数学和逻辑、硬件、软件。数学部分旨在为你提供讨论概念所需的数学语言。硬件部分介绍了用于构建计算机的组件。

这两部分为讨论软件如何控制硬件提供了背景知识。我们将学习C语言中的每一种基本编程结构,本书的最后还会涉及一些C++,并介绍编译器如何将C/C++代码翻译成汇编语言,后者是一种直接访问指令集架构的语言。我还会向你展示程序员如何直接使用汇编语言编写等效的结构。

第1章讲述了计算机的3个子系统及其连接方式,还讨论了如何设置书中用到的编程工具。

第2章展示了如何使用二进制和十六进制数字系统存储无符号整数以及字符的ASCII编码。本章我们将编写本书的第一个C程序,并使用gdb调试器来探究这些概念。

第3章讲述了无符号和有符号整数的加法和减法,并解释使用固定位数表示整数的限制。

第4章讲述了布尔代数运算符和函数,以及使用代数工具和卡诺图的函数最小化。

第5章从电子学简介开始,然后讨论逻辑门以及如何使用CMOS晶体管构建逻辑门。

第6章讨论了没有记忆功能的逻辑电路,包括加法器、译码器、复用器和可编程逻辑设备。

第7章讨论了具有记忆功能的时钟和非时钟逻辑电路,以及使用状态转换表和状态图的电路设计。

第8章讲述了存储器层级结构——云、大容量存储、内存、缓存、CPU寄存器。此外还讨论了寄存器、SRAM、DRAM的存储器硬件设计。

第 9 章概述了CPU子系统。本章还解释了指令执行周期和主要的x86-64寄存器,并展示了如何在gdb调试器中查看寄存器内容。

第 10 章讨论了由编译器生成的汇编语言版本和直接使用汇编语言编写的最小C函数。本章介绍了汇编器指令和CPU指令。我列举了一个使用gdb文本用户界面作为学习工具的例子。在章末还提供了AT&T语法的简要说明。

第 11 章讲述了在寄存器中传递参数、位置无关代码以及使用调用栈传递返回地址和创建自动变量。

第12章着眼于指令如何在比特级编码,还介绍了寻址模式和跳转指令,以及汇编器和链接器。

第13章介绍while、do-while、for、if-else和switch控制流结构的汇编语言实现。

第14章讲述了函数如何访问外部变量——全局变量、按值传递、按指针传递和按引用传递。本章总结了栈帧的结构。

第15章展示了递归的工作原理,还讨论了使用汇编语言通过函数或内联汇编访问高级语法无法直接触及的CPU硬件特性。

第16章讲述了位掩码、移位以及乘法和除法指令。

第17章解释了数组和记录(结构体)的实现方式以及在汇编语言层面的访问方法。

第18章展示了结构体如何用作C++对象。

第19章讲述了定点数和浮点数、IEEE 754标准以及部分SSE2浮点指令。

第20章将I/O与内存和总线时序进行比较。讲述了隔离I/O和内存映射I/O。本章概述了轮询式I/O编程,讨论了中断驱动I/O和直接内存访问。

第21章简要讲述了x86-64如何处理中断和异常。本章包括使用int 0x80和syscall在没有C运行时环境的情况下执行系统调用的例子。

高效使用本书

鉴于本书的组织形式,如果你遵循一些简单的指导方针,定能事半功倍。

许多章节的结尾都提供了练习,让你有机会实践章节的主要内容。这些只是练习,不是测试。事实上,我已经在我的GitHub主页(请搜索rgplantz)上给出了大部分练习的答案和我的解决方案。

如果你是将本书作为教材的教师,实在抱歉,你只能自己出考试题了。许多练习都有相当明显的拓展空间,教师可以据此设计课堂作业。

为了有效地利用这些练习,我推荐一种迭代方法。

(1)试着自己解决问题。花些时间思考,但是不要太久。

(2)如果不知道答案,看看我的解决方案。在某些情况下,我会在提供完整的解决方案之前给出提示。

(3)回到步骤(1),请教有经验的汇编语言程序员,看他们如何解决这个问题。

我强烈建议你做的一件事是自己输入代码。我相信这能帮助你更快地学习。如果不出意外,你不得不阅读代码中的每个字符。我认为从在线解决方案中复制和粘贴代码没有任何好处。说实话,本书中的程序没有什么实用性。这些代码是为了你自己动手练习而准备的,所以请本着这种精神使用代码。

这种实操方法也适用于前几章中的数学内容,包括在多种基数之间转换数字。虽然大多数计算器都能轻松实现数制转换,但转换并不是重点,重点是了解如何用位模式表示数值。我相信纸笔运算有助于你理解这些位模式。

在第1章中,我们将首先对计算机的主要子系统展开宏观的概述。然后,介绍如何在计算机上设置编程环境,以创建和运行本书中的程序。

资源与支持

资源获取

本书提供如下资源:

配套代码文件;

本书思维导图;

异步社区7天VIP会员。

要获得以上资源,您可以扫描下方二维码,根据指引领取。注意:部分资源可能需要验证您的身份才能提供。

提交勘误信息

作者、译者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区(www.epubit.com),按书名搜索,进入本书页面,点击“发表勘误”,输入勘误信息,点击“提交勘误”按钮即可(见下图)。本书的作者、译者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

与我们联系

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们。

如果您所在的学校、培训机构或企业想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接通过邮件发给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

关于异步社区和异步图书

“异步社区”是由人民邮电出版社创办的IT专业图书社区,于2015年8月上线运营,致力于优质内容的出版和分享,为读者提供高品质的学习内容,为作译者提供专业的出版服务,实现作者与读者在线交流互动,以及传统出版与数字出版的融合发展。

“异步图书”是异步社区策划出版的精品IT图书的品牌,依托于人民邮电出版社在计算机图书领域30余年的发展与积淀。异步图书面向IT行业以及各行业使用IT的用户。

第1章 预备知识

我们首先简要概述被视为由3个子系统组成的计算机硬件。其目的在于确保我们有一个公共框架来讨论事物的组织形式和结合形式。在该框架内,你将学习如何创建并执行一个程序。

本书涵盖了大量的编程内容。为了帮助你做好相关准备,本章用一节的篇幅,以作者的系统为例,讲述了如何搭建编程环境。

1.1 计算机子系统

你可以认为计算机硬件由3个独立的子系统组成:中央处理单元(Central Processing Unit,CPU)、内存(memory)[1]、输入/输出(Input/Output,I/O)。三者之间以总线相连,如图1-1所示。

[1] memory一词经常被翻译为“内存”,指可由CPU直接寻址访问的存储器(internal memory),但这种译法并不准确,因为还有flash memory这种存储设备。更准确的译法应该是“存储器”。在本书中,考虑用词习惯以及准确性,会根据上下文选择将该词译为“内存”或“存储器”。

图1-1 计算机子系统。CPU、内存、I/O子系统之间通过3根总线彼此通信

我们来依次了解一下各个部分:

CPU:控制内存和I/O设备之间往来的数据流。CPU对数据执行算术和逻辑运算,根据算术和逻辑运算的结果决定操作顺序。CPU还包含一部分容量很小的高速内存。

内存:为CPU和I/O设备提供易于访问的存储,用于存储CPU的指令及其处理的数据。

I/O:与外部环境以及大容量存储设备(例如,磁盘、网络、USB、打印机)通信。

总线:一种物理通信路径,其协议明确规定了该路径的使用方式。

如图1-1中的箭头所示,信号可以在总线上双向流动。地址总线用于指定内存位置或I/O设备。程序数据和指令在数据总线上流动。控制总线上的信号指定了各个子系统应该如何使用其他总线上的信号。

图1-1所示的总线代表必须在3个子系统之间传递的信号的逻辑分组。特定总线实现可能不会为每种总线设计独立的物理路径。举例来说,如果你在计算机中安装过显卡,它可能使用的是PCI-E(代表peripheral component interconnect-express)总线。PCI-E总线上相同的物理连接会在不同的时间传送地址和数据信号。

1.2 程序执行

程序由一系列存储在内存中的指令组成。在创建新程序时,你要使用编辑器编写源代码,多使用高级语言(例如,C、C++或Java)。编辑器将新程序的源代码(通常存储为磁盘文件)视为数据。然后使用编译器将高级语言语句转换成机器代码指令(同样存储为磁盘文件)。和编辑器一样,编译器将源代码和最终的机器指令视为数据。

在执行程序时,CPU将磁盘文件中的机器代码指令载入内存。大多数程序包含的一些常量数据也一并被读入内存。CPU通过读取[通常称为提取(fetching)]并执行内存中的指令来运行程序。此外还会根据程序的需要提取数据。

当CPU准备好执行程序的下一条指令时,该指令在内存中的位置会被放在地址总线上。CPU还会将读信号放在控制总线上。内存子系统则将指令放在地址总线上,由 CPU 随后复制。如果 CPU被指示从内存中读取数据,则同样的事件序列会再次发生。

如果CPU被指示将数据存入内存,那么它会将数据放在数据总线上,将保存数据的内存地址放在地址总线上,将写信号放在控制总线上。内存子系统则将数据总线上的数据复制到指定的内存位置。

这种“编辑-编译-执行”方案有多种变体。解释器是将编程语言转换成机器指令的程序,但不是将指令保存在文件中,而是立即执行。另一种变体是编译器将编程语言转换成中间速记语言,并将其保存在可以由解释器执行的文件中。

大多数程序还会访问I/O设备。有些是为了实现人机交互,例如,键盘、鼠标、屏幕。有些是为了机器可读的I/O,例如,磁盘。I/O设备要比CPU和内存慢得多,而且时序特性差异很大。由于其时序特性,I/O设备与CPU和内存之间的数据传输必须明确编程。

I/O设备编程要求全面理解设备的工作原理及其与CPU和内存的交互方式。我们将在本书接近尾声的时候介绍一些一般性概念。同时,书中编写的几乎每个程序至少都会用到终端屏幕,这是一种输出设备。操作系统包含可执行I/O的函数,C运行时环境(C runtime environment)提供了一个面向应用程序的函数库来访问操作系统的I/O函数。我们将使用这些C库函数来执行大部分的I/O操作,I/O编程相关的主题可以参阅其他更高阶的书籍。

上述内容旨在为你提供计算机硬件组织形式的概览。在更深入地探究这些概念之前,1.3 节会先帮助你设置好本书余下部分要用到的编程工具。

1.3 编程环境

在本节中,我将描述如何设置自己的计算机来完成本书中的所有编程任务。你可以根据使用的Linux发行版和个人偏好选择不同的设置方式。

我使用Ubuntu 20.04 LTS桌面版自带的GNU编程工具创建和执行本书中的程序,该发行版既作为主力操作系统,也作为Windows Subsystem for Linux下运行的操作系统。你可以在Ubuntu的网站免费下载它,其自带的编译器gcc和g++版本为9.3.0,汇编器as的版本为2.34。

你可能刚接触Linux命令行。在我们讲解程序的同时,我会展示用于创建这些程序的命令,不过这些只是一些基础知识而已。如果你花些时间熟悉命令行的使用,必将获益匪浅。William Shotts所著的The Linux Command Line, Second Edition(No Starch Press, 2019)是一本不错的参考资料。

你还应该熟悉Linux提供的编程工具文档。最简单的就是大多数程序中内置的帮助系统。你可以通过输入命令名和--help选项访问帮助系统。例如,gcc --help会显示gcc的命令行选项列表以及各个选项的简要描述。

大多数Linux程序都包含手册,通常称为手册页,它提供了比帮助系统更完备的文档。只需输入man命令以及程序名称就可以阅读手册页。例如,man man会显示man程序的手册页。

GNU程序甚至还自带了更丰富的文档,可以通过输入info命令以及程序名称进行阅读。例如,info info会显示info程序的文档,如下所示:

Next: Stand-alone Info, Up: (dir)
 
Stand-alone GNU Info
********************
 
This documentation describes the stand-alone Info reader which you can
use to read Info documentation.
 
    If you are new to the Info reader, then you can get started by typing
'H' for a list of basic key bindings. You can read through the rest of
this manual by typing <SPC> and <DEL> (or <Space> and <Backspace>) to
move forwards and backwards in it.
 
* Menu:
 
* Stand-alone Info::            What is Info?
* Invoking Info::               Options you can pass on the command line.
* Cursor Commands::             Commands which move the cursor within a node.
* Scrolling Commands::          Commands for reading the text within a node.
* Node Commands::               Commands for selecting a new node.
* Searching Commands::          Commands for searching an Info file.
* Index Commands::              Commands for looking up in indices.
* Xref Commands::               Commands for selecting cross-references.
* Window Commands::             Commands which manipulate multiple windows.
* Printing Nodes::              How to print out the contents of a node.
* Miscellaneous Commands::      A few commands that defy categorization.
* Variables::                   How to change the default behavior of Info.
* Colors and Styles::           Customize the colors used by Info.
* Custom Key Bindings::         How to define your own key-to-command bindings.
* Index::                       Global index.
 
-----Info: (info-stnd)Top, 31 lines --All-------------------------------------------
Welcome to Info version 6.7. Type H for help, h for tutorial.

以*起始并以::结尾的条目是指向其他info页的超链接。使用键盘上的方向键将光标定位在此类条目并按ENTER键就可以跳转到该页面。

要想获取info文档,必须安装以下Ubuntu包。

binutils-doc:为GNU汇编器as(有时也称为gas)添加文档。

gcc-doc:为GNU gcc编译器添加文档。

根据你使用的Linux发行版,需要安装的包可能会不一样。

在大多数例子中,我在编译程序的时候没有开启优化(-O0选项),因为我们的目标是学习概念,而不是生成最高效的代码。这些示例应该可以在任何安装了gcc、g++、as的x86-64 GNU开发环境中正常运行。但是,编译器生成的机器码可能会因特定的配置和版本而有所不同。你会在本书的中间部分看到编译器生成的汇编语言。在你继续阅读本书的其余部分时,任何差异都应该是一致的。

编程的时候还要用到文本编辑器。不要使用字处理器。字处理器会添加很多隐藏的控制字符来格式化文本。这些隐藏字符会干扰编译器和汇编器,使其无法正常工作。

有一些不错的Linux文本编辑器可供选择,它们各有特色。我喜欢的编辑器不时变化。我建议你多尝试几种,选择你喜欢的那款。

我用过的文本编辑器如下。

nano:大多数Linux发行版都自带的一款简单的文本编辑器,采用命令行用户界面。文本会被直接插入编辑器。CTRL和meta键用于指定文本操作的组合键。

vi:所有的Linux(和UNIX)系统应该都有安装,采用面向模式的命令行用户界面。通过键盘命令操作文本。有些命令可以将vi置于文本插入模式。ESC键用于返回命令模式。大多数Linux发行版自带了vim(Vi IMproved),添加了有助于程序源代码编辑的各种特性。

emacs:采用命令行用户界面。文本被直接插入编辑器。CTRL和meta键用于指定文本操作的组合键。

gedit:GNOME桌面提供的文本编辑器,采用图形用户界面,如果你用过字处理器,应该不会陌生。

kate:KDE 桌面提供的文本编辑器,采用图形用户界面,如果你用过字处理器,应该不会陌生。

Visual Studio Code:Microsoft推出的免费编辑器,可以在Windows 7/8/10、Linux和macOS上运行,采用图形用户界面,可用于编辑远程服务器上的文本文件和安装Windows Subsystem for Linux。此外还允许打开命令终端面板。

vi和emacs也提供了图形用户界面。

就本书涉及的编程而言,上述以及很多其他文本编辑器都是不错的选择。没必要花费过多的时间去挑选“最好的”。

动手实践

确保弄清楚你用来编程的计算机的配置。它使用的是什么CPU?内存多大?连接了哪些I/O设备?你打算用哪款编辑器?

1.4 小结

中央处理单元(CPU 该子系统控制着计算机的大部分活动。它还包含一部分容量很小的高速内存。

内存 该子系统为程序和数据提供存储。

输入/输出(I/O 该子系统提供了与外界以及大容量存储设备通信的手段。

总线 CPU、内存、I/O之间的通信路径。

程序执行 概述了程序执行时3个子系统和总线的工作方式。

编程环境 介绍了如何设置本书所需的编程工具。

在第2章中,你将开始学习数据在计算机中是如何存储的,了解C语言编程以及如何将调试器作为一种学习工具。

相关图书

Joy RL:强化学习实践教程
Joy RL:强化学习实践教程
成为GPT高手
成为GPT高手
高并发系统:设计原理与实践
高并发系统:设计原理与实践
DeepSeek极速上手 :高效做事不内耗
DeepSeek极速上手 :高效做事不内耗
AI设计:Midjourney绘画设计教程
AI设计:Midjourney绘画设计教程
AI高手速成 DeepSeek让你工作变轻松
AI高手速成 DeepSeek让你工作变轻松

相关文章

相关课程