cxuan本身的 Github 很是硬核,求各位大佬 star: github.com/crisxuan/be…git
汇编代码是计算机的一种低级表示,它是一种低级语言,能够从字面角度去理解它,包括处理数据、管理内存、读写存储设备上的数据,以及利用网络通讯等。编译器生成机器码通过了一系列的转换,这些转换遵循编程语言
、目标机器的指令集
和操做系统
。程序员
指令集就是指挥计算机工做的指令,由于程序就是按照必定执行顺序排列的指令。由于计算机的执行控制权由 CPU 操做,因此指令集就是 CPU 中用来计算和控制计算机的一系列指令的集合。每一个 CPU 在产出时都规定了与硬件电路相互配合工做的指令集。github
指令集有很多分类,可是通常分为两种,一种是精简指令集
,一种是复杂指令集
。具体描述以下编程
精简指令的英文是 reduced instruction set computer, RISC
,原意是精简指令集计算,简称为精简指令集,是 CPU 的一种 设计模式
,能够把 CPU 想象成一家流水线工厂,对指令数目
和寻址方式
都作了精简,使其实现更容易,指令并行执行程度更好,编译器的效率更高。设计模式
常见的精简指令集处理器包括 ARM、AVR、MIPS、PARISC、RISC-V 和 SPARC。数组
因此你就能理解缓存
这本书是讲啥的了。安全
它主要是基于 MIPS 体系结构把冯诺依曼体系的五大组件进行了逐一的硬件实现 + 软件设计介绍,更为重要的是引入了诸多并行计算的内容,这是大部分教材中忽略或者内容较少的,会根据这个思路把并行相关的内容,结合 OpenMP, CUDA 和 Hadoop/Spark 总体融入到新书中,毕竟这是将来发展的趋势markdown
还有这本书网络
这本书又是讲啥的。
这本书是讲 RISC-V 指令集的,由于指令集的不一样也区分了三个版本,三个版本???嗯,还有下面这个
这本书是讲 ARM 指令集的。
因此通常在看 CASPP 的时候并发的看看这本书是很是不错的选择。
精简指令集通常具备以下特征
复杂指令集的英文是 Complex Instruction Set Computing, CISC
,是一种微处理器指令集架构,也被译为复杂指令集。
复杂指令集包括 System/360、VAX、x86 等。
复杂指令集能够说是在精简指令集之上做出的改变。
复杂指令集的特色是指令数目多而复杂,每条指令字长并不相等,计算机必须加以判读,并为此付出了性能的代价。
通常来讲,提高 CPU 性能的方法有以下这几种
比较抽象,咱们后面会组织成文章具体介绍一下。
C 编译器会接收其余操做并把其转换为汇编语言
输出,汇编语言是机器级别的代码表示。咱们以前介绍过,C 语言程序的执行过程分为下面这几步
下面咱们更多的讨论都是基于汇编代码来讨论。
咱们平常所接触的高级语言,都是通过了层层封装的结果,因此咱们日常是接触不到汇编语言的,更不会用汇编语言来进行编程,这就和你不知道操做系统的存在同样,但其实你每一个操做,甚至你双击一个图标都和操做系统有关系。
高级语言的抽象级别很高,可是通过了层层抽象以后,高级语言的执行效率确定没有汇编语言高,也没有汇编语言可靠。
可是高级语言有更大的优势是其编译后可以在不一样的机器上运行,汇编语言针对不一样的指令集有不一样的表示。而且高级语言学习来更加通俗易懂,下降计算机门槛,让内卷更加严重(固然这是开个玩笑,冒犯到请别当真)。
话很少说,了解底层必须了解汇编语言。不然一个 synchronized 底层实现就可以让你头疼不已。并且,每天飘着也很差,早晚要落地。
了解汇编代码也有助于咱们优化程序代码,分析代码中隐含的低效率,而且这种优化方法一旦优化成功,将是量级的提升,而不是改改 if...else ,使用一个新特性所能比的。
计算机系统使用了多种不一样形式的抽象,能够经过一个简单的抽象模型来隐藏实现细节。对于机器级别的程序来讲,有两点很是重要。
首先第一点,定义机器级别程序的格式和行为被称为 指令集体系结构或指令集架构(instruction set architecture)
, ISA。ISA 定义了进程状态、指令的格式和每个指令对状态的影响。大部分的指令集架构包括 ISA 用来描述进程的行为就好像是顺序执行的,一条指令执行结束后,另一条指令再开始。处理器硬件的描述要更复杂,它能够同时并行执行许多指令,可是它采用了安全措施
来确保总体行为与 ISA 规定的顺序一致。
第二点,机器级别对内存地址的描述就是 虚拟地址(virtual address)
,它提供了一个内存模型来表示一个巨大的字节数组。
编译器在整个编译的过程当中起到了相当重要的做用,把 C 语言转换为处理器执行的基本指令。汇编代码很是接近于机器代码,只不过与二进制机器代码相比,汇编代码的可读性更强,因此理解汇编是理解机器工做的第一步。
一些进程状态对机器可见,可是 C 语言程序员却看不到这些,包括
程序计数器(Program counter)
,它存储下一条指令的地址,在 x86-64 架构中用 %rip
来表示。程序执行时,PC 的初始值为程序第一条指令的地址,在顺序执行程序时, CPU 首先按程序计数器所指出的指令地址从内存中取出一条指令,而后分析和执行该指令,同时将 PC 的值加 1 并指向下一条要执行的指令。
好比下面一个例子。
这是一段数值进行相加的操做,程序启动,在通过编译解析后会由操做系统把硬盘中的程序复制到内存中,示例中的程序是将 123 和 456 执行相加操做,并将结果输出到显示器上。因为使用机器语言难以描述,因此这是通过翻译后的结果,实际上每一个指令和数据均可能分布在不一样的地址上,但为了方便说明,把组成一条指令的内存和数据放在了一个内存地址上。
寄存器文件(register file)
包含 16 个命名的位置,用来存储 64 位的值。这些寄存器能够存储地址和整型数据。有些寄存器用于跟踪程序状态,而另外一些寄存器用于保存临时数据,例如过程的参数和局部变量,以及函数要返回的值。这个 文件
是和磁盘文件无关的,它只是 CPU 内部的一块高速存储单元。有专用的寄存器,也有通用的寄存器用来存储操做数。条件码寄存器
用来保存有关最近执行的算术或逻辑指令的状态信息。这些用于实现控件或数据流中的条件更改,例如实现 if 和 while 语句所需的条件更改。咱们都学太高级语言,高级语言中的条件控制流程主要分为三种:顺序执行、条件分支、循环判断
三种,顺序执行是按照地址的内容顺序的执行指令。条件分支是根据条件执行任意地址的指令。循环是重复执行同一地址的指令。
下面以条件分支为例来讲明程序的执行过程(循环也很类似)
程序的开始过程和顺序流程是同样的,CPU 从 0100 处开始执行命令,在 0100 和 0101 都是顺序执行,PC 的值顺序+1,执行到 0102 地址的指令时,判断 0106 寄存器的数值大于 0,跳转(jump)到 0104 地址的指令,将数值输出到显示器中,而后结束程序,0103 的指令被跳过了,这就和咱们程序中的 if()
判断是同样的,在不知足条件的状况下,指令会直接跳过。因此 PC 的执行过程也就没有直接+1,而是下一条指令的地址。
向量寄存器
用来存储一个或者多个整数或者浮点数值,向量寄存器是对一维数据上进行操做。机器指令只会执行很是简单的操做,例如将存放在寄存器的两个数进行相加,把数据从内存转移到寄存器中或者是条件分支转移到新的指令地址。编译器必须生成此类指令的序列,以实现程序构造,例如算术表达式求值,循环或过程调用和返回
我相信各位应该都知道汇编语言的出现背景吧,那就是二进制表示数据,太复杂太庞大了,为了解决这个问题,出现了汇编语言,汇编语言和机器指令的区别就在于表示方法上,汇编使用操做数
来表示,机器指令使用二进制来表示,我以前屡次提到机器码就是汇编,你也不能说我错,可是不许确。
可是汇编适合二进制代码存在转换关系的。
汇编代码须要通过 汇编器
编译后才产生二进制代码,这个二进制代码就是目标代码,而后由连接器将其链接起来运行。
汇编语言主要分为如下三类
助记符
,它有对应的机器码汇编语言的核心是汇编指令,而咱们对汇编的探讨也是基于汇编指令展开的。
CPU 是计算机的大脑,它也是整个计算机的核心,它也是执行汇编语言的硬件,CPU 的内部包含有寄存器,而寄存器是用于存储指令和数据的,汇编语言的本质也就是 CPU 内部操做数所执行的一系列计算。
没有内存,计算机就像是一个没有记忆的人类,只会永无休止的重复性劳动。CPU 所需的指令和数据都由内存来提供,CPU 指令经由内存提供,通过一系列计算后再输出到内存。
磁盘也是一种存储设备,它和内存的最大区别在于永久存储,程序须要在内存装载后才能运行,而提供给内存的程序都是由磁盘存储的。
通常来讲,内存内部会划分多个存储单元,存储单元用来存储指令和数据,就像是房子同样,存储单元就是房子的门牌号。而 CPU 与内存之间的交互是经过地址总线
来进行的,总线从逻辑上分为三种
CPU 与存储器之间的读写主要通过如下几步
下面咱们就来具体了解一下这三类总线
经过咱们上面的探讨,咱们知道 CPU 经过地址总线
来指定存储位置的,地址总线上能传送多少不一样的信息,CPU 就能够对多少个存储单元进行寻址。
上图中 CPU 和内存中间信息交换经过了 10 条地址总线,每一条线可以传递的数据都是 0 或 1 ,因此上图一次 CPU 和内存传递的数据是 2 的十次方。
因此,若是 CPU 有 N 条地址总线,那么能够说这个地址总线的宽度是 N 。这样 CPU 能够寻找 2 的 N 次方个内存单元。
CPU 与内存或其余部件之间的数据传送是由数据总线
来完成的。数据总线的宽度决定了 CPU 和外界的数据传输速度。8 根数据总线能够一次传送一个 8 位二进制数据(即一个字节)。16 根数据总线一次能够传输两个字节,32 根数据总线能够一次传输四个字节。。。。。。
CPU 与其余部件之间的控制是经过 控制总线
来完成的。有多少根控制总线,就意味着 CPU 提供了对外部器件的多少种控制。因此,控制总线的宽度决定了 CPU 对外部部件的控制能力。
内存结构
内存 IC 是一个完整的结构,它内部也有电源、地址信号、数据信号、控制信号和用于寻址的 IC 引脚来进行数据的读写。下面是一个虚拟的 IC 引脚示意图
图中 VCC 和 GND 表示电源,A0 - A9 是地址信号的引脚,D0 - D7 表示的是控制信号、RD 和 WR 都是好控制信号,我用不一样的颜色进行了区分,将电源链接到 VCC 和 GND 后,就能够对其余引脚传递 0 和 1 的信号,大多数状况下,+5V 表示1,0V 表示 0。
咱们都知道内存是用来存储数据,那么这个内存 IC 中能存储多少数据呢?D0 - D7 表示的是数据信号,也就是说,一次能够输入输出 8 bit = 1 byte 的数据。A0 - A9 是地址信号共十个,表示能够指定 00000 00000 - 11111 11111 共 2 的 10次方 = 1024个地址
。每一个地址都会存放 1 byte 的数据,所以咱们能够得出内存 IC 的容量就是 1 KB。
若是咱们使用的是 512 MB 的内存,这就至关因而 512000(512 * 1000) 个内存 IC。固然,一台计算机不太可能有这么多个内存 IC ,然而,一般状况下,一个内存 IC 会有更多的引脚,也就能存储更多数据。
内存读取过程
下面是一次内存的读取过程。
来详细描述一下这个过程,假设咱们要向内存 IC 中写入 1byte 的数据的话,它的过程是这样的:
A0 - A9
来指定数据的存储场所,而后再把数据的值输入给 D0 - D7
的数据信号,并把 WR(write)
的值置为 1,执行完这些操做后,便可以向内存 IC 写入数据此篇文章咱们主要探讨了指令集、指令集的分类,与汇编有关的硬件,总线都有哪些,分别的做用都是什么,而后咱们以一次内存读取过程来链接一下 CPU 和内存的交互过程。
原创不易,若有帮助还请各位读者四连(点在、在看、分享、留言),感谢各位大佬
关注公众号 程序员cxuan 回复 cxuan 领取优质资料。
我本身写了六本 PDF ,很是硬核,连接以下
我本身写了六本 PDF ,很是硬核,连接以下
我本身写了六本 PDF ,很是硬核,连接以下