深入理解计算机系统期末复习

深入理解计算机系统期末复习

第一章 计算机系统漫游

hello 程序的生命周期
1、被程序员创建
2、在系统上运行
3、输出简单消息
4、终止

1.1 信息就是位+上下文

名词解释:
1、计算机系统是由硬件和系统软件组成的,它们共同工作来运行应用程序。
2、hello.c源文件:程序员利用编辑器创建并保存的文本文件。
源程序:实际上是一个由值0和1组成的位序列。
位、字节 :8个位被组织成一组,称为字节。每个字节表示程序中某个文本字符。
上下文:
文本文件:只由ASCII字符构成的文件称为文本文件。所有其他文件都称为二进制文件。

简答题:C语言为什么会成功呢?
1、C语言与Unix操作系统关系密切
2、C语言小而简单
3、C语言是为实践目的设计的

1.2 程序被其他程序翻译成不同的格式

名词解释题
1、目标程序
2、编译系统

简答题:
将hello.c翻译成可执行目标程序hello
翻译源程序的过程(4个阶段)
在这里插入图片描述

$预处理阶段:预处理程序(cpp)根据以#开头的命令,修改原始的C程序。通常以.i为文件扩展名。
$编译阶段:编译器(ccl)将文本文件hello.i翻译成文本文件hello.s,它还包含一个汇编语言程序。汇编语言程序中的每条语句都以一种标准的文本格式确切地描述了一条低级机器语言。汇编语言非常有用,因为它为不同高级语言的不同编译器提供了通用的输出语言。
$汇编阶段:汇编器(as)将hello.s翻译成机器语言指令,将这些指令打包成一种叫做 可重定位目标程序 的格式,并将结果保存在目标文件 hello.o中,hello.o文件是一个二进制文件,它的字节编码是机器语言指令而不是字符。如果在文本编辑器中打开hello.o文件,看到的将是一堆乱码。
$链接阶段:hello程序调用了printf函数,它是每个C编译器都会提供的标准C库中一个函数。printf函数存在于printf.o的单独的预编译好了的目标文件中,而这个文件必须以某种方式合并到我们的hello.o程序中。链接器(ld)就负责处理这种合并。结果就得到hello文件,它是一个可执行目标文件(可执行文件),可以被加载到内存中,由系统执行

1.3 了解编译系统如何工作是有大益处的

	优化程序性能
	理解链接时出现的错误
	避免安全漏洞

1.4 处理器读并解释存储在存储器中的指令

在Unix系统上运行可执行文件hello,将文件名输入到外壳:
unix>./hello
hello,world
unix>
名词解释:
1、外壳(shell):外壳是一个命令行解释器,它输出一个提示符,等待你输入一个命令行,然后执行这个命令。
如果该命令行的第一个单词不是一个内置的外壳命令,那么外壳就会假设这是一个可执行文件的名字,它将加载并运行这个文件。

操作系统的Shell(外壳)有2种:
GUI(图形用户界面) shell
命令行shell

Windows中的命令行shell两种
Command shell(cmd)
PowerShell

1.4.1 系统的硬件组成

在这里插入图片描述

名词解释
1、总线:贯穿整个系统的是一组电子管道,称为总线。
······它携带信息字节并负责在各个部件间传递。
·······通常总线被设计成传送定长的字节块,也就是字。字中的字节数(即字长)是一个基本的系统参数,在各个系统中的情况都不尽相同。现在的大多数机器字长有的是4个字节(32位),有的是8个字节(64位)。为了讨论方便,假设字长为4个字节,并且总线每次只传送1个字。
2、位:计算机中存储信息的最小单位。
3、字节:计算机中存储信息的基本单位。8个二进制位为一个字节。
4、字:计算机处理信息的基本单位。其大小取决于计算机体系结构和操作系统。
5、字长:计算机处理器一次能处理的二进制数据的位数。
6、I/O设备:是系统与外部世界的联系通道。
··········每个I/O设备都通过一个控制器或适配器与I/O总线相连。控制器和适配器之间的区别主要在于它们的封装方式。
··········控制器是置于I/O设备本身的或者系统的主印刷电路板(通常为主板)上的芯片组,而适配组则是一块插在主板插槽上的卡。
——————-它们的功能都是在I/O总线和I/O设备之间传递消息。
7、主存:是一个临时存储设备,在处理器执行程序时,用来存放程序和程序处理的数据。
—————-从物理上来说,主存是由一组 动态随机存储器(DRAM)芯片组成的。
——————从逻辑上来说,存储器是一个线性的字节数组,每个字节都有其唯的地址(即数组索引),这些地址是从零开始的。
——————一般来说,组成程序的每条机器指令都由不同数量的字节构成。与C程序变量相对应的数据项的大小是根据类型变化的。
8、处理器:中央处理单元(CPU),简称处理器,是解释(或执行)存储在主存中指令的引擎。
—————-处理器的核心是 一个字长的存储设备(或寄存器),称为程序计数器(PC)。在任何时刻,PC都指向主存中的某条机器语言指令(即含有该条指令)。
—————-从系统通电开始,直到系统断电,处理器一直在不断地执行程序计数器指向的指令,再更新程序计数器,使其指向下一条指令。处理器看上去是按照一个非常简单的指令执行模型来操作的,这个模型是由指令集架构决定的。在这个模型中,指令按照严格的顺序执行,而执行一条指令包含执行一系列的步骤。处理器从PC指向的存储器处读取指令,解释指令中的位,执行该指令指示的简单操作,然后更新PC,使其指向下一条指令,而这条指令不一定与存储器中刚刚执行的指令相邻。
——————这样的简单操作是围绕着主存、寄存器文件和算数、逻辑单元(ALU)进行的。
——————-寄存器文件:是一个小的存储设备,由一些1字长的寄存器组成,每个寄存器都有唯一的名字。
——————- ALU计算新的数据和地址。

简答题
理解运行hello程序时发生了什么

简单操作,CPU在指令的要求下可能会执行哪些操作?
1、加载:把一个字节或者一个字从主存复制到寄存器,以覆盖寄存器原来的值。
2、存储:把一个字节或者一个字从寄存器复制到主存的某个位置,以覆盖这个位置上原来的内容。
3、操作:把两个寄存器的内容复制到ALU,ALU对这两个字做算术操作,并将结果存放到一个寄存器中,以覆盖该寄存器原来的内容。
4、跳转:从指令本身中抽取一个字,并将这个字复制到PC中,以覆盖PC中原来的值。

