聊聊计算机组成原理

聊聊计算机组成原理计算机组成原理,理解相关运算流程,从底层理解相关原理,对于高级语言开发的工作者都是有很大的帮助。可以从底层理解语法的逻辑作用。 计算机五大硬件结构 存储器结构比较 存储速度带,原码,反码,补码,移码

计算机组成原理

前言

学好计算机组成原理,理解相关运算流程,从底层理解相关原理,对于高级语言开发的工作者都是有很大的帮助。可以从底层理解语法的逻辑作用。

计算机五大硬件结构

计算机硬件.png

存储器结构比较

存储器比较.png

存储速度带来问题

存储器速度.png

  • 因为不同存储器因价格及速度原因,市场上的计算机都是使用多级缓存的存储器结构。多级缓存可以弥补cpu运行速度和主存运行速度不匹配的问题所带来的效率降低,但也带来了线程安全。主流cpu都带有三级缓存 L1,L2,L3。每级缓存预加载相应的指令及数据,造成多核多线程下的数据安全问题。对于共享资源,我们要做好线程安全问题。

怎么理解并行和并发

  • 并发: 两个或两个以上的事件在同一时间段发生
  • 并行: 两个或两个以上的事件在同一时刻发生

指令流水技术及指令优化

  • 指令的串行执行

指令的串行执行.png

  • 指令的二级流水

多级指令.png

多级流水技术可以在部件在空闲时继续工作,并行加载其他指令,大大压榨各个部件的利用率。 多级流水技术有:

  • 超标量技术

image.png

  • 超流水线技术

image.png

  • 超长指令字技术

image.png

理解

image.png

image.png

问题:

  • 结构相关 :不同指令争用同一功能部件产生资源冲突

解决:

停顿等待

指令存储器和数据存储器分开

指令预取技术 (适用于访存周期短的情况)

  • 数据相关:不同指令因重叠操作,可能改变操作数的 读/写 访问顺序

解决:

后退法

旁路技术

思考:这些解决办法都是系统底层帮我们解决,对于高级语言开发人员是透明的。但是在开发时,代码的顺序及出现的线程安全问题需要我们解决的。例如编译后的代码被优化是否会出现顺序性问题。我们可以使用volatile禁止指令重排序等。

系统中断现场保护

image.png

  • 单重中断

不允许中断现行的中断服务程序

  • 多重中断 允许级别更高的中断源中断现行的中断服务程序

image.png

原码,反码,补码,移码

对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式.

原码

定义

原码(true form)是一种计算机中对数字的二进制定点表示方法。原码表示法在数值前面增加了一位符号位(即最高位为符号位),该位为0表示正数,该位为1表示负数,其余位表示数值的大小。 比如如果是8位二进制:

[+1]原 = 0000 0001

[-1]原 = 1000 0001

为什么需要

计算机只能识别0和1,使用的是二进制。而在日常生活中人们使用的是十进制,并且我们用的数值有正负之分。于是在计算机中就用一个数的最高位存放符号(0为正,1为负)。这就是机器数的原码了。

反码

正数的反码是其本身

[+1] = [0000 0001]原 = [0000 0001]反

负数的反码是在其原码的基础上, 符号位不变,数值位取反

[-1] = [1000 0001]原 = [1111 1110]反

为什么需要

计算十进制的表达式: 1-1=0

1 – 1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [1000 0010]原 = -2

结果表明原码无法作减法运算

如果用原码表示, 让符号位也参与计算, 显然对于减法来说, 结果是不正确的.这也就是为何计算机内部不使用原码表示一个数.

为了解决做减法的问题, 出现了反码:

计算十进制的表达式: 1-1=0

1 – 1 = 1 + (-1) => [0000 0001]原 + [1000 0001]原=> [0000 0001]反 + [1111 1110]反 => [1111 1111]反 = [1000 0000]原 = -0
结果为-0
发现用反码计算减法, 结果的真值部分是正确的.但是符号部分不正确,+0和-0对人理解是一样的,但是计算机不同,需要唯一的。于是出现补码

补码

正数的补码就是其本身

