627-计算机体系结构

计算机体系结构

我们在VS2019上编辑了一段代码,把它保存起来了,这个代码文件就叫做demo.c(代码的源文件)
这个源代码文件是在计算机的哪里存储的?
答案是在磁盘存储的。
在这里插入图片描述
源代码编译以后,在windows下产生*.obj文件,名称和源代码的文件是相同的,demo.obj
在Linux或者Mac下是.o文件
也叫做“二进制可重定位目标文件”

编译之后,还没有运行,编译产生的这些obj文件(或者是.o文件)也是在磁盘上放的

最终,所有.obj或者.o文件参与链接生成二进制可执行文件,在Windows下是*.exe文件,在Linux或者Mac下默认是a.out文件
生成的二进制可执行文件也是在磁盘上存储的。
在这里插入图片描述
二进制可重定位文件和可执行文件的名字都是和源代码的文件的名字一样。

这些都是在磁盘上存储的,还没有运行

当我们去运行二进制可执行文件(.exe或者a.out)的时候
在这里插入图片描述
我们在Windows去双击test.exe,或者在Linux上输入:./a.out的时候
执行程序了以后
操作系统都有一个程序加载器—loader,会把磁盘上的请求操作系统执行的程序从磁盘加载到内存上。
在这里插入图片描述
所有运行的程序都是要往内存上走的。

在磁盘上的可执行文件,我们在操作系统里面把它叫做程序

我们在Windows去双击test.exe,或者在Linux上输入:./a.out的时候,操作系统加载器就从磁盘把可执行程序的代码段和数据段加载到内存上。
此时,就不叫程序了,叫:进程
在这里插入图片描述
程序是在磁盘上的二进制可执行文件,当运行以后,程序的代码段和数据段就被加载到内存上,叫做进程。
进程放的东西就是从程序加载来的代码段,数据段,作为进程内部空间的初始化的数据。
在这里插入图片描述
然后,在程序头里面,会有当前进程main函数第一行的指令的地址,最终会把这个指令的地址给CPU,CPU就从进程的main函数的第一行指令开始执行了。
在这里插入图片描述
这个程序就跑起来了,开始按我们的代码从main函数的第一行开始一行一行的执行起来了

CPU是专门用来执行指令的。指令:我们写的源代码都被翻译成机器码存储在代码段中。

当CPU在执行我们当前的进程的时候,不断的去执行进程里的代码段上的指令代码,CPU和内存之间的交互是怎样交互的?
CPU和内存之间有3根线:
这3根总线分别叫做:控制总线,地址总线,数据总线
在这里插入图片描述
控制总线:CPU控制内存来使用的,内存相当于是一个存储,CPU在执行指令的过程中,有可能从内存中读数据,也有可能从内存中某一个地方写数据。
在这里插入图片描述
CPU在做这个I/O的时候,往标准的输出设备(屏幕)上输出a的时候,这个a是在内存上的,它得从内存上去读这个数据。

如果我们在指令上有这个操作:我们需要把a=20写到内存里面
就是往内存去写数据。
那么这个控制总线就是发控制的:0:读操作(读内存)
1:写操作(写内存)
标识CPU当前和内存交互的时候是读操作还是写操作。
如果是读操作,在哪里读啊?不管在哪里读,都是通过一个地址来标识的,这个地址是在指令上的
比如说,CPU在执行指令的过程中,指令上操作了某一个数据,也就是说得去读这个数据,那么这个指令上就有这个数据的地址
这就是地址总线:
在32位系统,我们可以把地址总线当作32位
在64位系统,我们可以把地址总线当作64位
这是16进制表示,2给数字表示1个字节
在这里插入图片描述
我们通过地址总线定位到内存的某个位置以后,我们就可以从定位到的地址读数据了
这就是靠数据总线了在这里插入图片描述
通过数据总线把数据从内存拿到CPU里了
写的话也一样,CPU通过控制总线发一个写操作的信号到内存上,往哪里写呢?指令上肯定有这个内存的地址,指令在运行的时候,指令要往某一个变量里写数据,这个变量肯定有一个地址,通过地址总线定位到内存上写的区域,然后通过数据总线传过去1个数据,就会把内存相应的定位到的地址的这个区域修改成我们发过去的数据

在这里插入图片描述
ALU:逻辑运算单元,专门做运算
这个main函数的第一行指令的地址是存放到CPU的ip寄存器里面的