区分处理器的指令集架构和微体系结构:
指令集架构描述的是每条机器代码指令的效果;
微体系结构描述的是处理器实际上是如何实现的。

1.4.2 运行hello程序

在这里插入图片描述
在这里插入图片描述

简答题:

运行hello程序过程:
1、从键盘上读取hello命令
2、从磁盘加载可执行文件到主存
3、将输出字符串从内存写到显示器

1.5 高速缓存至关重要

在这里插入图片描述
针对处理器与主存之间的差异,系统设计者采用了更小的、更快的设备,即高速缓存存储器(简称高速缓存)

1.6 存储设备形成层次结构

在这里插入图片描述
简答题:
存储器层次结构的主要思想是一层上的存储器作为低一层存储器的高速缓存。

1.7 操作系统管理硬件

可以把操作系统看作是应用程序和硬件之间插入的一层软件。
所有应用程序对硬件的操作尝试都必须通过操作系统。

在这里插入图片描述
操作系统有2个基本功能:
1、防止硬件被失控的应用程序滥用
2、向应用程序提供一种简单一致的机制来控制复杂而又通常大相径庭的低级硬件设备。

操作系统通过几个抽象概念(进程,虚拟器存储器,文件)来实现这两个功能:
文件是对I/O设备的抽象表示
虚拟存储器是对主存和磁盘I/O设备的抽象表示
进程是对处理器、主存、I/O设备的抽象表示。

1.7.1 进程

名词解释
进程:进程是操作系统对一个正在运行的程序的一种抽象。

实际上CPU是在同时或者交替地执行不同的进程。

操作系统保持跟踪进程所需的所有状态信息。这种状态,也就是上下文。它包括许多信息,例如PC和寄存器文件的当前值,以及主存的内容。在任何时刻,单处理系统都只能执行一个程序的代码。当操作系统决定要把控制权从当前进程转移到某个新进程时,就会进行上下文切换,即保存当前进程的上下文、恢复新进程的上下文,然后将控制权传递到新进程。新进程会从上次停止的地方开始。图1-12展示了示例hello程序运行的基本理念。
在这里插入图片描述

1.7.2 线程

在现代系统中,一个进程实际上可以由多个称为线程的执行单元组成,每个线程都运行在进程的上下文中,并共享同样的代码和全局数据。由于网络服务器对并行处理的需求,线程称为越来越重要的编程模型,因为多线程之间比多进程之间更容易共享初级,线程一般来说比进程更高效。

操作系统提供的抽象表示
进程
线程
虚拟存储器
文件

1.7.3 虚拟存储器

是一个抽象概念,它为每个进程提供了一个假象,即每个进程都在独立地使用主存。每个进程看到的是一致的存储器, 称为 虚拟地址空间。

在这里插入图片描述在这里插入图片描述

1.7.4 文件

名词解释:
文件:就是字节序列。
EG:每个I/O设备,包括磁盘,键盘,显示器,甚至网络,都可以视为文件。

1.8 系统之间利用网络通信

从单独的系统来看,网络可视为一个I/O设备。
在这里插入图片描述

解答题:
(登陆远程主机并运行外壳后,远端的外壳在等待接受输入命令)远程运行hello程序的5个基本步骤
1、用户在telnet客户端在键盘上输入“hello”
2、本地客户端向telnet服务器发送字符串“hello”
3、服务器从网络上接收到字符串,向外壳发送字符串“hello”,外壳运行hello程序并将输出发送给telnet服务器
4、服务器通过网络向客户端发送字符串“hello world\n”
5、客户端在显示器上打印“hello world\n”
在这里插入图片描述

1.9 重要主题

名词解释:
并发:指一个同时具有多个活动的系统
并发则是一种通过交替执行多个任务来提高系统响应性的技术。

并行:指的是同时执行多个任务以加快系统运行速度

  1. 线程级并发

线程级并发是指在一个计算机系统中同时执行多个线程(或进程)的能力。在多线程编程中,多个线程可以并行执行,每个线程都可以独立执行不同的任务。这种并发可以通过操作系统的线程调度器实现,它能够将不同的线程分配到不同的处理器核心上,从而实现并行执行。线程级并发可以提高系统的吞吐量和响应性,并充分利用多核处理器的性能。

  1. 指令级并行
    指令级并行是指在一个处理器内部同时执行多条指令的能力。现代处理器通常采用流水线(pipeline)技术,将指令的执行过程划分为多个阶段,并同时执行不同阶段的多条指令。这样可以在一个时钟周期内完成多条指令的执行,提高处理器的效率。指令级并行可以通过流水线技术、超标量处理器、乱序执行等技术来实现。

流水线

超标量:如果处理器可以达到比一个周期一条指令更快的执行效率,称为超标量处理器。

  1. 单指令、多数据并行
    在最低层次上,许多现代处理器拥有特殊的硬件,允许一条指令可以产生多个并行执行的操作,这种方式称为单指令、多数据,即SIMD并行。

简答题
1、提供这些SIMD指令是为啥?
多是为了提高处理影像、声音、视频数据应用的执行速度。

2、超线程和并发的区别

超线程和并发是两个经常被提及但含义不同的概念。

  1. 超线程 (Hyperthreading): 超线程是一种CPU技术,它允许单个物理核心同时处理两个线程,从而实现逻辑上的双核处理器。这种技术通过复制处理器的状态来实现并行执行。但值得注意的是,两个线程并不能始终在同一个CPU核心上并行执行,只有当它们需要执行的指令不使用相同的CPU资源时,才能真正地并行。例如,Intel的超线程技术一直都是SMT2,也就是一个物理核心虚拟出两个核心。

  2. 并发 (Concurrency): 并发则是一种编程模型,它允许多个任务在同一时间段内启动、运行和完成。这并不意味着这些任务是真正并行的,而是在一个特定的时间段内,这些任务都被“同时”考虑或处理。并发可以通过多线程或多进程来实现。多线程是Java等编程语言中的一个特性,而多进程则是操作系统级别的概念。

