【计组】异常、CPU指令集--《深入浅出计算机组成原理》(五)

news2024/9/24 1:18:14

课程链接:深入浅出计算机组成原理_组成原理_计算机基础-极客时间 

一、异常

(一)异常

异常其实是一个硬件和软件组合到一起的处理过程。异常的发生和捕捉,是在硬件层面完成的。但是异常的处理,是由软件来完成的。

计算机会为每一种可能会发生的异常,分配一个异常代码(Exception Number),或者叫作中断向量(Interrupt Vector)。异常发生的时候,通常是 CPU 检测到了一个特殊的信号。比如正在执行的指令发生了加法溢出,就会有一个进位溢出的信号。这些信号,在组成原理里面,一般叫作发生了一个事件(Event)。CPU 在检测到事件的时候,其实也就拿到了对应的异常代码。

这些异常代码里,I/O 发出的信号的异常代码,是由操作系统来分配的,也就是由软件来设定的。而像加法溢出这样的异常代码,则是由 CPU 预先分配好的,也就是由硬件来分配的。

拿到异常代码之后,CPU 就会触发异常处理的流程。计算机在内存里,会保留一个异常表(Exception Table),也可以叫作中断向量表(Interrupt Vector Table),存放的是不同的异常代码对应的异常处理程序(Exception Handler)所在的地址。

 CPU 在拿到异常码之后,会先把当前的程序执行的现场,保存到程序栈里面,然后根据异常码查询,找到对应的异常处理程序,最后把后续指令执行的指挥权,交给这个异常处理程序。

 (二)异常的分类:中断、陷阱、故障和中止

1、中断(Interrupt):程序在执行的过程中被打断。打断执行的信号,来自于 CPU 外部的 I/O 设备,而不是在程序自己执行的过程中,所以可以称之为“异步”类型的异常

2、陷阱(Trap):程序员“故意“触发的异常。就好像在程序里面打了一个断点,这个断点就是设下的"陷阱"。当程序的指令执行到这个位置的时候,就掉到陷阱当中,对应的异常处理程序就会来处理这个"陷阱"当中的猎物。

最常见的一类陷阱,发生在从程序的用户态切换到内核态的时候。应用程序通过系统调用去读取文件、创建进程,也是通过触发陷阱来进行的。这是因为,用户态的应用程序没有权限来做这些事情,需要把对应的流程转交给有权限的异常处理程序来进行。

3、故障(Fault):不是开发的时候计划在内的,一样需要有对应的异常处理程序去处理。故障和陷阱、中断的一个重要区别是,故障在异常程序处理完成之后,仍然回来处理当前的指令,而不是去执行程序中的下一条指令。因为当前的指令因为故障的原因并没有成功执行完成。

4、中止(Abort):与其说是一种异常类型,不如说是故障的一种特殊情况。当 CPU 遇到了故障,但是没有异常处理程序能够处理这种异常,程序就不得不中止了。

陷阱、故障以及中止类型的异常,是在程序执行的过程中发生的,可以称之为“同步“类型的异常

无论是异步的中断,还是同步的陷阱和故障,都是采用同一套处理流程——保存现场、异常代码查询、异常处理程序调用

(三)异常处理:上下文切换

切换到异常处理程序的时候,指令的控制权被切换到了另外一个"函数"里面,所以要把当前正在执行的指令去压栈。这样,才能在异常处理程序执行完成之后,重新回到当前的指令继续往下执行。

异常情况往往发生在程序正常执行的预期之外,除了本来程序压栈要做的事情之外,还需要把 CPU 内当前运行程序用到的所有寄存器,都放到栈里面。最典型的就是条件码寄存器里面的内容。

像陷阱这样的异常,涉及程序指令在用户态和内核态之间的切换。对应压栈的时候,对应的数据是压到内核栈里,而不是程序栈里。

像故障这样的异常,在异常处理程序执行完成之后。从栈里返回出来,继续执行的不是顺序的下一条指令,而是故障发生的当前指令。因为当前指令发生故障没有正常执行成功,必须重新去执行一次。

所以,对于异常这样的处理流程,不像是顺序执行的指令间的函数调用关系。而是更像两个不同的独立进程之间在 CPU 层面的切换,所以这个过程我们称之为上下文切换(Context Switch)。

二、CPU指令集

(一)CISC 和 RISC