不管是32位还是64位系统,CPU都有一组通用的寄存器。
ip寄存器(EIP寄存器):存放的是CPU下一行要运行的指令地址。
在这里插入图片描述
CPU下一次要执行的指令从哪里来?从EIP寄存器找即将要执行的指令的地址
怎么找?
首先,通过控制总线发1个读信号,要读内存,然后发一个地址总线,地址从EIP寄存器来,然后把这个地址通过地址总线发到内存上
定位到内存的某一块区域,然后通过数据总线读这个内存区域的数据,然后就读出来EIP寄存器存放的地址上的指令,最终定位到代码段,从代码段把main函数的第一行指令通过数据总线读过来,开始在CPU执行main函数
在这里插入图片描述

在执行指令的过程中,一行一行的往下执行。
每次执行指令的时候都得通过控制总线发读信号,然后通过地址总线定位内存地址,然后通过数据总线把内存相应区域的指令拿过来,放到CPU里面去执行。

执行指令的过程中,还有可能访问数据,
在这里插入图片描述
a++这个操作
当它把这个指令读到CPU里去执行这个指令的时候,这个指令的源代码:a++
实际上翻译成指令是:
x86的汇编指令:
1、从内存上把a的值拿到eax寄存器上,这个寄存器拿的是10(读操作)
2、然后eax=eax+1 10+1=11(ALU)
3、把eax寄存器计算好的值11放回内存的a变量的内存区(写操作)
在这里插入图片描述
在这里插入图片描述

区别:X86的汇编指令是从右往左看。AT&T的汇编指令是从左往右进行运算的

所以a++对应的是3条指令,所以a++不是原子操作。

我们还要考虑一个问题:
CPU执行这些指令,我们刚才说的是过程,但是这些指令是在哪里放的?
要执行这些指令,得先从内存上去取这些指令,取这些指令在本质上也是读内存,a++是3条指令,先从内存上取出来放到CPU中,才能去执行它。
取第1条指令,通过控制总线发读信号,通过地址总线定位到内存的这条指令的位置,再通过数据总线从内存上把指令读到CPU里,然后CPU执行这条指令,还要去内存上读a这个变量的值啊,然后这条指令操作完了之后,接下来是第二条指令,又要重复刚才的操作,通过控制总线发读信号,通过地址总线定位到内存的这条指令的位置,再通过数据总线从内存上把指令读到CPU里,然后CPU执行这条指令,太麻烦了!!!CPU和内存进行读写操作还是麻烦的,虽然速度非常快。
在这里插入图片描述
是怎么提高效率的?
它在第一次读这条指令的时候

在这里插入图片描述
它就把邻近的指令:
在这里插入图片描述
一起都从内存读到CPU里面了。
一次性读这么多指令,执行只执行第一条,剩下的这些邻近的指令放在哪里? CPU的缓存!

CPU不管是执行指令,从内存的进程的代码段读指令,还是从数据段读数据,它不是执行哪个指令就读哪个指令,当下读哪个数据只加载哪个数据到内存上,它是根据程序的局部性的运行原理,当CPU在执行某一个指令的时候,它会把这个指令的邻近的指令全部一次性加载到CPU里,同样的,CPU在执行某一条指令访问数据的时候,它不仅仅从内存上把当前要访问的数据加载过来,而是把这个数据邻近的数据都一次性加载过来CPU中。
CPU的ALU只处理当前该处理的指令,只读取当前需要的数据。
剩下的还没用到的指令或者数据放在CPU缓存中。

3级缓存
第一级缓存:专门的数据缓存,指令缓存
第二级缓存第三级缓存:数据和指令混合存放
缓存一般是几十k,几百k,甚至上M的,但是不会太大,毕竟缓存的模块是在CPU中的
这样,CPU执行完第一条指令,就到CPU缓存中读取刚才执行的指令的邻近的指令就可以了。
访问完刚才的数据,接下来要访问其他的邻近的数据,直接从CPU缓存中读这个数据缓存就可以了。

数据是可读可写的,指令只能读不能写的,指令的这块内存是受保护的。

32位系统有16个通用寄存器,寄存器也是4字节的,e开头的编译器。
64位系统,寄存器是8字节的,r开头的寄存器

64位的操作系统,代码不一定就是64位的指令,还要看编译器是32位的还是64位的,才知道

ALU从寄存器拿是最快的,其次是从缓存中拿,然后是从内存拿,最慢的是从磁盘拿,磁盘I/O非常慢。

数组的CPU缓存命中高,因为数组内存是连续的,数据都是邻近存储的,而链表每一个节点都是独立产生的,数据不是邻近的存储,没有办法很好的做CPU的缓存命中。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

林林林ZEYU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值