64位和32位相比优势是什么(二)

news2024/11/23 7:23:43

程序的执行过程

当 CPU 执行程序的时候:

1.首先,CPU 读取 PC 指针指向的指令,将它导入指令寄存器。具体来说,完成读取指令这件事情有 3 个步骤:

步骤 1:CPU 的控制单元操作地址总线指定需要访问的内存地址(简单理解,就是把 PC 指针中的值拷贝到地址总线中)。

步骤 2:CPU 通知内存设备准备数据(内存设备准备好了,就通过数据总线将数据传送给 CPU)。

步骤 3:CPU 收到内存传来的数据后,将这个数据存入指令寄存器。

完成以上 3 步,CPU 成功读取了 PC 指针指向指令,存入了指令寄存器。

2.然后,CPU 分析指令寄存器中的指令,确定指令的类型和参数。
3.如果是计算类型的指令,那么就交给逻辑运算单元计算;如果是存储类型的指令,那么由控制单元执行。
4.PC 指针自增,并准备获取下一条指令。

比如在 32 位的机器上,指令是 32 位 4 个字节,需要 4 个内存地址存储,因此 PC 指针会自增 4。

在这里插入图片描述

了解了程序的执行过程后,我还有一些问题想和大家一起讨论:

  1. 内存虽然是一个随机存取器,但是我们通常不会把指令和数据存在一起,这是为了安全起见。具体的原因我会在模块四进程部分展开讲解,欢迎大家在本课时的留言区讨论起来,我会结合你们留言的内容做后续的课程设计。

  2. 程序指针也是一个寄存器,64 位的 CPU 会提供 64 位的寄存器,这样就可以使用更多内存地址。特别要说明的是,64 位的寄存器可以寻址的范围非常大,但是也会受到地址总线条数的限制。比如和 64 位 CPU 配套工作的地址总线只有 40 条,那么可以寻址的范围就只有 1T,也就是 240

  3. 从 PC 指针读取指令、到执行、再到下一条指令,构成了一个循环,这个不断循环的过程叫作CPU 的指令周期,下面我们会详细讲解这个概念。

详解 a = 11 + 15 的执行过程

上面我们了解了基本的程序执行过程,接下来我们来看看如果用冯诺依曼模型执行a=11+15是一个怎样的过程。

我们再 Review 下这个问题:程序员写的程序a=11+15是字符串,CPU 不能执行字符串,只能执行指令。所以这里需要用到一种特殊的程序——编译器。编译器的核心能力是翻译,它把一种程序翻译成另一种程序语言。

这里,我们需要编译器将程序员写的程序翻译成 CPU 认识的指令(指令我们认为是一种低级语言,我们平时书写的是高级语言)。你可以先跟我完整地学完操作系统,再去深入了解编译原理的内容。

下面我们来详细阐述 a=11+15 的执行过程:

1.编译器通过分析,发现 11 和 15 是数据,因此编译好的程序启动时,会在内存中开辟出一个专门的区域存这样的常数,这个专门用来存储常数的区域,就是数据段,如下图所示:

  • 11 被存储到了地址 0x100;

  • 15 被存储到了地址 0x104;

在这里插入图片描述

2.编译器将a=11+15转换成了 4 条指令,程序启动后,这些指令被导入了一个专门用来存储指令的区域,也就是正文段。如上图所示,这 4 条指令被存储到了 0x200-0x20c 的区域中:

0x200 位置的 load 指令将地址 0x100 中的数据 11 导入寄存器 R0;

0x204 位置的 load 指令将地址 0x104 中的数据 15 导入寄存器 R1;

0x208 位置的 add 指令将寄存器 R0 和 R1 中的值相加,存入寄存器 R2;

0x20c 位置的 store 指令将寄存器 R2 中的值存回数据区域中的 0x1108 位置。

3.具体执行的时候,PC 指针先指向 0x200 位置,然后依次执行这 4 条指令。

这里还有几个问题要说明一下:

  1. 变量 a 实际上是内存中的一个地址,a 是给程序员的助记符。

  2. 为什么 0x200 中代表加载数据到寄存器的指令是 0x8c000100,我们会在下面详细讨论。

  3. 不知道细心的同学是否发现,在上面的例子中,我们每次操作 4 个地址,也就是 32 位,这是因为我们在用 32 位宽的 CPU 举例。在 32 位宽的 CPU 中,指令也是 32 位的。但是数据可以小于 32 位,比如可以加和两个 8 位的字节。

  4. 关于数据段和正文段的内容,会在模块四进程和线程部分继续讲解。

