learn.lianglianglee.com/专栏/重学操作系统-完/03 程序的执行:相比 32 位,64 位的优势是什么?(下).md.html
2022-05-11 18:57:05 +08:00

1201 lines
32 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<!-- saved from url=(0046)https://kaiiiz.github.io/hexo-theme-book-demo/ -->
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=no">
<link rel="icon" href="/static/favicon.png">
<title>03 程序的执行:相比 32 位64 位的优势是什么?(下).md.html</title>
<!-- Spectre.css framework -->
<link rel="stylesheet" href="/static/index.css">
<!-- theme css & js -->
<meta name="generator" content="Hexo 4.2.0">
</head>
<body>
<div class="book-container">
<div class="book-sidebar">
<div class="book-brand">
<a href="/">
<img src="/static/favicon.png">
<span>技术文章摘抄</span>
</a>
</div>
<div class="book-menu uncollapsible">
<ul class="uncollapsible">
<li><a href="/" class="current-tab">首页</a></li>
</ul>
<ul class="uncollapsible">
<li><a href="../">上一级</a></li>
</ul>
<ul class="uncollapsible">
<li>
<a href="/专栏/重学操作系统-完/00 开篇词 为什么大厂面试必考操作系统?.md.html">00 开篇词 为什么大厂面试必考操作系统?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/00 课前必读 构建知识体系,可以这样做!.md.html">00 课前必读 构建知识体系,可以这样做!.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/01 计算机是什么:“如何把程序写好”这个问题是可计算的吗?.md.html">01 计算机是什么:“如何把程序写好”这个问题是可计算的吗?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/02 程序的执行:相比 32 位64 位的优势是什么?(上).md.html">02 程序的执行:相比 32 位64 位的优势是什么?(上).md.html</a>
</li>
<li>
<a class="current-tab" href="/专栏/重学操作系统-完/03 程序的执行:相比 32 位64 位的优势是什么?(下).md.html">03 程序的执行:相比 32 位64 位的优势是什么?(下).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/04 构造复杂的程序:将一个递归函数转成非递归函数的通用方法.md.html">04 构造复杂的程序:将一个递归函数转成非递归函数的通用方法.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/05 存储器分级L1 Cache 比内存和 SSD 快多少倍?.md.html">05 存储器分级L1 Cache 比内存和 SSD 快多少倍?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/05 (1) 加餐 练习题详解(一).md.html">05 (1) 加餐 练习题详解(一).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/06 目录结构和文件管理指令rm -rf 指令的作用是?.md.html">06 目录结构和文件管理指令rm -rf 指令的作用是?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/07 进程、重定向和管道指令xargs 指令的作用是?.md.html">07 进程、重定向和管道指令xargs 指令的作用是?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/08 用户和权限管理指令: 请简述 Linux 权限划分的原则?.md.html">08 用户和权限管理指令: 请简述 Linux 权限划分的原则?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/09 Linux 中的网络指令:如何查看一个域名有哪些 NS 记录?.md.html">09 Linux 中的网络指令:如何查看一个域名有哪些 NS 记录?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/10 软件的安装: 编译安装和包管理器安装有什么优势和劣势?.md.html">10 软件的安装: 编译安装和包管理器安装有什么优势和劣势?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/11 高级技巧之日志分析:利用 Linux 指令分析 Web 日志.md.html">11 高级技巧之日志分析:利用 Linux 指令分析 Web 日志.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/12 高级技巧之集群部署:利用 Linux 指令同时在多台机器部署程序.md.html">12 高级技巧之集群部署:利用 Linux 指令同时在多台机器部署程序.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/12 (1)加餐 练习题详解(二).md.html">12 (1)加餐 练习题详解(二).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/13 操作系统内核Linux 内核和 Windows 内核有什么区别?.md.html">13 操作系统内核Linux 内核和 Windows 内核有什么区别?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/14 用户态和内核态:用户态线程和内核态线程有什么区别?.md.html">14 用户态和内核态:用户态线程和内核态线程有什么区别?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/15 中断和中断向量Javajs 等语言为什么可以捕获到键盘输入?.md.html">15 中断和中断向量Javajs 等语言为什么可以捕获到键盘输入?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/16 WinMacUnixLinux 的区别和联系:为什么 Debian 漏洞排名第一还这么多人用?.md.html">16 WinMacUnixLinux 的区别和联系:为什么 Debian 漏洞排名第一还这么多人用?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/16 (1)加餐 练习题详解(三).md.html">16 (1)加餐 练习题详解(三).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/17 进程和线程:进程的开销比线程大在了哪里?.md.html">17 进程和线程:进程的开销比线程大在了哪里?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/18 锁、信号量和分布式锁:如何控制同一时间只有 2 个线程运行?.md.html">18 锁、信号量和分布式锁:如何控制同一时间只有 2 个线程运行?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/19 乐观锁、区块链:除了上锁还有哪些并发控制方法?.md.html">19 乐观锁、区块链:除了上锁还有哪些并发控制方法?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/20 线程的调度:线程调度都有哪些方法?.md.html">20 线程的调度:线程调度都有哪些方法?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/21 哲学家就餐问题:什么情况下会触发饥饿和死锁?.md.html">21 哲学家就餐问题:什么情况下会触发饥饿和死锁?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/22 进程间通信: 进程间通信都有哪些方法?.md.html">22 进程间通信: 进程间通信都有哪些方法?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/23 分析服务的特性:我的服务应该开多少个进程、多少个线程?.md.html">23 分析服务的特性:我的服务应该开多少个进程、多少个线程?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/23 (1)加餐 练习题详解(四).md.html">23 (1)加餐 练习题详解(四).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/24 虚拟内存 :一个程序最多能使用多少内存?.md.html">24 虚拟内存 :一个程序最多能使用多少内存?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/25 内存管理单元: 什么情况下使用大内存分页?.md.html">25 内存管理单元: 什么情况下使用大内存分页?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/26 缓存置换算法: LRU 用什么数据结构实现更合理?.md.html">26 缓存置换算法: LRU 用什么数据结构实现更合理?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/27 内存回收上篇:如何解决内存的循环引用问题?.md.html">27 内存回收上篇:如何解决内存的循环引用问题?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/28 内存回收下篇:三色标记-清除算法是怎么回事?.md.html">28 内存回收下篇:三色标记-清除算法是怎么回事?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/28 (1)加餐 练习题详解(五).md.html">28 (1)加餐 练习题详解(五).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/29 Linux 下的各个目录有什么作用?.md.html">29 Linux 下的各个目录有什么作用?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/30 文件系统的底层实现FAT、NTFS 和 Ext3 有什么区别?.md.html">30 文件系统的底层实现FAT、NTFS 和 Ext3 有什么区别?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/31 数据库文件系统实例MySQL 中 B 树和 B+ 树有什么区别?.md.html">31 数据库文件系统实例MySQL 中 B 树和 B+ 树有什么区别?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/32 HDFS 介绍:分布式文件系统是怎么回事?.md.html">32 HDFS 介绍:分布式文件系统是怎么回事?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/32 (1)加餐 练习题详解(六).md.html">32 (1)加餐 练习题详解(六).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/33 互联网协议群TCPIP多路复用是怎么回事.md.html">33 互联网协议群TCPIP多路复用是怎么回事.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/34 UDP 协议UDP 和 TCP 相比快在哪里?.md.html">34 UDP 协议UDP 和 TCP 相比快在哪里?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/35 Linux 的 IO 模式selectpollepoll 有什么区别?.md.html">35 Linux 的 IO 模式selectpollepoll 有什么区别?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/36 公私钥体系和网络安全:什么是中间人攻击?.md.html">36 公私钥体系和网络安全:什么是中间人攻击?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/36 (1)加餐 练习题详解(七).md.html">36 (1)加餐 练习题详解(七).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/37 虚拟化技术介绍VMware 和 Docker 的区别?.md.html">37 虚拟化技术介绍VMware 和 Docker 的区别?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/38 容器编排技术:如何利用 K8s 和 Docker Swarm 管理微服务?.md.html">38 容器编排技术:如何利用 K8s 和 Docker Swarm 管理微服务?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/39 Linux 架构优秀在哪里.md.html">39 Linux 架构优秀在哪里.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/40 商业操作系统:电商操作系统是不是一个噱头?.md.html">40 商业操作系统:电商操作系统是不是一个噱头?.md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/40 (1)加餐 练习题详解(八).md.html">40 (1)加餐 练习题详解(八).md.html</a>
</li>
<li>
<a href="/专栏/重学操作系统-完/41 结束语 论程序员的发展——信仰、选择和博弈.md.html">41 结束语 论程序员的发展——信仰、选择和博弈.md.html</a>
</li>
</ul>
</div>
</div>
<div class="sidebar-toggle" onclick="sidebar_toggle()" onmouseover="add_inner()" onmouseleave="remove_inner()">
<div class="sidebar-toggle-inner"></div>
</div>
<script>
function add_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.add('show')
}
function remove_inner() {
let inner = document.querySelector('.sidebar-toggle-inner')
inner.classList.remove('show')
}
function sidebar_toggle() {
let sidebar_toggle = document.querySelector('.sidebar-toggle')
let sidebar = document.querySelector('.book-sidebar')
let content = document.querySelector('.off-canvas-content')
if (sidebar_toggle.classList.contains('extend')) { // show
sidebar_toggle.classList.remove('extend')
sidebar.classList.remove('hide')
content.classList.remove('extend')
} else { // hide
sidebar_toggle.classList.add('extend')
sidebar.classList.add('hide')
content.classList.add('extend')
}
}
function open_sidebar() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.add('show')
overlay.classList.add('show')
}
function hide_canvas() {
let sidebar = document.querySelector('.book-sidebar')
let overlay = document.querySelector('.off-canvas-overlay')
sidebar.classList.remove('show')
overlay.classList.remove('show')
}
</script>
<div class="off-canvas-content">
<div class="columns">
<div class="column col-12 col-lg-12">
<div class="book-navbar">
<!-- For Responsive Layout -->
<header class="navbar">
<section class="navbar-section">
<a onclick="open_sidebar()">
<i class="icon icon-menu"></i>
</a>
</section>
</header>
</div>
<div class="book-content" style="max-width: 960px; margin: 0 auto;
overflow-x: auto;
overflow-y: hidden;">
<div class="book-post">
<p id="tip" align="center"></p>
<div><h1>03 程序的执行:相比 32 位64 位的优势是什么?(下)</h1>
<p>在 02 课时中我们学习了计算机的组成原理,还分析了一些你在工作中可能会遇到的问题。本课时,我们继续深入学习程序执行部分,进一步讨论程序在冯诺依曼模型上如何执行。</p>
<h3>程序的执行过程</h3>
<p>当 CPU 执行程序的时候:</p>
<p>1.首先CPU 读取 PC 指针指向的指令,将它导入指令寄存器。具体来说,完成读取指令这件事情有 3 个步骤:</p>
<p><strong>步骤 1</strong>CPU 的控制单元操作地址总线指定需要访问的内存地址(简单理解,就是把 PC 指针中的值拷贝到地址总线中)。</p>
<p><strong>步骤 2</strong>CPU 通知内存设备准备数据(内存设备准备好了,就通过数据总线将数据传送给 CPU</p>
<p><strong>步骤 3</strong>CPU 收到内存传来的数据后,将这个数据存入指令寄存器。</p>
<p>完成以上 3 步CPU 成功读取了 PC 指针指向指令,存入了指令寄存器。</p>
<p>2.然后CPU 分析指令寄存器中的指令,确定指令的类型和参数。
3.如果是计算类型的指令,那么就交给逻辑运算单元计算;如果是存储类型的指令,那么由控制单元执行。
4.PC 指针自增,并准备获取下一条指令。</p>
<blockquote>
<p>比如在 32 位的机器上,指令是 32 位 4 个字节,需要 4 个内存地址存储,因此 PC 指针会自增 4。</p>
</blockquote>
<p><img src="assets/Ciqc1F9fGs2AEfeRAADnPPOm_gU294.png" alt="图片1" /></p>
<p>了解了程序的执行过程后,我还有一些问题想和大家一起讨论:</p>
<ol>
<li>内存虽然是一个随机存取器,但是我们通常不会把指令和数据存在一起,这是为了安全起见。具体的原因我会在模块四进程部分展开讲解,欢迎大家在本课时的留言区讨论起来,我会结合你们留言的内容做后续的课程设计。</li>
<li>程序指针也是一个寄存器64 位的 CPU 会提供 64 位的寄存器这样就可以使用更多内存地址。特别要说明的是64 位的寄存器可以寻址的范围非常大,但是也会受到地址总线条数的限制。比如和 64 位 CPU 配套工作的地址总线只有 40 条,那么可以寻址的范围就只有 1T也就是 240。</li>
<li>从 PC 指针读取指令、到执行、再到下一条指令,构成了一个循环,这个不断循环的过程叫作<strong>CPU 的指令周期</strong>,下面我们会详细讲解这个概念。</li>
</ol>
<h3>详解 a = 11 + 15 的执行过程</h3>
<p>上面我们了解了基本的程序执行过程,接下来我们来看看如果用冯诺依曼模型执行<code>a=11+15</code>是一个怎样的过程。</p>
<p>我们再 Review 下这个问题:程序员写的程序<code>a=11+15</code>是字符串CPU 不能执行字符串,只能执行指令。所以这里需要用到一种特殊的程序——编译器。编译器的核心能力是翻译,它把一种程序翻译成另一种程序语言。</p>
<p>这里,我们需要编译器将程序员写的程序翻译成 CPU 认识的指令(指令我们认为是一种低级语言,我们平时书写的是高级语言)。你可以先跟我完整地学完操作系统,再去深入了解编译原理的内容。</p>
<p>下面我们来详细阐述 a=11+15 的执行过程:</p>
<p>1.编译器通过分析,发现 11 和 15 是数据,因此编译好的程序启动时,会在内存中开辟出一个专门的区域存这样的常数,这个专门用来存储常数的区域,就是数据段,如下图所示:</p>
<ul>
<li>11 被存储到了地址 0x100</li>
<li>15 被存储到了地址 0x104</li>
</ul>
<p><img src="assets/Ciqc1F9jNVKAbRJhAADt2il2zYI826.png" alt="1.png" /></p>
<p>2.编译器将<code>a=11+15</code>转换成了 4 条指令,程序启动后,这些指令被导入了一个专门用来存储指令的区域,也就是正文段。如上图所示,这 4 条指令被存储到了 0x200-0x20c 的区域中:</p>
<p>0x200 位置的 load 指令将地址 0x100 中的数据 11 导入寄存器 R0</p>
<p>0x204 位置的 load 指令将地址 0x104 中的数据 15 导入寄存器 R1</p>
<p>0x208 位置的 add 指令将寄存器 R0 和 R1 中的值相加,存入寄存器 R2</p>
<p>0x20c 位置的 store 指令将寄存器 R2 中的值存回数据区域中的 0x1108 位置。</p>
<p>3.具体执行的时候PC 指针先指向 0x200 位置,然后依次执行这 4 条指令。</p>
<p>这里还有几个问题要说明一下:</p>
<ol>
<li>变量 a 实际上是内存中的一个地址a 是给程序员的助记符。</li>
<li>为什么 0x200 中代表加载数据到寄存器的指令是 0x8c000100我们会在下面详细讨论。</li>
<li>不知道细心的同学是否发现,在上面的例子中,我们每次操作 4 个地址,也就是 32 位,这是因为我们在用 32 位宽的 CPU 举例。在 32 位宽的 CPU 中,指令也是 32 位的。但是数据可以小于 32 位,比如可以加和两个 8 位的字节。</li>
<li>关于数据段和正文段的内容,会在模块四进程和线程部分继续讲解。</li>
</ol>
<h3>指令</h3>
<p>接下来我会带你具体分析指令的执行过程。</p>
<p>在上面的例子中load 指令将内存中的数据导入寄存器,我们写成了 16 进制0x8c000100拆分成二进制就是</p>
<blockquote>
<p>这里大家还是看下图,需要看一下才能明白。</p>
</blockquote>
<p><img src="assets/CgqCHl9fMJiAXO1-AABvVvPHepg435.png" alt="12.png" /></p>
<ul>
<li>最左边的 6 位,叫作<strong>操作码</strong>,英文是 OpCode100011 代表 load 指令;</li>
<li>中间的 4 位 0000是寄存器的编号这里代表寄存器 R0</li>
<li>后面的 22 位代表要读取的地址,也就是 0x100。</li>
</ul>
<p>所以我们是把操作码、寄存器的编号、要读取的地址合并到了一个 32 位的指令中。</p>
<p>我们再来看一条求加法运算的 add 指令16 进制表示是 0x08048000换算成二进制就是</p>
<p><img src="assets/Ciqc1F9fMKGAT9ymAACIAk1pGnk727.png" alt="11.png" /></p>
<ul>
<li>最左边的 6 位是指令编码,代表指令 add</li>
<li>紧接着的 4 位 0000 代表寄存器 R0</li>
<li>然后再接着的 4 位 0001 代表寄存器 R1</li>
<li>再接着的 4 位 0010 代表寄存器 R2</li>
<li>最后剩下的 14 位没有被使用。</li>
</ul>
<p>构造指令的过程,叫作指令的编码,通常由编译器完成;解析指令的过程,叫作指令的解码,由 CPU 完成。由此可见 CPU 内部有一个循环:</p>
<ol>
<li>首先 CPU 通过 PC 指针读取对应内存地址的指令,我们将这个步骤叫作 Fetch就是获取的意思。</li>
<li>CPU 对指令进行解码,我们将这个部分叫作 Decode。</li>
<li>CPU 执行指令,我们将这个部分叫作 Execution。</li>
<li>CPU 将结果存回寄存器或者将寄存器存入内存,我们将这个步骤叫作 Store。</li>
</ol>
<p><img src="assets/Ciqc1F9fMKiAZhMVAABIVEePzcA916.png" alt="image" /></p>
<p>上面 4 个步骤,我们叫作 CPU 的指令<strong>周期</strong>。CPU 的工作就是一个周期接着一个周期,周而复始。</p>
<h4>指令的类型</h4>
<p>通过上面的例子,你会发现不同类型(不同 OpCode的指令、参数个数、每个参数的位宽都不一样。而参数可以是以下这三种类型</p>
<ol>
<li>寄存器;</li>
<li>内存地址;</li>
<li>数值(一般是整数和浮点)。</li>
</ol>
<p>当然,无论是寄存器、内存地址还是数值,它们都是数字。</p>
<p>指令从功能角度来划分,大概有以下 5 类:</p>
<ol>
<li>I/O 类型的指令,比如处理和内存间数据交换的指令 store/load 等;再比如将一个内存地址的数据转移到另一个内存地址的 mov 指令。</li>
<li>计算类型的指令,最多只能处理两个寄存器,比如加减乘除、位运算、比较大小等。</li>
<li>跳转类型的指令,用处就是修改 PC 指针。比如编程中大家经常会遇到需要条件判断+跳转的逻辑,比如 if-elseswtich-case、函数调用等。</li>
<li>信号类型的指令,比如发送中断的指令 trap。</li>
<li>闲置 CPU 的指令 nop一般 CPU 都有这样一条指令,执行后 CPU 会空转一个周期。</li>
</ol>
<p>指令还有一个分法,就是寻址模式,比如同样是求和指令,可能会有 2 个版本:</p>
<ol>
<li>将两个寄存器的值相加的 add 指令。</li>
<li>将一个寄存器和一个整数相加的 addi 指令。</li>
</ol>
<p>另外,同样是加载内存中的数据到寄存器的 load 指令也有不同的寻址模式:</p>
<ol>
<li>比如直接加载一个内存地址中的数据到寄存器的指令<code>la</code>,叫作直接寻址。</li>
<li>直接将一个数值导入寄存器的指令<code>li</code>,叫作寄存器寻址。</li>
<li>将一个寄存器中的数值作为地址,然后再去加载这个地址中数据的指令<code>lw</code>,叫作间接寻址。</li>
</ol>
<p><strong>因此寻址模式是从指令如何获取数据的角度,对指令的一种分类,目的是给编写指令的人更多选择</strong></p>
<p>了解了指令的类型后,我再强调几个细节问题:</p>
<ol>
<li>关于寻址模式和所有的指令,只要你不是嵌入式开发人员,就不需要记忆,理解即可。</li>
<li>不同 CPU 的指令和寄存器名称都不一样,因此这些名称也不需要你记忆。</li>
<li>有几个寄存器在所有 CPU 里名字都一样,比如 PC 指针、指令寄存器等。</li>
</ol>
<h4>指令的执行速度</h4>
<p>之前我们提到过 CPU 是用石英晶体产生的脉冲转化为时钟信号驱动的,每一次时钟信号高低电平的转换就是一个周期,我们称为<strong>时钟周期</strong>。CPU 的主频,说的就是时钟信号的频率。比如一个 1GHz 的 CPU说的是时钟信号的频率是 1G。</p>
<p>到这里你可能会有疑问:是不是每个时钟周期都可以执行一条指令?其实,不是的,多数指令不能在一个时钟周期完成,通常需要 2 个、4 个、6 个时钟周期。</p>
<h3>总结</h3>
<p>接下来我们来做一个总结。这节课我们深入讨论了指令和指令的分类。接下来,我们来看一看在 02 课时中留下的问题:<strong>64 位和 32 位比较有哪些优势</strong></p>
<p>还是老规矩,请你先自己思考这个问题的答案,写在留言区,然后再来看我接下来的分析。</p>
<p><strong>【解析】</strong> 其实,这个问题需要分类讨论。</p>
<ol>
<li>如果说的是 64 位宽 CPU那么有 2 个优势。</li>
</ol>
<p><strong>优势 1</strong>64 位 CPU 可以执行更大数字的运算,这个优势在普通应用上不明显,但是对于数值计算较多的应用就非常明显。</p>
<p><strong>优势 2</strong>64 位 CPU 可以寻址更大的内存空间</p>
<ol>
<li>如果 32 位/64 位说的是程序,那么说的是指令是 64 位还是 32 位的。32 位指令在 64 位机器上执行,困难不大,可以兼容。 如果是 64 位指令,在 32 位机器上执行就困难了。因为 32 位指令在 64 位机器执行的时候,需要的是一套兼容机制;但是 64 位指令在 32 位机器上执行32 位的寄存器都存不下指令的参数。</li>
<li>操作系统也是一种程序,如果是 64 位操作系统,也就是操作系统中程序的指令都是 64 位指令,因此不能安装在 32 位机器上。</li>
</ol>
</div>
</div>
<div>
<div style="float: left">
<a href="/专栏/重学操作系统-完/02 程序的执行:相比 32 位64 位的优势是什么?(上).md.html">上一页</a>
</div>
<div style="float: right">
<a href="/专栏/重学操作系统-完/04 构造复杂的程序:将一个递归函数转成非递归函数的通用方法.md.html">下一页</a>
</div>
</div>
</div>
</div>
</div>
</div>
<a class="off-canvas-overlay" onclick="hide_canvas()"></a>
</div>
<script defer src="https://static.cloudflareinsights.com/beacon.min.js/v652eace1692a40cfa3763df669d7439c1639079717194" integrity="sha512-Gi7xpJR8tSkrpF7aordPZQlW2DLtzUlZcumS8dMQjwDHEnw9I7ZLyiOj/6tZStRBGtGgN6ceN6cMH8z7etPGlw==" data-cf-beacon='{"rayId":"70997d4a2a423cfa","version":"2021.12.0","r":1,"token":"1f5d475227ce4f0089a7cff1ab17c0f5","si":100}' crossorigin="anonymous"></script>
</body>
<!-- Global site tag (gtag.js) - Google Analytics -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-NPSEEVD756"></script>
<script>
window.dataLayer = window.dataLayer || [];
function gtag() {
dataLayer.push(arguments);
}
gtag('js', new Date());
gtag('config', 'G-NPSEEVD756');
var path = window.location.pathname
var cookie = getCookie("lastPath");
console.log(path)
if (path.replace("/", "") === "") {
if (cookie.replace("/", "") !== "") {
console.log(cookie)
document.getElementById("tip").innerHTML = "<a href='" + cookie + "'>跳转到上次进度</a>"
}
} else {
setCookie("lastPath", path)
}
function setCookie(cname, cvalue) {
var d = new Date();
d.setTime(d.getTime() + (180 * 24 * 60 * 60 * 1000));
var expires = "expires=" + d.toGMTString();
document.cookie = cname + "=" + cvalue + "; " + expires + ";path = /";
}
function getCookie(cname) {
var name = cname + "=";
var ca = document.cookie.split(';');
for (var i = 0; i < ca.length; i++) {
var c = ca[i].trim();
if (c.indexOf(name) === 0) return c.substring(name.length, c.length);
}
return "";
}
</script>
</html>