X86架构(八)——32位处理器架构
寄存器扩展
相较于16位处理器,32位处理器对通用寄存器做了如下图所示扩展
在32位模式下,为了生成32位物理地址,处理器需要使用32位的指令指针寄存器(IP——>EIP)
在16位处理器中,标志寄存器FLAGS是16位的,在32位处理器中,扩展到了32位,低16位和原先保持一致
IA-32架构的处理器是基于分段模型的,因此,32 位处理器依然需要以段为单位访问内存。不过,段的基地址是0x00000000,段的长度是4GB。在这种情况下,可以视为不分段,即平坦模型(Flat Mode)
平坦模型
整个内存空间视为一个连续的地址空间,没有分段等复杂的内存布局结构
段选择器
在32位模式下,为了防止对内存的违规访问,传统的段寄存器(CS、SS、DS、ES)不在保存16位段地址,而是段的选择子,用于选择要访问的段
段选择器用于在保护模式下选择不同的内存段。它指向全局描述符表(GDT)或局部描述符表(LDT)中的一个段描述符,从而确定内存段的基地址、长度和访问权限等信息
描述符高速缓存器
描述符高速缓存器用于存储最近使用的段描述符信息。当处理器执行涉及内存访问的指令时,它首先会检查描述符高速缓存器中是否有对应的段描述符。如果有,就可以直接使用高速缓存中的信息,而无需再次从全局描述符表(GDT)或局部描述符表(LDT)中读取,从而提高内存访问的速度
基本工作模式
- 实模式(Real-address Mode):
- 特点:这是为了兼容早期的8086处理器而存在的模式,是X86架构CPU启动后的初始模式。在该模式下,CPU访问内存的地址都是真实的物理地址。一共只有20位地址线,可访问的内存空间为1MB,以及拥有8个16位的通用寄存器和4个16位的段寄存器。该模式下不能对内存进行分布管理,程序可以较为自由地访问内存,但也容易出现程序之间相互干扰的问题
- 寻址方式:物理地址 = 段地址(段寄存器的值左移4位)+ 偏移地址
- 保护模式(Protected Mode):
- 特点:这是现代操作系统主要使用的模式,提供了对内存及一些外围设备的硬件级保护。处理器可以寻址4GB的地址空间,支持多任务、内存分页管理和优先级保护等机制。该模式引入了虚拟地址的概念,应用程序只能使用逻辑地址,逻辑地址的转换由内存管理单元(MMU)来完成,使应用程序无法直接访问真实地址,从而保护了系统数据的安全
- 寻址方式:段寄存器中保存的是段选择子,而不是直接的段基地址。根据段选择子从全局描述符表(GDT)或局部描述符表(LDT)中获取段描述符,从而确定段基地址,再加上段内偏移量得到线性地址。如果开启了分页机制,线性地址会经过页部件转换后形成物理地址
- 虚拟8086模式(Virtual-8086 Mode):
-
特点:是保护模式下的一种准操作模式。在多任务环境下,每个任务都可以执行实地址下的“8086指令”,即可以运行那些为8086处理器编写的程序。这样既能够保持对旧程序的兼容性,又能在多任务的环境下运行
-
工作方式:每个虚拟8086任务都有自己的寄存器状态、堆栈和程序计数器等,操作系统会在保护模式下管理和切换这些虚拟8086任务,确保它们之间的独立性和安全性
线性地址
逻辑地址
逻辑地址是由程序生成的,与段相关的偏移地址部分
传统上,逻辑地址由段地址和偏移地址组成
偏移地址又叫做有效地址
物理地址
物理地址是内存中实际存储单元的地址
线性地址
线性地址是在保护模式下,由逻辑地址经过段机制转换后得到的地址。如果没有开启分页机制,线性地址就直接对应物理地址;如果开启了分页机制,线性地址会经过页部件转换后才形成物理地址
分页机制
为了解决任务频繁创建与释放产生的内存碎片的问题,IA-32 处理器新支持分页功能,分页功能将物理内存空间划分成逻辑上的页。页的大小是固定的,一般为4KB,通过使用页,可以简化内存管理
当页功能开启时,段部件产生的地址就不再是物理地址了,而是线性地址(Linear Address),线性地址还要经页部件转换后,才是物理地址
线性地址的概念用来描述任务的地址空间。IA-32 处理器上的每个任务都拥有4GB的虚拟内存空间,这是一段平坦线性地址空间
处理器特点
流水线
为了提高处理器的执行效率和速度,可以把一条指令的执行过程分解成取指令、译码、执行、访存和写回等步骤,并分配给相应的单元来完成。各个单元的执行是独立的、并行的。如此一来,各个步骤的执行在时间上就会重叠起来,这种执行指令的方法就是流水线(Pipe-Line)技术。
高速缓存
- Cache 主要用于缓解 CPU 与主存之间速度不匹配的矛盾。CPU 的速度远快于主存,当 CPU 需要访问数据时,如果每次都从主存中读取,会极大地降低系统性能。Cache 存储了 CPU 近期可能会用到的数据和指令,当 CPU 需要访问这些内容时,可以直接从速度更快的 Cache 中获取,大大提高了数据访问速度
- 当 CPU 发出内存访问请求时,首先会检查 Cache 中是否有所需的数据。如果有,称为命中(hit),CPU 可以直接从 Cache 中读取数据,速度非常快。如果没有命中(miss),则需要从主存中读取数据,并将该数据存储到 Cache 中,以便下次访问时能够更快地获取
- 高速缓存的装载是以块为单位的,包括那个所需数据的邻近内容。为此,需要额外的时间来等待块从内存载入高速缓存,在该过程中所损失的时间称为不中惩罚(miss penalty)
乱序执行
为了实现流水线技术,需要将指令拆分成更小的可独立执行部分,即拆分成微操作(microoperations),简写为μops
add eax, ebx ;一个微操作
add eax, [mem] ;两个未操作:一个用于从内存中读取数据并保存到临时寄存器,另一个用于将EAX 寄存器和临时寄存器中的数值相加
一旦将指令拆分成微操作,处理器就可以在必要的时候乱序执行(Out-Of-Order Execution)程序
乱序执行是指处理器在执行指令时,不按照程序中指令的顺序依次执行,而是根据指令的依赖关系和处理器的资源情况,动态地调整指令的执行顺序。这样可以充分利用处理器的各个执行单元,避免因等待前面指令的结果而导致的性能损失。
例如:
mov eax, [mem]
shl eax, 5
add eax, [mem2]
mov [mem2], eax
指令 add eax, [mem2]
可以拆分为两个微操作。如此一来,在执行逻辑左移指令的同时,处理器可以提前从内存中读取mem2 的内容
寄存器重命名
寄存器重命名的基本思想是将程序中使用的逻辑寄存器(由程序员可见的寄存器名称表示)映射到处理器内部的物理寄存器上。这样,当不同的指令需要使用相同的逻辑寄存器时,处理器可以为它们分配不同的物理寄存器,从而避免了由于数据依赖关系而导致的指令停顿。
mov eax, [mem1]
shl eax, 3
mov [mem2], eax
mov eax, [mem3]
add eax, 2
以上代码片断做了两件事,但互不相干:将mem1 里的内容左移3 次,并将mem3里的内容加2。如果我们为最后三条指令使用不同的寄存器,那么将更明显地看出这两件事的无关性。并且,事实上,处理器实际上也是这样做的,从而使其可以并行处理
分支目标预测
在程序执行过程中,分支指令(如条件跳转、循环等)会根据特定的条件决定程序的执行流向。分支目标预测的目的就是在分支指令执行之前,尽可能准确地预测分支的执行方向和目标地址,以便处理器提前取指并执行可能的目标指令,避免因等待分支结果而导致的流水线停顿
其原理通常是基于历史信息进行预测。处理器会记录过去执行的分支指令的结果和行为,当遇到新的分支指令时,根据历史信息来推测该分支指令的执行方向和目标地址
在处理器内部,有一个小容量分支目标缓存器(Branch Target Buffer,BTB)。当处理器执行了一条分支语句后,它会在BTB 中记录当前指令的地址、分支目标的地址,以及本次分支预测的结果。下一次,在那条转移指令实际执行前,处理器会查找BTB中的转移记录。如果能找到对应的条目,则推测执行和上一次相同的分支,把该分支的指令送入流水线
当该指令实际执行时,如果预测是失败的,那么,清空流水线,同时刷新BTB 中的记录。这个代价较大
… 还要补充哦 存档 存档 兄弟们