直接访问:
适用于简单的计算机系统,如早期的微处理器(例如8位和16位微处理器),通常在实模式下使用。
段基址+段偏移地址:段寄存器 段的起始地址 多任务
主要用于8086及其后续的x86架构的实模式。该模式通过段基址和段内偏移地址来访问内存,适合1MB的地址空间。

IP寄存器(Instruction Pointer,指令指针寄存器)是计算机中央处理器(CPU)中的一个重要寄存器,用于指示当前正在执行的指令的地址。在x86架构中,IP寄存器与代码段寄存器(CS)一起工作,形成一个组合地址(CS:IP),指向内存中存储的指令。
在现代计算机中,虽然IP寄存器的概念仍然存在,但其实现可能有所不同。例如,在64位架构中,IP寄存器通常被称为RIP(Register Instruction Pointer),并且可以处理更大的地址空间。
总的来说,IP寄存器在计算机体系结构中仍然是一个基本概念,尽管具体的实现和名称可能会有所变化。

偏移量的来源:
指令编码:在汇编语言中,每条指令通常会包含一个偏移量,这个偏移量是相对于段基址的。CPU在执行指令时,会将这个偏移量与CS寄存器中的段基址相加,从而计算出实际的物理地址。
指令格式:不同的指令有不同的格式,某些指令可能直接在指令中包含偏移量,而其他指令可能需要通过寄存器或内存中的值来获取偏移量。
程序计数器(IP寄存器):在执行过程中,CPU会维护一个指令指针(IP寄存器),它指向当前执行的指令的偏移量。每当执行一条指令后,IP会自动更新,以指向下一条指令。
任务切换
任务切换:在多任务环境中,操作系统通过保存和恢复段寄存器的值来实现任务切换。当一个任务被挂起时,操作系统会保存当前任务的段寄存器和其他寄存器的状态;当恢复任务时,再将之前保存的状态加载回去。
系统缓存策略
在8086系统中,采用段基址+段偏移地址的方式进行寻址。当执行多任务时,每次任务切换会涉及到CPU缓存策略的几个方面:
- 上下文切换:在任务切换时,CPU需要保存当前任务的上下文(包括寄存器状态、程序计数器等),并加载新任务的上下文。这一过程会影响CPU缓存的内容,因为不同任务可能会使用不同的数据和指令。
- 缓存失效:由于不同任务可能会访问不同的内存区域,任务切换后,原有的缓存数据可能不再有效。因此,CPU可能会在任务切换时清空或标记缓存,以避免使用过时的数据。
- 缓存一致性:在多任务环境中,确保缓存一致性是一个重要问题。CPU可能会采用一些策略来维护缓存的一致性,例如使用写回策略或写直达策略,以确保数据在多个任务之间的一致性。
- 预取策略:在任务切换后,CPU可能会根据新任务的访问模式进行预取,以提高数据访问的效率。这意味着CPU会尝试预测新任务将要访问的数据,并提前将其加载到缓存中。
段选择子+段偏移地址: 段表
适用于x86架构的保护模式。保护模式引入了段选择子,允许更复杂的内存管理和保护机制。
【段选择子+段偏移地址】与【段基址+段偏移地址】有些相似之处,之所以采用【段选择子+段偏移地址】主要是为了安全,原来的【段基址+段偏移地址】方式,程序员可以直接跳转到其他代码段和数据段,没有任何限制,安全性全依赖于程序员的职业操守和水平,因此CPU设计者就发明了【段选择子+段偏移地址】。
计算机中的段表(Segment Table)是用于管理内存分段的一种数据结构。它在分段存储管理中起着关键作用,主要用于记录各个段的起始地址和长度等信息。每个程序在运行时被划分为多个段,例如代码段、数据段和堆栈段等。
段表的主要功能包括:
地址转换:在程序访问内存时,段表帮助将逻辑地址转换为物理地址。逻辑地址由段号和段内偏移量组成,段表提供了段的基地址,结合偏移量可以计算出实际的物理地址。
内存保护:段表可以记录每个段的访问权限(如只读、可读可写等),从而保护内存不被非法访问。
动态分配:段表支持动态内存分配,允许程序在运行时根据需要申请和释放内存段。
在计算机系统中,使用段选择子(Segment Selector)和段偏移地址(Offset)进行寻址时,段的起始地址确实存储在段表中。段表包含每个段的描述符,其中包括段的基地址、界限和其他属性。
每个段通常还有一个对应的段寄存器(如在x86架构中有CS、DS、SS等),这些寄存器用于存储段选择子。段选择子指向段表中的一个条目,从而获取该段的基地址。段基地址并不是存储在段寄存器中,而是通过段选择子访问段表后得到的。
因此,段的起始地址在段表中,而段寄存器则用于存储段选择子,以便于访问段表获取段基地址。
全局段描述符表有很多个段描述符,每个段描述占用8个字节,这个段描述符里面就包括了段基址,另外还有一些安全性相关的描述信息例如段的可读,可写,可执行,段的大小等。