简而言之,超线程是一种硬件技术,用于在单个物理核心上模拟多个逻辑核心,从而在一定程度上实现并行处理。而并发是一种软件或系统级的技术,用于管理和调度多个任务,使它们在某一个时间段内看起来像是同时运行的。
a
在这里插入图片描述

1.10 小结

简答题

  1. 计算机系统组成 答:由硬件和系统软件组成,它们共同协作以运行应用程序。
  2. 为什么将系统中的存储设备划分成层次结构
    答:因为计算机把大量的时间用于存储器、I/O设备和CPU寄存器之间复制数据
  3. 处理器读取并解释存放在主存力的二进制指令。
  4. 操作系统的内核是什么媒介和提供3个基本的抽象?
    答:操作系统内核是应用程序和硬件之间的媒介。
    抽象:
    1) 文件是对I/O设备的抽象
    2)虚拟存储器是对主存和磁盘的抽象
    3)进程是对处理器、主存和I/O设备的抽象。
  5. 网络提供的手段
    计算机系统之间通信的手段。
    从特殊系统的角度来看,网络就是一种I/O设备。

第二章 信息的表示和处理

2.1 信息存储

名词解释
字节:最小的可寻址的存储器单位
虚拟存储器:机器级程序将存储器视为一个非常大的字节数组,称为虚拟存储器。
地址:存储器的每个字节都有一个唯一的数字来标识,称为它的地址。
虚拟地址空间:所有可能地址的集合。
只是一个展现给机器级程序的概念性映像。

二进制、八进制、十进制、十六进制

进制转换
计算题:
在这里插入图片描述

2.1.2 字

名词解释:

程序对象:程序数据、指令、控制信息

字:每台计算机都有一个字长,指明整数和指针数据的标称大小。因为虚拟地址是以这样的一个字来编码的,所以字长决定的重要参数就是虚拟地址空间的最大大小。也就是说,对于一个字长为w位的机器而言,虚拟地址的范围为0-2w-1,程序最多访问2w个字节。

2.1.4 寻址和字节顺序

大端法:
小端法:
双端法:

简答题:
在什么时候字节顺序会成为问题?
在这里插入图片描述
在这里插入图片描述

信息的表示

信息:“位”➕上下文

二进制值是计算机编码、存储和操作信息的核心。

位向量:有固定长度为w,由0和1组成的串。

位向量的运算可以定义成参数的对应元素之间的运行。

位向量的应用:表示有限集合。集合编码。
位级运算的常见用法:实现掩码运算。

逻辑运算符:||,&&,! 非0参数表示TRUE 参数0标记FALSE 返回1或0 。
如果第一参数求值就能确定表达式的结果,那么逻辑运算符就不会对第二个参数求值。

移位运算:
逻辑左移
逻辑右移
算术右移

第三章 程序的机器级表示

3.1

GCC C语言编译器以汇编代码的形式产生输出,汇编代码是机器代码的文本表示,给出程序中的每一条指令。然后GCC调用汇编器和链接器,从而根据汇编代码生成可执行的机器代码。

填空:
存储器系统的实现是将___多个硬件存储器___和___操作系统软件___组合起来。

汇编代码表示非常接近机器代码。与机器代码的二进制格式比,一个主要的特点是它用___可读性更好的文本格式___来表示。

能够理解___汇编代码___以及___它与原始C代码___的联系,是理解计算机如何
执行程序的关键一步。

IA32机器码和C源代码非常不一样:
能获取到一些在C程序中看不到的处理器状态,比如:
Program Counter (PC): 程序计数器
Register File (RF): 寄存器堆
Condition Code (CC) register: 条件码寄存器
一些用于存储浮点数的浮点数寄存器

对待内存的方式:
C语言中可以声明和分配不同数据类型的对象,存储到内存
机器码将内存视为一个大的、字节可寻址的数组,不会区分数据类型

IA32机器代码和原始的C代码差别非常大。一些通常对C语言程序员隐藏的处理器状态是可见的:

  1.  程序计数器(IA32中,通常称为“PC”,用%eip表示)指示将要执行的下一条指令在存储器中的地址
    
  2. 整数寄存器文件包含8个命名的位置,分别存储32位的值。这些寄存器可以存储地址(对应C语言的指针)或整数数据。有的寄存器被用来记录某些重要的程序状态,而其他的寄存器则用来保存临时数据,例如过程的局部变量和函数的返回值。
  3. 条件码寄存器保存着最近执行的算术或逻辑指令的状态信息。它们用来实现控制或数据流中的变化,比如用来实现if 、while语句。
  4. 一组浮点寄存器存放浮点数据。

机器代码只是简单地将___存储器___看成一个___很大的、按字节寻址的数组___。

C语言中的聚合数据类型,例如:数组和结构,___在机器代码中用连续的一组字节___来表示。
名词解释:

机器级语言
机器码

编译器
汇编器
链接器

2种主流机器语言(指令集架构)
指令集架构(ISA)
———Intel Architecture 32 (IA-32)
———AMD64 (x86-64)

简答题:
为什么学习机器层的语言?

  1. 为了能更了解计算机底层的运作原理
  2. 能更了解自己的程序可以被编译器优化到什么程度,因而能更了解自己代码的效率
  3. 反向工程,黑客、破解方法

历史视角:
1978年:8086, 8087, 8088; -》 x86(16位)架构
1982年:80286
1985年:80386; -》 x86(32位) — IA-32架构
至2002年:各种型号处理器陆续推出,延用IA-32架构,世纪末进入瓶颈期
2003年:AMD推出AMD64,扩展、兼容IA-32架构,后被因特尔采用,添加了一些其它功能后改成Intel-32,后又称x86-64
至今因特尔处理器基本都延用x86-64

对于机器级编程重要的两种抽象?

答:

  1. 机器级程序的格式和行为,定义为指令集体系结构,它定义了处理器状态、指令的格式、以及每条指令对状态的影响。
  2. 机器级程序使用的存储器地址是虚拟地址,提供的存储器模型看上去是一个非常大的字节数组。