CPU 的指令集里的机器码是固定长度还是可变长度,也就是复杂指令集(Complex Instruction Set Computing,简称 CISC)和精简指令集(Reduced Instruction Set Computing,简称 RISC)这两种风格的指令集一个最重要的差别。

在计算机历史的早期,所有的 CPU 其实都是 CISC。当时的计算机很慢,存储空间也很小,为了让计算机能够做尽量多的工作,CPU 指令集的设计,需要仔细考虑硬件限制。

为了性能考虑,很多功能都直接通过硬件电路来完成。为了少用内存,指令的长度也是可变的,常用的指令要短一些,不常用的指令可以长一些。那个时候的计算机,想要用尽可能少的内存空间,存储尽量多的指令。

后来,计算机的性能越来越好,存储的空间也越来越大了。 70 年代末,RISC 开始登上了历史的舞台。大卫·帕特森(David Patterson)教授发现,实际在 CPU 运行的程序里,80% 的时间都是在使用 20% 的简单指令。于是,他就提出了 RISC 的理念。自此之后,RISC 类型的 CPU 开始快速蓬勃发展。

RISC 架构的 CPU 的想法其实非常直观。既然我们 80% 的时间都在用 20% 的简单指令,那么,在 RISC 架构里面,CPU 选择把指令“精简”到 20% 的简单指令。而原先的复杂指令,则通过组合简单指令来实现,让软件来实现硬件的功能。这样,CPU 的整个硬件设计就会变得更简单了,在硬件层面提升性能也会变得更容易了。

RISC 的 CPU 里完成指令的电路变得简单了,于是也就腾出了更多的空间。这个空间,常常被拿来放通用寄存器。因为 RISC 完成同样的功能,执行的指令数量要比 CISC 多,所以,如果需要反复从内存里面读取指令或者数据到寄存器里来,那么很多时间就会花在访问内存上。于是,RISC 架构的 CPU 往往就有更多的通用寄存器。

除了寄存器这样的存储空间,RISC 的 CPU 也可以把更多的晶体管,用来实现更好的分支预测等相关功能,进一步去提升 CPU 实际的执行效率。

程序的 CPU 执行时间 = 指令数  ×  CPI  ×  Clock Cycle Time

CISC 的架构,其实就是通过优化指令数,来减少 CPU 的执行时间。而 RISC 的架构,其实是在优化 CPI。因为指令比较简单,需要的时钟周期就比较少。

(二)微指令架构

微指令(Micro-Instructions/Micro-Ops)架构是为了解决指令集的向前兼容而产生的。在微指令架构的 CPU 里面,编译器编译出来的机器码和汇编代码并没有发生什么变化。但在指令译码的阶段,指令译码器“翻译”出来的,不再是某一条 CPU 指令而是好几条“微指令”。这里的一条条微指令,就不再是 CISC 风格的了,而是变成了固定长度的 RISC 风格的了。微指令架构的引入,让 CISC 和 RISC 的分界变得模糊了。

RISC 风格的微指令,会被放到一个微指令缓冲区里面,然后再从缓冲区里面,分发给到后面的超标量,并且是乱序执行的流水线架构里面。

不过,一个能够把 CISC 的指令译码成 RISC 指令的指令译码器,比原来的指令译码器要复,这也就意味着更复杂的电路和更长的译码时间。

之所以大家认为 RISC 优于 CISC,来自于一个数字统计,那就是在实际的程序运行过程中,有 80% 运行的代码用着 20% 的常用指令。这意味着,CPU 里执行的代码有很强的局部性。而对于有着很强局部性的问题,常见的一个解决方案就是使用缓存

即在 CPU 里面加了一层Cache用来保存的是指令译码器把 CISC 的指令“翻译”成 RISC 的微指令的结果。这样,在大部分情况下,CPU 都可以从 Cache 里面拿到译码结果,而不需要让译码器进行实际的译码操作。这样不仅优化了性能(译码器的晶体管开关动作变少了),还减少了功耗。

(三)ARM 和 RISC-V

ARM现在的含义,是“Advanced RISC Machines”,ARM的芯片是基于RISC的。

ARM最主要的两个优点:

1、功耗优先。在移动设备上,功耗是一个远比性能更重要的指标。RM 的 CPU,主频更低,晶体管更少,高速缓存更小,乱序执行的能力更弱。所有这些,都是为了功耗所做的妥协。一个 4 核的 Intel i7 的 CPU,设计时功率就是 130W。而一块 ARM A8 的单个核心的 CPU,设计功率只有 2W。