虚拟地址:
适用于现代操作系统(如Windows、Linux等)中的虚拟内存管理。虚拟地址允许程序使用比物理内存更大的地址空间,并通过页表实现地址转换。
现代的操作系统和CPU未打开分页时采用的是【段选择子+段偏移地址】访问代码和数据,而一旦打开分页时,经过【段选择子+段偏移地址】得到的地址不再是物理地址了,而是叫做虚拟地址,默认则是打开分页的。
现代的操作系统和CPU采用的平坦模型,平坦模型就是整个内存就一个段,因此段基址就是0,段偏移地址就等于虚拟地址了。
- 什么是虚拟地址,物理地址,虚拟地址空间,物理地址空间,虚拟内存,物理内存?
- 虚拟地址
对于程序来说的地址 - 物理地址
内存中的地址 - 虚拟地址空间
虚拟地址的集合 - 物理地址空间
物理地址的集合 - 虚拟内存
存储在磁盘上的 - 物理内存
存储在内存中的
- 虚拟地址
虚拟地址空间的3种状态
a.未分配,这个虚拟地址仅仅是个数字而已,没有任何指向。
b.未缓冲,这个虚拟地址指向了磁盘的某个字节存储单元,里面存储了指令或者数据。
c.已缓冲,这个虚拟地址指向了物理内存的某个字节存储单元,里面存储了指令或者数据。
- 什么是进程虚拟地址空间?

共享库的内存映射区域:这个区域是一些标准的系统库,这个共享库在物理内存中只存储一份,每个进程将这个区域的虚拟地址映射到同一份共享库物理内存上。
内核区域:这个区域是操作系统自己代码,数据,栈空间,内核在物理内存中只存储一份,每个进程将这个区域的虚拟地址映射到同一份内核物理内存上。

- 什么是虚拟页,物理页?
- 虚拟页
以虚拟内存划分的页 - 物理页
内存中的页
- 虚拟页
每个虚拟页可以有三种状态,未分配,已缓冲,未缓冲
未分配:虚拟页还没有分配磁盘空间
未缓冲:虚拟页分配了磁盘空间,但没有在物理页上缓冲。
已缓冲:虚拟页缓冲或者映射在了物理页上。

页表是建立虚拟页号和物理页号映射关系的表结构,每个页表项(PTE)包括了有效位,物理页号,磁盘地址等信息,如下图:
当页表项 PTE n的页表项有效位为0时,表示虚拟页 n没有缓冲在物理内存,可能在磁盘或者未分配,例如PTE 0页表项里存储的是null,表明虚拟页0即VP0是未分配状态,PTE 3里存储的是磁盘地址,表明虚拟页 3即VP3在磁盘里,但没有缓冲,VP3状态为未缓冲。
页表基址寄存器(PTBR):
每个进程都有自己的页表,CPU执行某个进程时,会先把该进程的一级页表起始地址存储到页表基址寄存器,这样CPU查找一级页表起始地址可以直接从寄存器查找,加快了查找效率。
处理器根据虚拟地址访问物理内存的分为页表项命中和页表项未命中两种情况,页表项命中意味着页表项的有效位为1,页表项存储的是物理页号,虚拟页缓冲在物理页中,未命中意味着页表项有效位为0,此时需要发送缺页中断。
页表项命中的步骤如下图:
1.CPU将虚拟地址(VA)送入MMU,MMU根据页表基址寄存器中页表的起始地址加上虚拟页号,找到了页表项的物理地址PTEA。
2.MMU将PTEA送入到高速缓冲或者内存。
3.从高速缓冲或者内存中找到页表项(PTE),返回页表项(PTE)给MMU。
4.MMU根据PTE找出物理页号,然后加上虚拟页偏移量形成物理地址(PA),送入到高速缓冲或者内存。
5.高速缓冲或者内存获取数据,返回数据给处理器。
页表项未命中的步骤如下图:
1.CPU将虚拟地址(VA)送入MMU,MMU根据页表基址寄存器中页表的起始地址加上虚拟页号,找到了页表项的物理地址PTEA。
2.MMU将PTEA送入到高速缓冲或者内存。
3.从高速缓冲或者内存中找到页表项(PTE),返回页表项(PTE)给MMU。
4.MMU根据PTE,发现页不在内存中,未命中,因此MMU发送一个缺页中断,交由缺页异常处理程序处理。
5.缺页异常处理程序根据页置换算法,选择出一个牺牲页,如果这个页面已经被修改了,则写出到磁盘上,最后将这个牺牲页的页表项有效位设置为0,存入磁盘地址。
6.缺页异常程序处理程序调入新的页面,如果该虚拟页尚未分配磁盘空间,则分配磁盘空间,然后磁盘空间的页数据拷贝到空闲的物理页上,并更新PTE的有效位为1,更新物理页号,缺页异常处理程序返回后,再回到发生缺页中断的指令处,重新按照页表项命中的步骤执行。