程序编码(IA-32)
编译
编译命令
gcc -O1 -o p p1.c p2.c
-O0, -O1, -O2, -O3
编译过程:
C预处理器 -> 编译器 -> 汇编程序(汇编器) -> 链接器
a.c ------> a.c (扩充)------>a.s------------------------->a.o -----------> a.exe

编译器根据指令集架构(ISA)来编译
根据处理器的指令集架构(ISA),编译器将相对抽象的C语言执行模型转换为处理器执行的非常基本的指令。
a.c ------> a.c (扩充)------>a.s------------------------->a.o -----------> a.exe
相同的C源文件,根据不同的ISA会导致产生哪些不同的文件?
从a.s(包括a.s)开始就不一样了
相同的汇编文件,根据不同的ISA编译会怎样?
从a.o(包括a.o)开始不一样

汇编代码和机器代码是非常接近的(每行对应一条二进制指令)

IA32的程序内存(Program memory)
程序内存(Program memory)
可执行机器码
运行时堆栈(run-time stack)
用户分配的内存块
还有操作系统需要的一些信息…

机器指令
单个机器指令只执行非常基本的操作:
将存储在寄存器中的两个数字相加
在内存和寄存器之间传输数据
有条件地跳转到新的指令地址

编译器必须生成这样的指令序列来实现程序结构

gcc的优化选项-O
O0选项不进行任何优化,在这种情况下,编译器尽量的缩短编译消耗(时间,空间),此时,debug会产出和程序预期的结果。当程序运行被断点打断,此时程序内的各种声明是独立的,我们可以任意的给变量赋值,或者在函数体内把程序计数器指到其他语句,以及从源程序中 精确地获取你期待的结果

O1优化会消耗稍多的编译时间,它主要对代码的分支,常量以及表达式等进行优化。

O2会尝试更多的寄存器级的优化以及指令级的优化,它会在编译期间占用更多的内存和编译时间。

O3在O2的基础上进行更多的优化,例如使用伪寄存器网络,普通函数的内联,以及针对循环的更多优化。

检查我们生成的汇编文件
我们想知道编译器对code.c生成了怎样的汇编程序:-S选项
gcc -O1 -S code.c

编译成二进制文件:-c选项
gcc -O1 –c code.c

查看二进制文件
直接打开查看
HxD
用反汇编程序查看
objdump
选项:-d(反汇编), -s(显示节信息), -x(显示头部信息和全局符号表)
比如
objdump -d code.o
objdump -sxd code.o

3.3数据格式

由于是从16位体系结构扩展成32位的。后面遇到的大多数指令都是对字节或双字操作的。
Intel用术语字表示16位数据类型
字:16位数据类型 (w)
双字:32位(l)
:普通整数(int) 长整数(long int) char*(四字节的双字)
四字:64位
在这里插入图片描述
字符后缀:表明操作数的大小

3.4 访问信息

一个IA32中央处理单元(CPU)包含一组8个存储32位值的寄存器。
这些寄存器用来存储整数数据和指针。
在这里插入图片描述

3.4.1 操作数指示符

大多数指令有一个或多个操作数,指示出执行一个操作中要引用的原数据值,以及放置结果的目标位置。
操作数
立即数
寄存器
存储器
0x123表示内存地址为0x123的记忆单元保存的值
(%eax)表示内存地址为%eax的记忆单元保存的值
Imm(Eb,Ei,s)表示内存地址为Eb+Ei*s+Imm的记忆单元保存的值。
Eb在这里称为基址寄存器,Ei为变址寄存器,s为比例因子
带括号的寻址都为这种内存寻址形式的特例

计算题3.1

3.4.2 数据传送指令

练习题3.2

3.4.3 数据传送示例

书中的“过程”指的就是函数

练习题3.5

3.5 算术和逻辑操作

3.5.1 加载有效地址(leal)

lea :Load effective address
leal S,D
计算S的地址,存入D(不加载地址S的存储器数据)
movl S,D 则会在计算S的地址后,从存储器地址S处读取数据到D
比如:

	movl 1234(%eax,%ebx,8),%ecx
	相当于下面两行指令:
	lea 1234(%eax,%ebx,8),%ecx
	movl (%ecx),ecx
因此也可以利用它简洁地描述算术操作,比如:
		指令leal  7(%edx,%edx,4),%eax将设置寄存器%eax的值为5x+7 。

练习题3.6

3.5.2 一元和二元算术、逻辑运算

3.5.3 移位操作

练习题3.8

练习题3.9

练习题3.10

3.5.5 特殊的算术操作

3.6 控制

3.6.1 条件码

3.6.2 访问条件码

3.6.3 跳转指令及其编码

第四章 处理器体系结构

  1. 为什么学习处理器的工作原理?
  • 富有智识趣味和重要性
    • 深入了解事物的运作具有内在价值,特别是: 计算机科学家和工程师日常生活中如此重要的系统的内部运作对许多人来说仍然是个谜。 处理器设计体现了许多优秀工程实践的原则。它需要创建一个简单且有规律的结构来执行复杂任务。
  • 理解处理器如何工作有助于理解整个计算机系统如何工作
  • 设计嵌入式系统必须了解处理器如何工作
  • 有可能设计处理器
  1. 怎样学习处理器的工作原理
    概念:指令集架构

指令集体系结构:一个处理器支持的指令和指令的字节级编码称为它的指令集体系结构。

指令被编码为由一个或多个字节序列组成的二进制格式。

Y86指令集架构:定义各种状态元素、指令集和它们的编码、一组编程规范和异常事件处理。

流水线化的处理器:
这个处理器将每条指令的执行分解为5步。每个步骤由一个独立的硬件部分或阶段来处理。指令步经流水线的各个阶段,且每个时钟周期有一条新指令进入流水线。所以处理器可以同时执行五条指令的不同阶段。为了使这个处理器保留Y86 ISA的顺序的性质,就要求处理很多冒险或冲突 情况。

冒险:就是一条指令的位置或操作数依赖于其他仍在流水线中的指令。

4.1 .1 程序员可见状态