2、低价。ARM 并没有自己垄断 CPU 的生产和制造,只是进行 CPU 设计,然后把对应的知识产权授权出去。苹果、三星、华为,它们都是拿到了基于 ARM 体系架构设计和制造 CPU 的授权。ARM 自己只是收取对应的专利授权费用。多个厂商之间的竞争,使得 ARM 的芯片在市场上价格很便宜。

在 ARM 似乎已经垄断了移动 CPU 市场的时候,开源的 RISC-V 出现了,RISC 概念的发明人,图灵奖的得主大卫·帕特森教授从伯克利退休之后,成了 RISC-V 国际开源实验室的负责人,开始推动 RISC-V 这个“CPU 届的 Linux”的开发。可以想见,未来的开源 CPU,也多半会像 Linux 一样,逐渐成为一个业界的主流选择。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/137719.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【并发编程十】c++线程同步——条件变量(condition_variable)

【并发编程十】c线程同步——条件变量(condition_variable)一、互斥二、条件变量1、为何要引入条件变量?2、不使用条件变量3、使用条件变量3.1、互斥锁有什么问题?3.2、条件变量3.3、条件变量成员函数3.4、demo三、future四、信号量简介&…

【并发编程九】c++线程同步——互斥(mutex)

【并发编程九】c线程同步——互斥(mutex)一、互斥1、mutex1.1、mutex1.2、 lock_guard1.3、 RAII2、std::recursive_mutex3、std::shared_mutex、std::shared_lock、std::unique_lock4、std::scoped_lock二、条件变量三、future四、信号量简介&#xff1…

chrony服务器

Chrony是一个开源自由的网络时间协议 NTP 的客户端和服务器软软件。它能让计算机保持系统时钟与时钟服务器(NTP)同步,因此让你的计算机保持精确的时间,Chrony也可以作为服务端软件为其他计算机提供时间同步服务。 Chrony由两个程序…

【嵌入式Linux环境搭建-10】tftp服务安装、双网卡并行