指令

接下来我会带你具体分析指令的执行过程。

在上面的例子中,load 指令将内存中的数据导入寄存器,我们写成了 16 进制:0x8c000100,拆分成二进制就是:

这里大家还是看下图,需要看一下才能明白。

在这里插入图片描述

  • 最左边的 6 位,叫作操作码,英文是 OpCode,100011 代表 load 指令;

  • 中间的 4 位 0000是寄存器的编号,这里代表寄存器 R0;

  • 后面的 22 位代表要读取的地址,也就是 0x100。

所以我们是把操作码、寄存器的编号、要读取的地址合并到了一个 32 位的指令中。

我们再来看一条求加法运算的 add 指令,16 进制表示是 0x08048000,换算成二进制就是:

在这里插入图片描述

  • 最左边的 6 位是指令编码,代表指令 add;

  • 紧接着的 4 位 0000 代表寄存器 R0;

  • 然后再接着的 4 位 0001 代表寄存器 R1;

  • 再接着的 4 位 0010 代表寄存器 R2;

  • 最后剩下的 14 位没有被使用。

构造指令的过程,叫作指令的编码,通常由编译器完成;解析指令的过程,叫作指令的解码,由 CPU 完成。由此可见 CPU 内部有一个循环:

  1. 首先 CPU 通过 PC 指针读取对应内存地址的指令,我们将这个步骤叫作 Fetch,就是获取的意思。

  2. CPU 对指令进行解码,我们将这个部分叫作 Decode。

  3. CPU 执行指令,我们将这个部分叫作 Execution。

  4. CPU 将结果存回寄存器或者将寄存器存入内存,我们将这个步骤叫作 Store。

在这里插入图片描述

上面 4 个步骤,我们叫作 CPU 的指令周期。CPU 的工作就是一个周期接着一个周期,周而复始。

指令的类型

通过上面的例子,你会发现不同类型(不同 OpCode)的指令、参数个数、每个参数的位宽,都不一样。而参数可以是以下这三种类型:

  1. 寄存器;

  2. 内存地址;

  3. 数值(一般是整数和浮点)。

当然,无论是寄存器、内存地址还是数值,它们都是数字。

指令从功能角度来划分,大概有以下 5 类:

  1. I/O 类型的指令,比如处理和内存间数据交换的指令 store/load 等;再比如将一个内存地址的数据转移到另一个内存地址的 mov 指令。

  2. 计算类型的指令,最多只能处理两个寄存器,比如加减乘除、位运算、比较大小等。

  3. 跳转类型的指令,用处就是修改 PC 指针。比如编程中大家经常会遇到需要条件判断+跳转的逻辑,比如 if-else,swtich-case、函数调用等。

  4. 信号类型的指令,比如发送中断的指令 trap。

  5. 闲置 CPU 的指令 nop,一般 CPU 都有这样一条指令,执行后 CPU 会空转一个周期。

指令还有一个分法,就是寻址模式,比如同样是求和指令,可能会有 2 个版本:

  1. 将两个寄存器的值相加的 add 指令。

  2. 将一个寄存器和一个整数相加的 addi 指令。

另外,同样是加载内存中的数据到寄存器的 load 指令也有不同的寻址模式:

  1. 比如直接加载一个内存地址中的数据到寄存器的指令la,叫作直接寻址。

  2. 直接将一个数值导入寄存器的指令li,叫作寄存器寻址。

  3. 将一个寄存器中的数值作为地址,然后再去加载这个地址中数据的指令lw,叫作间接寻址。

因此寻址模式是从指令如何获取数据的角度,对指令的一种分类,目的是给编写指令的人更多选择

了解了指令的类型后,我再强调几个细节问题:

  1. 关于寻址模式和所有的指令,只要你不是嵌入式开发人员,就不需要记忆,理解即可。

  2. 不同 CPU 的指令和寄存器名称都不一样,因此这些名称也不需要你记忆。

  3. 有几个寄存器在所有 CPU 里名字都一样,比如 PC 指针、指令寄存器等。

指令的执行速度