名词解释:

  1. 程序可见状态:Y86程序中的每条指令都会读取或修改处理器状态的某些部分。这称为程序可见状态。
     	这里的“程序员”既可以是用汇编代码写程序的人,也可以是机器级代码的编译器。
    
  2.  Y86的处理器状态类似于IA32 。
     有8个程序寄存器:%eax,%ecx,%edx,%ebx,%esi,%edi,%esp,%ebp
     处理器的每个程序寄存器存储一个字。
     寄存器%esp被入栈、出栈、调用和返回指令作为栈指针。
     在其他情况中,寄存器没有固定的含义或固定值。
     有3个1位的条件码:ZF,SF,OF,它们保存最近的算术或逻辑指令所造成影响的有关信息。
     程序计数器(PC)存放当前正在执行指令的地址。
    
  3.  程序寄存器堆(RF):每个寄存器保存一个32位的字。
    

在这里插入图片描述

存储器:从概念上来说就是一个很大的字节数组,保存着程序和数据。
Y86程序用虚拟地址来引用存储器位置。
硬件和操作系统软件联合起来将地址翻译成实际或物理地址,指明数据实际保存在存储器中哪个地方。

程序状态的最后一个部分是状态 码Stat,它表明程序执行的总体状态。它会指示是正常运行还是出现了某种异常。

4.1 .2 Y86指令集

在这里插入图片描述

这个指令集就是处理器实现的目标。
Y86指令集基本上是IA32指令集的一个子集。它只包括四字节整数操作,寻址方式比较少,操作也比较少。因为只有四字节数据,所以称之为“字”不会有任何歧义。上图中,左边是指令的汇编码表示,右边是字节编码。汇编代码格式类似于IA32的ATT格式。

Y86指令集。指令编码长度从1个字节到6个字节不等。一条指令含有一个单字节的指令指示符,可能含有一个单字节的寄存器指示符,还可能含有一个四字节的常数字。字段fn指明是某个整数操作(opl),数据移动条件(cmovxx)或是分支条件(jxx)。所有的数值都用十六进制表示。

不同Y86指令的更多细节:
****IA21的movl指令分成了4个不同的指令:irmovl,removal,mrmovl,rmmovl
************ 分别显示地指明源和目的的格式。源可以是立即数(i),寄存器(r)或存储器(m)。指令名字的第一个字母就表明了源的类型。目的可以是寄存器(r)或存储器(m)。指令名字的第二个字母指明了目的类型。在决定如何实现数据传送时,显示地指明数据传送的这4种类型是很有帮助的。
************两个存储器传送指令中的存储器引用方式是简单的基址和偏移量形式。在地址计算中,我们不允许第二变址寄存器和任何寄存器的伸缩。
************同IA32一样,不允许从一个存储器地址直接传送到另一个存储器地址。另外也不允许将立即数传送到存储器。
****有4个整数操作指令(opl)。addl,subl,andl,xorl。它们只对寄存器数据进行操作,而IA32还允许对存储器进行这些操作。这些指令会设置3个条件码ZF,SF,OF(零,符号和溢出)
****有7个跳转指令(jxx)。jmp,jle,jl,je,jne,jge和jg。根据分支指令的类型和条件码的设置来选择分支。
****有6个人条件传送指令(cmovxx):cmovle,cmovl,cmove,cmovge,comvg。这些指令的格式与寄存器-寄存器传送指令rrmovl一样,但是只有大哥条件码满足所需要的约束时,才会更新目的寄存器的值。
**** call指令将返回地址入栈,然后跳转到目的地址。ret指令从这样的过程调用中返回。
**** pushl和popl指令实现了入栈和出栈,就像在IA32中一样。
****halt指令停止指令的执行。IA32中国有一个与之相当的指令hlt。IA32的应用程序不允许使用这条指令,因为它会导致整个系统暂停运行,对于Y86来说,执行halt指令会导致处理器停止,并将状态码设置为HLT。

4.1 .3 指令编码。

	指令的字节级编码。每条指令需要1~6个字节不等,这取决于需要哪些字段。每条指令的第一个字节表明指令的类型。这个字节分为2部分,每部分4位:高位是代码部分,低位时功能部分。功能值只用在一组相关指令共用一个代码时才有用。

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

Y86中寄存器编号跟IA32中的相同。程序寄存器存在CPU中的一个寄存器文件中,这个寄存器文件就是一个小的,以寄存器ID作为地址的随机访问存储器。

分支指令和调用指令的目的地址是一个绝对地址,而不是像IA32那样使用PC相对寻址方式。处理器使用相对寻址方式,分支指令会更简洁,同时这样也能允许代码从存储器的一部分复制到另一部分,而不需要更新所有的分支目标地址。因为更关心描述的简单性,所以就用了绝对寻址方式。同IA32一样,所有整数采用小端法编码。当指令按照反汇编格式书写时,这些字节就以相反的顺序出现。

指令集的一个重要性质:字节编码必须有唯一的解释。
任意一个字节序列要么是一个唯一的指令序列的编码,要么就不是一个合法的字节序列。Y86就具有这个性质,因为每条指令的第一个字节有唯一的代码和功能组合,给定这个字节,可以决定所有其他附加字节的长度和含义。这个性质保证了处理器可以以无二义性地执行目标代码程序。即使代码嵌入在程序的其他字节中,只要从序列的第一个字节开始处理,仍然可以很容易地确定指令序列。反过来说,如果不知道一段序列的起始位置,就不能准确地确定怎样将序列划分成单独的指令。对于试图直接从目标代码字节序列中抽取出机器级程序的反汇编程序和其他一些工具来说,这就带来了问题。
在这里插入图片描述

在这里插入图片描述

RISC和CISC区别:
在这里插入图片描述

4.2 逻辑电路设计和硬件控制语言( HCL )

大多数现代电路技术都是用信号线上的高电压或低电压来表示不同的位值。

数字系统

怎么表示0和1?
逻辑1是用1.0伏特左右的高电压表示的
逻辑0是用0.0伏特左右的低电压表示的

实现数字系统需要哪些主要部分?

  1. 计算对位进行操作的函数的组合逻辑
  2. 存储位的存储器元素
  3. 控制器元素更新的时钟信号
数字电路设计的演化

曾经(1970s)是怎么设计的?
手绘

现在是怎么设计的
使用硬件描述语言HDL。

硬件控制语言(HCL)

硬件控制语言( HCL ):描述电路的数据流和时序。

HCL是什么级别的抽象?用来描述什么抽象模型?