10.tftp服务安装 板子有有线网卡,需有线连接到电脑 主机安装TFTP服务 $ sudo apt-get install xinetd tftpd tftp $ sudo vim /etc/xinetd.d/tftp /*添加下面内容, service tftp { protocol udp port 69 socket_type dgram wait …

aws lambda 理解RIC和RIE构建和测试容器镜像并通过cdk部署lambda函数

参考资料 AWS Lambda 的新功能 — 容器映像支持 快速构建基于 Lambda 容器镜像的 OCR 应用 利用 Lambda 容器镜像搭建分布式压测引擎 lambda容器镜像构建 可以将 Lambda 函数打包和部署最大 10 GB 的容器映像,轻松构建和部署依赖于大量依赖项的更大型工作负载 …

【Java核心技术】创建多线程

1、多线程的概述 什么是线程&#xff1f; 线程(thread)是一个程序内部的一条执行路径。 我们之前启动程序执行后&#xff0c;main方法的执行其实就是一条单独的执行路径。 public static void main(String[] args) {// 代码...for (int i 0; i < 10; i) {System.out.prin…

《柳叶刀》:约20%中国男性死亡可归因于吸烟

*仅供医学专业人士阅读参考 吸烟喝酒可谓众所周知的两大“健康刺客”。一首歌名为《给我一杯酒》中的歌词唱到“给我一杯酒&#xff0c;再给我一只烟&#xff0c;说走就走&#xff0c;我有的是时间”&#xff0c;传唱度极高&#xff0c;甚至还一度成为短视频平台的最热门的BGM之…

概论_第2章_重点内容__随机变量函数的概率分布

一 定义 概括地说&#xff1a; 随机变量Y是随机变量X的函数。 设g(x) 是一给定的连续函数&#xff0c; 称Yg(X) 为随机变量X的一个函数&#xff0c; Y也是一个随机变量。当X取值 时&#xff0c;Y取值 . ~~~~~~~~~~~~~~ 本文讨论连续型随机变量函数。 定理1: 设X为连续型…

Appium环境搭建及元素定位

01 Appium简介 Appium是一个开源测试自动化框架&#xff0c;可用于原生&#xff0c;混合和移动Web应用程序测试。它使用WebDriver 协议驱动iOS&#xff0c;Android和Windows应用程序。 01 环境搭建步骤 Appium环境安装&#xff1a; 第一步 安装 appium 桌面版客户端 Appium…

Linux挂载磁盘命令

需求&#xff1a; 只有一个硬盘&#xff0c;创建多个挂载点 参考&#xff1a;linux如何实现挂载—linux_是小明同学啊的博客-CSDN博客_linux挂载 1 查看当前挂载情况 执行 df -h&#xff0c; 查看当前 / 根目录下挂载的分区名&#xff0c;在下图中为倒数第三行&#xff0c; …

html练习

1. 2. 3. <h1>各科小常识</h1> <h3>语文</h3> <p> 三国演义是中国四大古典名著之一&#xff0c;元末明初小说家罗贯中所著。是中国第一部章回体历史演义的小说&#xff0c;描写了从东汉末年到西晋初年近100年的历史风云。</p> <hr&g…

Ubuntu20.04 LTS 安装 ros Noetic 树莓派4/PC

Ubuntu 20.04 LTS 安装树莓派系统. 主要参考了这两篇文章&#xff1a; https://blog.csdn.net/liangforcold/article/details/126385774 https://blog.csdn.net/yangcunbiao/article/details/123056806 https://blog.csdn.net/duping812/article/details/110391081 1、下载安…

【前端-NPM私服】内网使用verdaccio搭建私有npm服务器-docker搭建verdaccio流程

目录一、npm私服是什么1. 定义2. 为什么需要npm私服二、npm私服如何使用1. 链接到npm私服2. 注册私服账号3. 发布组件到私服4. 关联LDAP服务5. 提高下载速度三、私服搭建方案四、docker搭建Verdaccio流程1. 拉镜像2. 创建卷3. 启动容器4. 软链接卷到统一的目录5. 配置Verdaccio…

【node.js】npm包管理工具的使用

&#x1f973;博 主&#xff1a;初映CY的前说(前端领域) &#x1f31e;个人信条&#xff1a;想要变成得到&#xff0c;中间还有做到&#xff01; &#x1f918;本文核心&#xff1a;node.jsx中npm包管理工具的基础使用&#xff0c;包与依赖关系的介绍 下图为本文的核心 目…

rmq 主备自动切换模式

https://rocketmq.apache.org/zh/docs/deploymentOperations/16autoswitchdeploy/ https://github.com/apache/rocketmq/blob/develop/docs/cn/controller/design.md controller 端 leader选举 主备自动切换模式就是controller模式&#xff0c;controller可以嵌入name serve…

ccc-sklearn-12-线性回归(2)

一、非线性问题&#xff1a;多项式回归 主要探讨&#xff1a;通过线性回归解决非线性问题 数据的线性与非线性 通常情况下&#xff0c;分类问题中决策函数往往是一个分段函数&#xff0c;这个函数明显不满足可以用一条直线进行表示的属性&#xff0c;因此分类问题中特征与标签[…

若依整合第三方登录

0&#xff1a;以gitee为例&#xff0c;首先开通gitee第三方登录&#xff1a;&#xff08;在设置里面的第三方应用里面新建&#xff09; 0.1&#xff1a;后端引入JustAuth第三方登陆框架&#xff1a; <dependency><groupId>me.zhyd.oauth</groupId><artif…

H5UI库、加密技术和二维码

一、H5UI库 1. 使用方法&#xff1a; ​ &#xff08;1&#xff09;页面中引入css文件 ​ h5ui.css &#xff08;h5ui.min.css&#xff09; ​ &#xff08;2&#xff09;页面中引入js文件 ​ ​ jquery.min.js ​ ​ h5ui.min.js 2. 组件…

十五、Kubernetes中Pod生命周期详解、实例

1、概述 我们一般将pod对象从创建至终的这段时间范围称为pod的生命周期&#xff0c;它主要包含下面的过程&#xff1a; pod创建过程 运行初始化容器&#xff08;init container&#xff09;过程 运行主容器&#xff08;main container&#xff09; 容器启动后钩子&#xff0…

对于负载均衡服务器一致性哈希算法一些简单的想法

文章目录一致性哈希负载均衡的介绍一致性哈希负载均衡的介绍 负载均衡这个概念可以抽象为&#xff1a;从n个候选服务器中选择一个进行通信。 负载均衡算法有&#xff1a;随机&#xff0c;轮询&#xff0c;最小连接数等。今天的“猪脚”是一致性哈希负载均衡算法&#xff1b; 一…