之前我们提到过 CPU 是用石英晶体产生的脉冲转化为时钟信号驱动的,每一次时钟信号高低电平的转换就是一个周期,我们称为时钟周期。CPU 的主频,说的就是时钟信号的频率。比如一个 1GHz 的 CPU,说的是时钟信号的频率是 1G。

到这里你可能会有疑问:是不是每个时钟周期都可以执行一条指令?其实,不是的,多数指令不能在一个时钟周期完成,通常需要 2 个、4 个、6 个时钟周期。

总结

【解析】 其实,这个问题需要分类讨论。

  1. 如果说的是 64 位宽 CPU,那么有 2 个优势。

优势 1:64 位 CPU 可以执行更大数字的运算,这个优势在普通应用上不明显,但是对于数值计算较多的应用就非常明显。

优势 2:64 位 CPU 可以寻址更大的内存空间

  1. 如果 32 位/64 位说的是程序,那么说的是指令是 64 位还是 32 位的。32 位指令在 64 位机器上执行,困难不大,可以兼容。 如果是 64 位指令,在 32 位机器上执行就困难了。因为 32 位指令在 64 位机器执行的时候,需要的是一套兼容机制;但是 64 位指令在 32 位机器上执行,32 位的寄存器都存不下指令的参数。

  2. 操作系统也是一种程序,如果是 64 位操作系统,也就是操作系统中程序的指令都是 64 位指令,因此不能安装在 32 位机器上。

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

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

相关文章

[CKA]考试之备份还原 etcd

由于最新的CKA考试改版,不允许存储书签,本博客致力怎么一步步从官网把答案找到,如何修改把题做对,下面开始我们的 CKA之旅 题目为: Task 首先,为运行在https://127.0.0.1:2379上的现有 etcd 实例创建快照…

36 # 加载 json 的处理流程

require 源码大致过程 mod.require 会默认调用 require 语法Module.prototype.require 模块的原型上有 require 方法Module._load 调用模块的加载方法,最终返回的是 module.exportsModule._resolveFilename 解析文件名,将文件名变成绝对路径&#xff0c…

UTF是变长编码

在阅读关于UTF8变长编码的文档时,看到如下内容, 文档中1110表示涉及3个字节,10表示涉及一个字节,还有后面的1110高位有三个1,表示从当前字节起有3字节参与表示UNICODE,后面的高位有1个1,表示从当…

Netty实战(十六)

UDP广播事件(二)编写广播者和监视器 一、编写广播者二、编写监视器三、运行 LogEventBroadcaster 和 LogEventMonitor 一、编写广播者 Netty 提供了大量的类来支持 UDP 应用程序的编写。下面我们列出一些要用到的类型: 名 称描 述interface…

价格·歧视

一级价格歧视与耳机价格歧视 价格歧视指的是厂商对于两个完全一样的产品收取不同的价格,无论是对同一消费者还是对不同消费者。 一级价格歧视(完全价格歧视) 对于每一个消费者都收取不同的价格,而且价格定在消费者最多愿意支付的…

基于Java新生报到系统设计与实现(源码+lw+部署文档+讲解等)

博主介绍: ✌全网粉丝30W,csdn特邀作者、博客专家、CSDN新星计划导师、java领域优质创作者,博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战 ✌ 🍅 文末获取源码联系 🍅 👇🏻 精…

ZooKeeper【客户端命令行】

客户端连接ZooKeeper服务器 启动ZooKeeper集群 ./zkServer.sh start 启动客户端 ./zkCli.sh 我们发现启动客户端时它会默认连接本地的服务器,这是因为zookeeper客户端启动时默认连接的是本地模式。 指定连接集群中的服务器 ./zkServer.sh start -server hadoo…

C语言之结构体讲解

目录 结构体类型的声明 结构体初始化 结构体成员访问 结构体传参 对于上期指针初阶(2)我们后期还会讲数组指针是什么?大家可以先思考一下,后期我们会讲 1.结构体的声明 结构是一些值的集合,这些值被称为成员变量&am…

swagger解析

1.引用swagger包&#xff1a; !-- swagger --> <dependency><groupId>io.springfox</groupId><artifactId>springfox-swagger2</artifactId><version>2.7.0</version> </dependency> <dependency><groupId>io…

【Android -- JNI 和 NDK】Java 和 C/C++ 之间传递参数和返回值