从HCL设计模型怎么得到电路设计?

数字电路的基本计算单元是什么?逻辑门

4.2.1 逻辑门电路

逻辑门只对单个位的数进行操作,而不是整个字。
逻辑门总是活动的。一旦一个门的输入变化了,在很短的时间内,输出就会相应地变化。

几种逻辑门类型和对应的HCL表达式:
And:a&&b
Or:a||b
Not:!a
在这里插入图片描述

4.2.2 组合电路和 HCL 布尔表达式

将多个逻辑门组合在一起,可以得到一个计算块(computational blocks),称为组合电路。
关于如何组合,有两个规定:
•输出不能直接连在一起。
••••••否则它们可能会使线上的信号矛盾,可能会导致一个不合法的电压或电路故障;
•不能有回路。
••••••也就是在网中不能有路径经过一系列的门而形成一个回路,这样的回路会导致该网络计算的函数有歧义。

在这里插入图片描述
在这里插入图片描述

HCL表达式和C表达式

HCL可以描述组合电路,HCL表达式和C表达式看起来很接近,但它们有哪些区别呢?
HCL描述的是电路结构,电路输出连续响应(有一点点延迟)
HCL的输入只能是0和1的比特值
HCL表达式不会部分计算
C表达式只会在程序执行过程中被遇到时才求值
C的逻辑表达式允许参数是任意整数,0表示FLASE,其他任何值都是TRUE
C的逻辑表达式有个属性就是它们可能只被部分求值

4.2.3 字级组合电路和HCL整型表达式

通常,我们设计操作 数据字(word)的电路。
有一些位级信号,代表一个整数或一些控制模式。
数据字的大小范围从 4 位到 32 位不等,表示整数、地址、指令码和寄存器标识符等信息。
在这里插入图片描述

在HCL中,多路复用函数是用情况表达式 来描述的。

练习4.8-4.9
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

4.2.5 存储器和时钟控制

组合电路从本质上讲,不存储任何信息,它们只是响应输入信号,生成某个输出(是输入的某个函数)。
为创建时序电路(Sequential circuits)(或称时序逻辑电路)(也就是有状态并且在这个状态上进行计算的系统),我们需要能保存信息的设备(按位存储信息的设备)

存储设备都是由同一个时钟控制。

时钟:是一个周期性信号,决定什么时候要把新值加载到设备中。

2类存储设备:
•时钟寄存器(简称寄存器):存储单个位或字。时钟信号控制寄存器加载输入值。
•随机访问存储器(简称存储器):存储多个字,用地址来选择该读或该写哪个字。

硬件和机器级编程时,寄存器的差别:
在硬件中,寄存器直接将它的输入和输出连接到电路的其他部分。
在机器级编程中,寄存器代表的是CPU中为数不多的可寻址的字,这里的地址是寄存器ID。这些字通常都存在寄存器文件中,虽然硬件优势可以直接将一个字从一个指令传送到另一个指令,以避免献血寄存器文件再读出来的延迟。需要避免歧义时,分别称“硬件寄存器”,“程序寄存器”

在这里插入图片描述

这样一个
多端口随机访问存储器允许同时进行多个读和写操作。图中所示的寄存器文件中,电路可以读两个程序寄存器的值,同时更新第3个寄存器的状态

寄存器文件不是组合电路,因为它有内部存储。
向寄存器文件写入字是由时钟信号控制的,控制方式类似于将值加载到时钟寄存器。

当dstW设为特殊的ID值0xF时,不会写任何程序寄存器。
问题:试图同时读和写同一个寄存器会发生什么?
如果更新一个寄存器,同时在读端口上用一个寄存器ID,会看到一个从旧值到新值的变化。
在这里插入图片描述
从存储器中读的操作类似于组合逻辑。

如果地址超出了范围,error信号会置0

4.3 Y86的时序实现

执行指令的步骤

每一步的具体 处理取决于正在执行的指令。
我们把所有指令的操作都组织成统一的步骤序列:
•Fetch(取指令):从存储器读取指令字节,地址为程序计数器的值。指令代码icode, 功能代码ifun, rA, rB, valC, valP。valP等于PC值加上已取出指令长度。
•Decode(解码):从寄存器堆读取最多两个值 valA, valB
•Execute(执行):ALU根据根据icode和ifun进行计算(计算操作数、更新地址、比较CC)得到的值 ValE
•Memory(访存):读写内存,valM
•Write back(写回):写回最多两个值到寄存器堆
•PC update(更新PC):更新程序计数器PC,让其指向下一条指令

•处理器无限循环重复以上步骤,直到遇到异常

在这里插入图片描述

异常处理

•Y86这里假设直接停止
•实际上会进入异常处理模式,根据异常类型执行特殊代码

  1. halt指令
  2. 非法指令和功能码结合的指令
  3. 取指或数据读写试图访问一个非法地址

时序处理器(SEQ)

•SEQ在每个时钟周期都完整地执行所有指令步骤

在这里插入图片描述

SEQ芯片硬件结构

•信息流走向
•按stages划分来安排硬件结构
•取指:将PC寄存器作为地址,指令存储器读取指令的字节,PC增加器计算ValP
•Decode(译码):从寄存器堆同时读取两个值 valA, valB
•Execute(执行):ALU根据根据指令类型进行计算(整数操作执行指令指定操作,其他指令 ,作为一个加法器,计算增加或减少栈指针,或计算有效地址,或加0,将一个输入传到输出;计算条件码的新值/计算分支Cnd)得到的值 ValE
•Memory(访存):读写内存(读出或写入一个存储器字),valM
•Write back(写回):寄存器文件有两个写端口。端口E 写ALU计算的结果,W写从数据存储器中读出的值。
•PC update(更新PC):更新程序计数器PC,让其指向下一条指令

SEQ的时序

原则:处理器从来不需要为了完成一条指令的执行而去读由该指令更新了的状态。

SEQ阶段的实现

取指
译码和写回
执行
访存
更新PC阶段

SEQ问题:
太慢了。
不能充分利用硬件单元因为每个单于只在整个时钟周期的一部分时间内才被使用。

4.4 流水线系统

•任务被划分成若干个独立的阶段(stages)
•多个“服务对象”可以同时经过系统(每个阶段一次服务一个对象)