[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补

负数的补码是在其原码的基础上, 符号位不变, 其余各位取反, 最后+1. (即在反码的基础上+1)

[-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补

补的理解

image.png

计算机巧妙地把符号位参与运算, 并且将减法变成了加法, 背后蕴含了怎样的数学原理呢?

将钟表想象成是一个1位的12进制数. 如果当前时间是6点, 我希望将时间设置成4点, 需要怎么做呢?我们可以:

  1. 往回拨2个小时: 6 – 2 = 4
  2. 往前拨10个小时: (6 + 10) mod 12 = 4
  3. 往前拨10+12=22个小时: (6+22) mod 12 =4

2,3方法中的mod是指取模操作, 16 mod 12 =4 即用16除以12后的余数是4.

所以钟表往回拨(减法)的结果可以用往前拨(加法)替代!

计算机中的物理存储位类似钟表,钟表是模12,存储位有32位64位等。超过位数会被计算机舍去,因为物理已经存不了溢出的位数了,相当于钟表的,超过可以重回。具有模的特性,所有减法(回退)可以转变为加法(前进)。cpu等电路设计大大简化。

为什么需要

补码的出现, 解决了0的符号以及两个编码的问题:

1-1 = 1 + (-1) = [0000 0001]原 + [1000 0001]原 = [0000 0001]补 + [1111 1111]补 = [0000 0000]补=[0000 0000]原

这样0用[0000 0000]表示, 而以前出现问题的-0则不存在了.而且可以用[1000 0000]表示-128:

(-1) + (-127) = [1000 0001]原 + [1111 1111]原 = [1111 1111]补 + [1000 0001]补 = [1000 0000]补

-1-127的结果应该是-128, 在用补码运算的结果中, [1000 0000]补 就是-128.

注意:

实际上是使用以前的-0的补码[-0]=[1000 0000]原=[1111 1111]反=[1000 0000]补来表示-128,  

所以-128并没有原码和反码表示(-128直接对应补码 [1000 0000]补).
(对-128的补码表示[1000 0000]补算出来的原码是[0000 0000]原, 这是不正确的)

使用补码, 不仅仅修复了0的符号以及存在两个编码的问题, 而且还能够多表示一个最低数. 这就是为什么8位二进制, 使用原码或反码表示的范围为[-127, +127], 而使用补码表示的范围为[-128, 127].

因为机器使用补码, 所以对于编程中常用到的32位int类型, 可以表示范围是: [-231, 231-1] 因为第一位表示的是符号位.而使用补码表示时又可以多保存一个最小值.

总结:

  1. 使符号位能与有效值部分一起参加运算,从而简化运算规则.
  2. 使减法运算转换为加法运算,进一步简化计算机中运算器的线路设计

移码

如果把所有的数字,都加上 128,也就是把 -128 ~ +127 的范围的数字,都平移到 0 ~ 255 范围内,然后再用 0 ~ 255 的“机器数”来表示,这就是移码。移码(又叫增码或偏置码)通常用于表示浮点数的阶码,其表示形式与补码相似,只是其符号位用“1”表示正数,用“0”表示负数,数值部分与补码相同。

移码 = 补码符号位第一位数字取反

[+1] = [0000 0001]原 = [0000 0001]反 = [0000 0001]补= [1000 0001]移 [-1] = [1000 0001]原 = [1111 1110]反 = [1111 1111]补= [0111 1111]移

为什么需要

补码表示很难直接判断其真值大小,通过右移进行判断

image.png

总结:

  1. 正数:原码=反码=补码
  2. 负数:反码=原码符号位不变, 其余各位取反;补码=反码符号位不变,数据项+1
  3. 移码 = 补码的符号位直接取反(符号位除外)

十进制互转二进制

  • 十转二

十进制数除2,余数为权位上的数,得到的商值继续除,从下到上读每项的余数就是二进制数

10转2.jpg

  • 二转十

2转10.jpg

把二进制数按权展开、相加即得十进制数。

十进制与八进制与十六进制之间的转换

原理同上

image.png

image.png

进制在java中的应用

    public static void main(String[] args) {
        int a = 0x2f;//0x 小写十六进制(等价于0x002f)
        int c = 0144;//0 八进制
        int d = 144;//0 十进制
        //15*16^0+2*16^1
        System.out.println(a);//47
        //4*8^0+4*8^1+1*8^2=4+32+64=100
        System.out.println(c);//100
        System.out.println(d);//144
        //十六进制
        System.out.println(Integer.toHexString(c));//64
        //八进制
        System.out.println(Integer.toOctalString(c));//144
        //二进制
        System.out.println(Integer.toBinaryString(a));//101111
        System.out.println(Integer.toUnsignedString(c));//100
        int b = 0x2F;//大写十六进制
        System.out.println(Integer.toBinaryString(b));//101111
    }

参考视频《计算机组成原理》,对于想要更深入了解计算机组成原理,推荐 www.bilibili.com/video/BV1WW…

今天的文章聊聊计算机组成原理分享到此就结束了,感谢您的阅读。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/17113.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注