计算机-第一期合集
2022-05-21 18:10:56 0 举报
计算机体系
作者其他创作
大纲/内容
堆栈段寄存器 ss
谁来研究编译器怎么写?
保存段描述表的基地址
何为计算机体系结构?
WB写回
汇编语言
小结: 写好的汇编代码源程序,经过汇编器转换成机器码保存到硬盘,当 CPU 需要读取时,硬盘上的数据会被加载到内存中,然后部分数据会读取到 CPU 的缓存中加快执行,CPU 是面向缓存来进行交互的。至于,代码怎么保存的?加载到内存中是如何分布的都是通过 操作系统来控制
物理地址
通过编译原理的知识引申出其他知识
CPU
往小看:CPU 内部ISA 指令集,告诉控制单元,从存储单元获取数据,再运算单元中处理,然后写回到存储单元ISA 指令集就是对存储单元的数据,通过控制单元在运算单元中进行 CRUD往大看:计算机硬件ISA指令集控制 CPU 里面的控制组件去把从内存读取到缓存再提取到寄存器里的数据,进行 CRUD 再写回到缓存然后写回内存,最后内存又可以输出到外设或者硬盘
一组代码组成(指令流组成)
虚拟内存、分页
LLVM
虚拟地址
可以关联到数据结构
汇编器
数据结构
指令地址寄存器
存储单元(寄存器)MU
引出
编译器
如果直接写一堆的二进制数,那太难了,直让人眼花,编写和排错都太难。因此,在此基础上增加了一层抽象,也就是汇编语言,使用英语进行编写程序然后通过汇编器编译成对应的一堆二进制数(机器语言)
xx段寄存器
....
保护模式
汇编指令4
控制单元CU
推理可得
B 私有内存
栈帧
专用寄存器那么也就存在通用寄存器,可以专用也可以随便使用的寄存器
放到内存中,因为 CPU 的运行速度太快,代码从硬盘加载到内存进行加快访问;对于 CPU 来说还是慢,所以在 CPU 中也会加缓存那么具体硬盘如何保存代码?又读取到内存后怎么分布的?这些都是操作系统来进行控制了
需要执行的指令放在哪?
(1)提供了保护模式(2)真 32 位机 (32位寄存器,32位地址总线,32位数据总线)(3)虚拟内存(基于段的)(4)特权级(4个等级): CPL RPL DPL(5)指令流水线(6)一级缓存(7)内存模型(实模式和保护模式)(8)分页
(1)类型系统,屏蔽对内存单元的访问 操作多少字节(byte、char、short.....) 比如:看下汇编语言 xxxb xxxw xxxl 表示操作一个字节、两个字节、四个字节(2)抽象对数据的操作,+-*/ = .....,定义符号表示 比如:汇编的数据操作(mov、add .......)(3)抽象控制流程,if while 比如:抽象了汇编的 jmp jne ....(4)添加语言自身的特性 C 语言并没有扩展自己特性,所以是最纯粹的汇编抽象语言
可以将内存的数据缓存到硬盘上,段描述符中一位二进制数(P) 进行表示当前段的数据是否在内存中
4
锁存器
页描述符表
...
通过画图发现指令段 call 的过程,具有先进后出的特点,那么对应的内存使用顺序也符合这一特点,这不就是数据结构——栈。span style=\
全局段描述表
...12
《计算机体系结构精髓》
栈帧,用来保存代码段的私有数据,rbp 和 rsp 限定出当前执行的代码段的栈帧大小栈内存的栈帧通过 是 rsp 减少(增加)来开辟(销毁)内存空间(栈内存增长方向高地址到低地址)
操作系统也是一个程序,地位特殊。其他程序不可以直接操作操作系统的内存
span style=\
ID译码
数据段内存
代码段寄存器 cs
总结
《计算机组成与嵌入式系统》
例子:假如从内存取数据进行加一操作从 CPU 角度分为: 1.将数据加载到寄存器 2.对寄存器的数+1 3.将寄存器的数写回内存
因为 16位的寄存器寻址范围是 64kb (2^16),提供的内存是 1M( 2^20)那为什么不设计 20 位寄存器呢?因为设计的时候就是按照 16 位设计,没想到甲方修改了需求内存变大成 1 M,故此在最小的改动上选择增大地址总线到 20 位,在增加一种寄存器来对内存进行分段,叫段寄存器,而指令地址寄存器表示当前内存段的偏移量。 2^16=64k 2^20 = 1M 所以 1M 的内存可以分成 2^4=16 段
栈顶
汇编代码
EX执行
指令=操作码+操作数
通用段寄存器 es
SSB
怎么控制 CPU 呢?
C 语言屏蔽 CPU 的底层实现,面向更符合人类的习惯的编程方式
数据结构的贯穿整个知识树,同样一直出现的还有算法数据结构:存储数据的结构算法:给定输入按照定义和限制进行输出 数据结构 + 算法,相辅相成,缺一不可 (数据的存放形式,数据的操作动作)推理得出,数据结构与算法存在于计算机的每个地方,是与语言无关的;而每个语言均拥有相同的数据结构和算法,就如同自然包含阴阳。
A 私有内存
代码段内存
这样我们就理解了 Java 语言说的一次编译到处运行了。后端提供跨平台能力,后端只需要解析前端提供的 IR (字节码,那么前端可以和各种各样的语言进行适配,只需要生成约定好的中间语言(IR)即可后端想要跨平台,那就是适配所有的 ISA 指令架构即可。当前也就两种 Intel ARM
目的是推出汇编
Global Descriptor Table Register
得出:体系结构研究的内容造出更小的单元、更多的逻辑、更小的功耗、更高的性能的计算机
汇编指令2
寄存器组
目录
linux-2.6.0\\arch\\i386\\kernel\\head.SENTRY(cpu_gdt_table).quad 0x00cf9a000000ffff/* 0x60 kernel 4GB code at 0x00000000 */.quad 0x00cf92000000ffff/* 0x68 kernel 4GB data at 0x00000000 */.quad 0x00cffa000000ffff/* 0x73 user 4GB code at 0x00000000 */.quad 0x00cff2000000ffff/* 0x7b user 4GB data at 0x00000000 */
Java Scala ....
总线
实模式的情况下,需要规划好不同程序位置,不灵活,无法运行更多的程序。
《计算机组成与体系结构》
树
操作系统
指令流水线
ARM
堆内存
晶体三级管
实现方式连续的空间,也可以叫它数组;通过约定好的数组下标找到上一个数据而不连续空间,链表结构则需要在当前数据中保存上一个数据的内存地址
前言
由于抽出一层,所以需要一个中间层,编译器将 C 语言编译成机器码
栈
intel 手册
核心思想:抽象了汇编语言对于CPU和内存的操作
编译原理
中间表示
栈内存:代码段专享,动态分配堆内存:多个指令流共享的数据,动态分配代码段内存:保存程序的指令流,静态分配数据段内存:保存编译时就存在的数据,静态数据,静态分配
硬盘
4KB
运算器
ISA 指令集
通用寄存器
指令集与 CPU 相关,而汇编语言与指令集相关所以汇编语言就是面向 CPU 编程,而汇编语言的写法取决于 ISA 指令集汇编语言是所有语言的基础,往上衍生无数种语言
按照功能对内存划分
《汇编语言,基于 x86 处理器》
专用寄存器
B: 代码段
一些名词的解析
DSB
状态寄存器
如何设计一门语言呢?
为了提高访问效率,避免每次都来这么个流程,所以每个段寄存器都配有一个高速缓冲寄存器,称之为段描述符高速缓冲寄存器。对程序员而言它是不可见的。每当把一个段选择子装入到某个段寄存器时,处理器自动从描述符表中取出相应的描述符,把描述符中的信息保存到对应的高速缓冲寄存器中。此后对该段访问时,处理器都使用对应高速缓冲寄存器中的描述符信息,而不用再从描述符表中取描述符。
计算机语言的本质是对下一级语言的抽象
CSB
计算机硬件
TODO
虚拟内存
前端
CSA
L
M访存
地址总线
栈内存
call ...
屏蔽 CPU 底层处理,面向更符合人类习惯的编程方式,而不需要去详细了解 CPU 的构建和计算机的组成原理与体系结构简单点:抽象了汇编语言对于 CPU 和内存的操作最纯粹的汇编抽象,没有扩展自身语言的特性
GDT
存储器
目标语言
VM
验证
linux
最简单的做法:程序隔离虚拟地址与物理地址做映射
参照
其他程序运行的内存分布情况
栈顶寄存器
如何学习汇编语言呢?
怎么做?
call
往大看
old_bp
指令段 A:
五大组成结构
解答
A 的栈底
得出:计算机组成原理是基于计算机体系结构研究计算机硬件之间组合的交互行为
内存
操作 CPU 去控制其他硬件具体过程:就是通过操作 CPU 的控制单元,控制存储单元,运算单元去对来自缓存数据进行 CRUD 操作。抽象了 ISA 指令集的规则,提供了人类方便识别和编写的代码方式(助记符)总结:操作 CPU 的寄存器与运算单元,将结果写回内存;简单说:汇编就是操作寄存器的一门语言
堆
汇编是针对的是内存和CPU,汇编要去对某一个值,拿出来放到 CPU 进行 CRUD,并且汇编语言是基于 ISA 指令集,开发的利于识别的语言,span style=\"font-size: inherit;\
代码段
RPL: 全称request privilege level,请求特权级,存放在段选择子中CPL:全称current privilege level,代表当前执行程序的特权级,是特殊的 RPL (处于 SS 和 CS )DPL: 全称descriptor privilege level,存放在段描述符中,用于表示段的特权级font color=\"#ff00ff\
得出:计算机最底层的操作就是汇编语言通过操作 CPU 硬件去操作其他硬件进行输入输出
所以分段模式太鸡内了,并且 Intel 手册规定还必须要分段,所以 linux 中就分了一段
CPU 组成
栈底
数据段
控制器
指令集就是 y=f(x) x 是机器语言
通过和数论,电学进行组合进行制造出计算机硬件
汇编指令7
汇编和 CPU 的 ISA 指令架构相关font color=\"#ff00ff\
H
首先得了解 ISA 指令集
A: 代码段
复杂指令集: CISC
用 16进制来存储空间进行编号就有了高地址和低地址
什么叫寄存器?
后端
CU、AU、MU 是 CPU 的核心单元CPU 缓存的数据是取自内存,存储单元的数据来自缓存,所以我们也可以将存储单元叫寄存器
往小看
20位地址总线
程序存储执行
看书验证
汇编指令3
段选择子的结构
交换分区
程序分段的模式,存在的缺点:由于分段的大小不规则,使得容易造成内存外碎片;还有交换数据到硬盘虚拟内存时,因只需要一小快数据而要加载这个段的数据于是就出现了一种别的方式:分页。每一快的大小相同 4kb(intel 最大 4M),太大易产生内存内碎片,太小分的页就多为了维持线性地址和物理地址的映射关系,所以就需要页描述符表(类似段描述符表)来保存页的元数据比如页帧的大小,PL,物理基地址等信息。 e.g. 4GB/4KB
推理得出,每一个语言的第一个编译器,都是由下一层语言来实现;然后再用自己的语言重新写一个编译器,再用它编译出来就形成了新的语言
CPU 内部也有一样的硬件组成微服务里面也有一套这样的结构依旧还是冯诺依曼体系往大说:业务服务器、Redis、数据库
语法分析 词法分析
指向该段的段描述符
物理内存
在易经中的伏羲一画开天,想出阴阳,用阴阳来表示信息
当前执行的指令段对应的栈帧
外设
内存最小寻址单元是 1 字节=8位
代码段 A 跳转到代码段 B ,代码段会有私有数据需要存放,那么就需要在栈内存开辟一块空间,将这块保存一组数据的空间叫帧——而这片空间是在栈内存中,于是叫做栈帧
CS:IP = CS << 4 + IP
访问
计算机的基石
IF取指
指令流水线,将一个指令周期拆分成多个步骤,每步完成后将结果保存到锁存器中,那么就可以并行执行多条指令从而提高执行效率。因为之前指令的执行方式是需要等到一条指令执行完成后才会处理下一个指令。
可谓一阴一阳,阴阳交替生万物
操作系统统一控制 CPU CPU 指导操作系统开发
数据总线
汇编很简答,汇编就是操作寄存器
图灵一念之想得到了计算机简易版,冯诺依曼给了它灵魂
依旧还是冯诺依曼体系
1982-i286 1985-i386 (32位机出现)1989-i486;(1)提供了保护模式(2)真 32 位机 (32位寄存器,32位地址总线,32位数据总线)(3)虚拟内存(基于段的)(4)特权级(4个等级): CPL RPL DPL(5)指令流水线(6)一级缓存(7)内存模型(实模式和保护模式)(8)分页
高速缓存
汇编指令5
计算机的体系结构
运算单元AU
3
控制总线
.text 代码段 .data 数据段$字符串+: 表示代码片段,就是指令段的执行起始位置 e.g. call b
由于抽出一层,所以需要一个中间层,汇编器编译成机器码
中间产物 (IR)
汇编是什么?
ISA 指令
以二进制为计算机的数值计算基础,0/1
设想:能不能设计出一个机器去执行所有的计算?
输出设备
规则
数据段寄存器 ds
intel
DSA
类比学习得到:前端,词法分析----单词流---->语法分析----语法树------>语义分析----带有语义的语法树 (AST) ----> 中间产物后端,根据中间产物进行分析优化,生成目标语言。那么得出下面的简单流程 e.g.
已经知道计算机世界中是用二进制来表示信息,把现实的信息抽象到计算机中,也就是对信息进行编码。所以需要向 CPU 输入编码信息,从而来控制计算机而具体编码规则,CPU 厂商必须进行规定并告诉使用者这样的编码规则称之为:指令集架构 ISAe.g. 0001 0001 表示某个操作 ---Intel PC 端用户较多,所以之后用 Intel 来进行分析
计算机一切由 0 1 组成,万事万物由阴阳组成
汇编指令1
编译原理是非常重要,起到了承上启下的作用。它将抽象的上一层语言转化为计算机能理解的指令,也就是机器码。好比,社会环境中的翻译官,实现不同国家语言的转换。所以我们可以通过类比现实中的翻译过程来,理解计算机世界中的编译原理思想。翻译者听到英语后,在自己的脑中转为自己理解的东西(中间产物),依据自己理解的意思再根据中文的语法和词语进行翻译成中文 ——这就是编译原理的本质。
ISA 定义了一组规则,根据规则去控制 CPU 的控制器,来操作寄存器组的数据,而寄存器的数据来自高速缓存,将寄存器的数据通过运算单元进行 CRUD ,在写回寄存器或内存至此,汇编就是控制 CPU 的寄存器组进行计算后写回内存
段描述符高速缓存
1
加法器、锁存器、触发器......
ISA
内存地址
DS/ES
段寄存器+指令地址寄存器=物理地址
SRAM
程序 A
实现方式,内存连续和不连续,数组和链表呗连续的空间,也可以叫它数组;通过约定好的数组下标找到上一个数据而不连续空间,链表结构则需要在当前数据中保存上一个数据的内存地址
a=1
1978 16-bit Processors and Segmentation808616位的寄存器,16位的数据总线,20位地址总线8088 16位的寄存器,8位的数据总线,20位地址总线重点:段寄存器其他不是重点,为了配合某种甲方需求吧
OS 系统内存
程序 B
指令段 B:
目的
段寄存器
RPL
精简指令集: RISC
引申:秒杀的一种做法,到时间才提供真实的抢购地址
低地址 L
段选择子+段描述符部分信息(不可见)
机器码
类型
OS
一切语言都需要:抽象对内存的访问,抽象对汇编指令的操作然后来设计自己的语言通过解析成一个 AST 的抽象语法树,得到约定中间产物 IR ——这就是语言的前端再通过 IR 输入到后端,解释器进行得到成机器码
为什么需要保护模式?
只有代码段才分为:一致性代码段和非一致代码段 (段描述符当 S=1 4位的TYPE中 执行位 一致位 读写位 访问位 )一致性代码段:共享代码段,低权级也可以正常转移到目标代码段执行 ( 指令地址寄存器保存目标代码段的起始地址)非一致性代码段:DPL == CPL 才可以正常转移到目标代码段执行( 指令地址寄存器保存目标代码段的起始地址)
已经说了指令段的私有数据内存,哪指令段的共享数据内存,怎么处理呢?简单,因为只要有内存地址不同的指令段都可以通过内存地址取到数据,比如 C 语言方法参数传递,个数超过能用的寄存器就会采用栈内存传递,只是栈内存开辟和销毁会随着指令段执行完成后,容易被新的栈帧覆盖,所以单独划出一片内存(堆),不像栈内存那样容易被覆盖。至此,指令段之间都有共享数据的内存地址,就达到了共享了,而这个内存地址可以放到数据段中。汇编代码是要被汇编器编译后才能被转化成机器语言,所以汇编器会有一套它能识别的汇编代码的编写规则
操作系统面向 CPU 开发, CPU 厂商指导操作系统开发CPU 为了满足不同的操作系统开发,同一个事情提供了多种实现方式
物理
CS/SS
数学
CPU 可以控制整个计算机
防止践踏到操作系统内存
rsp
RAM
GDTR 指向的是保存在内存的段描述表的基地址;为了访问内存的线性地址,处理器通过选择子 (index)在段描述符表中获得对应的段描述符信息,段描述符信息(段基址,段的大小,特权级等信息),实际的线性地址就等于段基址加上指令地址寄存器的偏移量。
源语言
栈底寄存器
Index:处理器将索引值乘以8在加上GDT或者LDT的基地址,就是要加载的段描述符
三种类型的总线位数通常与 CPU 有关控制总线:控制的指令数量 2 ^ N地址总线:表示寻址的范围数据总线:一次传输的位数
B 代码段栈帧
数字逻辑
研究计算机硬件的书
冯诺依曼体系
汇编对 ISA 的抽象C 语言对汇编的抽象Java 对 JVM 的抽象,JVM 对真实计算机的抽象不管上层如何变,底层都是机器码
怎么编写控制编码?
ebpf
2
简单说:有一条纸带,机器头上有一组状态和固定的程序,根据纸带的信息,转换机器状态,来控制是读、写还是跳过操作
查GDT+段寄存器+指令地址寄存器=物理地址
空出一块 ,分配无用值(有时候,想要一个数据,初始化的值为一个无效值 e.g. Object obj = null
ret
rbp
获取段描述符信息
C 语言
输入设备
内容:数字逻辑层面上研究 CPU 、存储器、外设的硬件实现和优化、以及相互关系的详细说明
程序
真实场景和内存空间有限的情况下,指令流不会一直排列下去,而是会被分成一段段的,我们就叫它指令段,也就是对应的代码段。不同的代码段文件通过链接在一起,实现相互跳转执行。汇编语言中通过 call 指令来进行在指令段之间跳转,ret 指令 回到跳转前指令段指令=操作码+操作数;那么指令段中的指令必定是会有自己的数据,而这些数据随着指令的销毁而销毁,而又有些数据是可以在多个指令段之间共享。于是,可以按照功能对内存划分:指令段私有内存(栈),指令段共享内存(堆)指令段是多个的并且存在 call 指令在不同指令段之间跳转执行,所以指令段私有内存不是简单的执行完这个指令段然后释放,去执行下一个。而是,执行当前一部分指令段时,遇到 call 指令跳转到另外一个指令段,并会产生新的私有数据内存这个时候就需要一个数据结构来表示这种存储关系
机器语言
程序执行是由许许多多的指令组成,指令之间是可以相互跳转的,这也符合最开始的图灵机模型的设计,就是根据状态进行读写移动所以为了实现指令的跳转,所以需要维持一个状态机,于是就专门用一个寄存器来保存状态,该寄存器称为状态寄存器上面也说了指令流执行,还会进行指令的跳转,那么就得知道执行到那条指令了,于是就专门用一个寄存器来保存指向指令的地址,,叫指令地址寄存器
我们就直接找 CISC ,选 Intel 公司的
都有哪些寄存器呢?
ISA 指令流
汇编指令6
高地址 H
怎么造语言?
SSA
1KB
阴中有阳,阳中有阴一花一世界,一叶一菩提
实模式
栈内存空间是连续的,所以只需要考虑这种情况即可。为了知道当前指令段对应的栈帧,就是当前执行使用的栈帧,也即是栈顶所以需要一个栈顶寄存器 sp 和一个栈底寄存器 bp 来限定出栈帧大小往小看:当前执行的指令段如何操作私有数据?通过栈顶指针操作加减就可以得到内存地址用来保存数据或获取数据往大看:当前指令段A 跳转到指令段 B 执行,如何开辟新的栈帧?如何销毁栈帧?开辟栈帧,保存上一个栈帧的栈底指针;把栈底指针指向栈顶指针相同位置( bp = sp),通过 sp 减一个数值从而达到栈帧的开辟(栈内存由高地址向低地址方向分配内存)销毁栈帧,也就是指令段 B 执行完成后,需要释放 B 对应的栈帧,由于已经保存上一个指令段 A 的栈帧栈底指针(old_bp);所以我们只需要将栈顶指针指向栈底指针相同位置(sp = bp)而栈底指针指向上一个的栈底指针指向的位置(bp=old_bp)
分析出来的中间产物数据得用一个结构来保存,树这种数据结构
它的功能就是存储N位二进制的东西,底层由触发器组合成的。 CPU 中有很多个寄存器,所以叫寄存器组。
这种访问模式没有限制可以访问到内存的每一个地方,那么会干扰到其他程序比如其他程序控制了 OS 那么就控制整个计算机,所以需要提供保护模式
布尔代数
代码加载到内存
汇编指令流
特权级
现在,RISC 和 CISC 不分了对外 CISC 对内 RISC ,CPU 内部有一个译码单元可以把 CISC (mop) 指令分解成 RISC (uop)
语言的鼻祖
《计算机组成原理》
字节码
CPL
图灵机模型
直接看书
由此可知
硬件的基础
段选择子
算法
段描述的结构
n
核心思想
GraalVM
保护模式中的全局段描述表,可以通过代码来分配程序内存备注:系统启动都是实模式,然后通过代码切换为保护模式
IP
ROM
GDTR
CS与SS中的RPL,就是被称为CPL
0 条评论
回复 删除
下一页