•性能:
•增加了吞吐量(throughput)
••••也就是单位时间服务的顾客总数
•轻微增加执行时间(latency) ,即服务单个对象的时间

计算流水线

•顾客/对象:
••••••••••••指令
•阶段:
••••••••••••每个阶段执行指令的一部分

非流水线化的硬件 及其 流水线图

在这里插入图片描述

吞吐量(Throughput)计算

三阶段的计算流水线

在这里插入图片描述
在这里插入图片描述

流水线的重要问题:1. 不一致的划分

在这里插入图片描述
在这里插入图片描述

流水线的重要问题:2. 流水线过深

•流水线过深导致流水线寄存器数量过多,延迟增加过多

练习题4.26,4.27在这里插入图片描述

4.4.4 带反馈的流水线系统

数据相关、控制相关

在这里插入图片描述

Y86的流水线实现

程序计数寄存器(PC)值的计算和更新:
•在原本SEQ(非流水线化的Y86处理器)中,一条指令执行的同时,计算新的PC值,然后等待下一个时钟周期开始时更新
•现在改成在时钟周期开始时计算新的PC值并更新(SEQ+)

SEQ到SEQ+中对状态元素的改变是一种通用的改进的例子,这种改进称为 电路重定时。

重定时改变了一个系统的状态表示,但是并不改变它的逻辑行为。通常用它来平衡一个系统中各个阶段的延迟

画图惯例

浅灰色方框-硬件单元:如:ALU
灰色圆角矩形-控制逻辑块:这些块用来从一组信号源中进行选择,或者用来计算一些布尔函数。会非常详细分析这些块,包括HCL描述
白色圆觉方框-线路的名字:只是线路的标识,而不是什么硬件元素
中等粗度的线-宽度为字长的数据连接:每条这样的线实际上都代表一簇32根线,并列地连在一起,将一个字从硬件的一个部分传到另一部分。
细线-宽度为字节或更窄的数据连接:根据线上要携带的值的类型,每条这样的线实际上都代表一簇4根或8根线
虚线-单个位的连接:代表芯片上单元与块之间传递的控制值。

4.5.2 插入流水线寄存器

4.5.4 预测下一个PC

•大部份PC新值都可以预测,除了:
•条件转移和返回指令

猜测分支方向并根据猜测开始取指的技术称为分支预测。
在这里插入图片描述
在这里插入图片描述

4.5.5 流水线冒险(Hazard)

•Hazard:冒险,危害,风险

•数据冒险
•数据相关,下一条指令会用到这一条指令计算出的结果

•控制冒险
•控制相关,一条指令要确定下一条指令的 位置

这些相关可能会导致流水线产生计算错误,称为冒险。

对数据冒险的处理

•4.5.6 用暂停来避免数据冒险

暂停时,处理器会停止流水线中一条或多条指令,直到冒险条件不再满足。让一条指令停顿在译码阶段,直到产生它的源操作数的指令通过了写回阶段,这样处理器就能避免数据冒险。

暂停技术就是让一组指令阻塞在它们所处的阶段,而允许其他指令继续通过流水线。

缺点:性能不好。一条指令更新一个寄存器,紧跟其后的指令就使用被更新的寄存器,这会导致流水线暂停长达三个周期,严重降低了整体的吞吐量。

•4.5.7 用转发来避免数据冒险
将结果值直接从一个流水线阶段传到较早阶段的技术称为数据转发,或转发,有时称为旁路。

数据转发需要在基本的硬件结构中增加一些额外的数据连接和控制逻辑。

•4.5.8 加载/使用数据冒险
有一类数据冒险不能单纯使用数据转发来解决,因为存储器读在流水线发生的比较晚。
在这里插入图片描述

第六章 存储器层次结构

6.1存储技术

存储器系统 是一个具有不同容量、成本和访问时间的存储设备的层次结构。
CPU寄存器:保存着最常用的数据
靠近CPU的小的、快速的高速缓存存储器作为一部分存储在相对慢速的主存储器中的数据和指令的缓冲区域。
主存暂时存放存储在容量较大的、慢速磁盘上的数据,而这些磁盘常常又作为存储在通过网络连接的其他机器的磁盘或磁带上的数据的缓冲区域。

6.1.1 随机访问存储器(RAM)

•静态RAM(SRAM)
•动态RAM(DRAM)
SRAM用来作为高速缓存存储器,既可以在CPU之上,也可以在片下。
DRAM用来作为主存以及图形系统的帧缓冲区。

典型的,一个桌面系统的SRAM不会超过几兆字节,但是DRAM却有几百或几千兆字节。

静态RAM(SRAM)

SARM 将每个位存储在双稳态的存储单元里,每个单元是用一个六晶体管电路来实现的。

最大特点:双稳态特性

0
1
——-
0———-》电磁干扰 0,1——经过很短时间—-》0.(抗干扰)

六晶体管电路

由于SRAM存储器单元的双稳态特性,只要通电,它就会永远地保持它的值。即使有干扰,例如电子噪音,来扰乱电压,当干扰消除时,电路就会恢复到稳定值。

稳态?

动态RAM(DRAM)

•将每个位存储为对一个电容的充电;每个存储单元使用一个晶体管和一个电容

•在10~100毫秒内会失去电荷,因此需要持续刷新,即周期性地读取出来,然后再写进去

•也会利用纠错码来发现出错的位

SRAM和DRAM比较
传统的DRAM组织结构

•这里是16个超单元,每个超单元保存一个字节(8位)
•整个DRAM芯片按行列4x4组织成一个阵列