本文主要介绍 JNI 的数据传递上&#xff0c;即 Java 如何传递对象给 C; 而 C 又如何将数据封装成 Java 所需的对象。 1. 基本数据类型 传递 java 的基本类型是非常简单而直接的&#xff0c;一个 jxxx 之类的类型已经定义在本地系统中了&#xff0c;比如&#xff1a;jint, jby…

RHCE shell 作业一

1. 设置邮箱 [rootserver ~]# yum install s-nail -y [rootserver ~]# vim /etc/s-nail.rc 编写脚本 [rootserver ~]# vim homework1.sh 设置定时任务 [rootserver ~]# vim /etc/crontab 2. [rootserver ~]# vim homework2.sh 测试&#xff1a; 3. [rootserve…

Maven配置多个镜像源 SpringBoot配置多个镜像源

Maven配置多个镜像源 SpringBoot配置多个镜像源 当在 Maven 中配置多个镜像源&#xff0c;并在 Spring Boot 项目中配置多个镜像源时&#xff0c;可以按照以下步骤进行操作&#xff1a; 1. Maven 中配置多个镜像源 在 Maven 的 settings.xml 文件中&#xff0c;按照以下示例配…

背单词学英语20年经验总结

推荐一款最近开发的单词小程序&#xff1a; 悟道单词&#xff0c;融入了卡片记忆&#xff0c;图像记忆等&#xff0c;融入了我20年背单词经验。 从这个小程序里我悟出了两大记忆原则 两个记忆原则&#xff1a; 1. 图像是文字之本法则 想一想我们原来是怎么记住中文字词的&#…

【文生图系列】基础篇-马尔可夫链

文章目录 马尔可夫链转移矩阵例子 应用实例参考 在阅读论文Denoising Diffusion Probabilistic Models时&#xff0c;发现论文里面介绍扩散概率模型&#xff08;diffusion probabilistic model&#xff09;是一个参数化的马尔科夫链&#xff08;parameterized Markov chain&…

List数组高效率去重

List数组高效率去重 一、环境准备–生成包含重复元素的list数组 /*** 生成包含重复元素的list数组* return*/ private static List<String> getList(){List<String> list new ArrayList<>();for (int i 1; i < 10000; i) {list.add(String.valueOf(i)…

Kendo UI for jQuery---03.组件___网格---02.开始

网格入门 本指南演示了如何启动和运行 Kendo UI for jQuery Grid。 完成本指南后&#xff0c;您将能够实现以下最终结果&#xff1a; 1. 创建一个空的 div 元素 首先&#xff0c;在页面上创建一个空元素&#xff0c;该元素将用作 Grid 组件的主容器。 <div id"my-…

SpringMVC组件原理剖析

文章目录 SpringMVC组件原理剖析一、 前端控制器初始化1.1 初始化SpringMVC容器1.2 注册了 SpringMVC的 九大组件1.3 处理器映射器初始化细节 二、前端控制器执行主流程2.1 定位doDispatcher方法2.2 验证HandlerExecutionChain2.3 HandlerAdapter执行目标方法 SpringMVC组件原理…

64位和32位相比优势是什么(一)

前置知识&#xff1a;程序是如何执行的&#xff1f; 一道常规的面试题&#xff1a;相比 32 位&#xff0c;64 位的优势是什么&#xff1f; 面试官考察这种类型的问题&#xff0c;主要是想看求职者是否有扎实的计算机基础&#xff0c;同时想知道求职者在工作中是否充满好奇&am…

路径规划算法:基于未来搜索优化的路径规划算法- 附代码

路径规划算法&#xff1a;基于未来搜索优化的路径规划算法- 附代码 文章目录 路径规划算法&#xff1a;基于未来搜索优化的路径规划算法- 附代码1.算法原理1.1 环境设定1.2 约束条件1.3 适应度函数 2.算法结果3.MATLAB代码4.参考文献 摘要&#xff1a;本文主要介绍利用智能优化…

【硬件专题】案例:怎么通过元件丝印信息反查芯片

今天同事和昨天因为工作上的原因,问我一个问题,就是怎么通过丝印(Marking code)知道用的是什么芯片。以下列举几个方法: 凭经验 比如昨天给出的一张图片,看图片是比较模糊的。但是根据之前的使用,看芯片LOGO很明显是ST的,然后看上面的型号是STM**F1*VCT*,那么…