•芯片有两组引脚,一组是地址引脚 addr,一组是数据引脚data
•访问某地址(i,j)的时候(表示i行j列),先发送i,再发送j(共用地址引脚

读取DRAM超单元 (2,1)

•步骤 a1:RAS(Row Access Strobe,行访问选痛脉冲)选中第2行

•步骤 a2:第2行数据从DRAM阵列被整行复制到行缓冲区

•步骤b1:CAS(Column Access Strobe,列访问选通脉冲)选中第1列

•步骤b2:行缓冲区第1列(即超单元(2,1)的数据)被复制到数据线

存储器模块

练习题6.1

增强的DRAM

所有增强型DRAM都是基于传统的DRAM核心构建而成的。
•快速页模式DRAM(FPM DRAM)
使用[RAS, CAS, CAS, CAS, CAS]而不是[(RAS,CAS), (RAS,CAS), (RAS,CAS), (RAS,CAS)]的方式来访问行内容。
•扩展数据输出DRAM(EDO DRAM)
在FPM DRAM的基础上,CAS信号更加紧密地排列。
•同步DRAM(SDRAM)
使用上升时钟边沿而不是异步控制信号进行驱动。
•双倍数据速率同步DRAM(DDR SDRAM)
是SDRAM的增强版,利用了两个时钟边沿作为控制信号。
•视频RAM(VRAM)(其实就是显存)
类似于FPM DRAM,但输出是通过移动行缓冲区来产生的。
双端口(允许并发读写)。

非易失性存储器

•DRAM和SRAM是易失性存储器
•如果断电,会丢失信息。
•非易失性存储器即使断电也能保留数值。
•通用名称为只读存储器(ROM)
•这个名称有些误导,因为有些ROM可以读取和修改。
•ROM的类型
•可编程只读存储器(Programable ROM, PROM)只会写一次
•可擦除可编程只读存储器(Erasable PROM, EPROM)
•电子可擦除只读存储器(Electrically Erasable PROM, EEPROM)这些都很少写入
•闪存存储器(Flash memory)经常重复擦写

固件
连接CPU和内存的典型总线结构

•总线是一组并行传输地址、数据和控制信号的电线集合。
•总线通常由多个设备共享。

6.2 磁盘存储

磁盘构造

•磁盘由盘片组成,每个盘片有两个表面。
•每个表面由同心环形轨道组成,称为磁道。
•每个磁道由分隔的扇区组成

2. 磁盘容量

容量:可以存储的最大位数。
•厂商以千兆字节(GB)为单位表示容量,其中1 GB = 10^9。
容量由以下技术因素决定:
•记录密度(位/英寸):可以压缩到一英寸轨道段中的位数。
•轨道密度(轨道/英寸):可以压缩到一英寸径向段中的轨道数。
•面积密度(位/平方英寸):记录密度和轨道密度的乘积。

计算磁盘容量

练习题6.2

磁盘操作

6.3

4. 逻辑磁盘块

5 I/O总线

6 访问磁盘读

局部性

•局部性原理
•程序倾向于重复使用近期使用过的数据和指令,或者是最近引用过的数据和指令。
•时间局部性:最近引用过的项在不久的将来可能会再次被引用。
•空间局部性:地址相近的项在不久的将来可能会再次被引用。
•例子:
•数据:
•数组内容访问的空间局部性
•sum访问的时间局部性
•指令:
•指令顺序执行(空间局部性)
•指令重复执行(时间局部性)

判断局部性

•在阅读代码时判断其是否具有良好的局部性,是专业程序员的关键技能!

6.2.2 取指令的局部性

6.2.3 局部性小结

6.3 存储器层次结构

基本的和持久的属性

存储技术
计算机软件
硬件和软件的这些基本属性互相补充得很完美

这把我们引向了一种组织内存和存储系统的方法,称为存储器层次结构。

6.3.1 缓存

•缓存,或高速缓存:
•一个小而快速的存储设备,它作为存储在 更大、也更慢的设备中的数据对象的缓冲区域

为什么存储器层次结构有效?

•相比于第 k+1 层的数据,程序倾向于更频繁地访问第 k 层的数据。
•因此,第 k+1 层的存储可以更慢,因此每位的成本可以更低并且容量更大。
•整体效果:一个大型的内存池,成本与底部的廉价存储相当,但以接近顶部快速存储的速度为程序提供数据。
•使用小型高速缓存和大型低速存储的组合,给出大型高速缓存的错觉。

基本的缓存原理
替换策略
放置策略

无限制:允许将第k+1级缓存的块放置到第k级缓存的任何块中
•在高层缓存(靠近CPU)实现这个策略代价很高

限制性的放置策略
•第k+1级的第i块必须被放置到第k级的第 i % n 块

缓存不命中的情况种类

•Cold miss(冷不命中):
•缓存是空的时候称为冷缓存(Cold Cache),这时候访问什么都会miss,这种miss称为Cold Miss(冷不命中)或强制不命中(Compulsory Miss)

•Conflict miss(冲突不命中):
•使用限制性策略时,引用的不同对象映射到同一个缓存块

•Capacity miss(容量不命中):
•程序某个阶段的工作集大小超过缓存的大小(缓存装不下)

缓存管理

•需要某些程序负责判定是否命中,决定块如何划分、如何放置等等。不同级别的缓存有不同的管理逻辑。

存储器层次结构概念小结

6.4 高速缓存存储器

•前面介绍存储器层次结构时提到的缓存指的是一般意义上(广义)的缓存,不同存储层次间的缓存
•对于每个k,位于k的更快更小的存储设备作为位于k+1 层的更大更慢的存储设备的缓存

•狭义上的缓存(我们说计算机或处理器中的缓存值得就是这种缓存)又称高速缓存,位于CPU和主存之间
•CPU先尝试从L1缓存获取数据/指令,没有再从L2,再没有就从L3,再没有才到内存

缓存存储结构

•直接映射
•组相联映射
•全相连映射

为什么用中间的位作索引?为什么不是用高位?
组相联高速缓存
通用的高速缓存存储器结构
全相连高速缓存
直接映射高速缓存中的冲突不命中
抖动
解决方案
命中率计算

6.11

编写高速缓存友好的代码

•记住几点:
•缓存命中率高(不命中率低)的程序运行得更快
•局部性好的程序更容易有较高的命中率

•让最常见的情况运行得快
•内层循环、核心函数

•提升循环内部的缓存命中率

6.4.5 有关写的问题

  1. 假设要写一个已经在缓存里的变量w(写命中)
    •先更新缓存里的w,然后再更新低一层的w
    •直写(write-through)
    •写回(write-back)

  2. 如何处理写不命中
    •写分配(write-allocate):分配缓存块,然后写到内存
    •非写分配(no-write-allocate):不分配缓存块,直接写到内存

直写高速缓存通常是非写分配的,写回高速缓存通常是写分配的

练习题6.19

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值