实模式

访问内存
实模式也就是说寄存器中存放的地址都是真实地址,比如下面这段程序:

data SEGMENT ;定义一个数据段存放Hello World!
    hello  DB 'Hello World!$' ;注意要以$结束
data ENDS
code SEGMENT ;定义一个代码段存放程序指令
    ASSUME CS:CODE,DS:DATA ;告诉汇编程序,DS指向数据段,CS指向代码段
start:
    MOV AX,data  ;将data段首地址赋值给AX                
    MOV DS,AX    ;将AX赋值给DS,使DS指向data段
    LEA DX,hello ;使DX指向hello首地址
    MOV AH,09h   ;给AH设置参数09H,AH是AX高8位,AL是AX低8位,其它类似
    INT 21h      ;执行DOS中断输出DS指向的DX指向的字符串hello
    MOV AX,4C00h ;给AX设置参数4C00h
    INT 21h      ;调用4C00h号功能,结束程序
code ENDS
END start

寄存器CS、DS中都是存放的真实的指令、数据段地址。在计算hello的内存物理地址时,直接将DX左移4位并与DX相加即可(DX为16位,也就是说段的最大偏移为64KB,最多16段)。在实模式下,我们可以读写任意内存地址,在单任务操作系统(比如DOS)中这样做是没问题的,但在多任务操作系统是很危险的。

实模式下的中断

在这里插入图片描述
从上面这张图可以看出,实模式下IDTR寄存器保存了中断向量表的起始地址长度,中断向量表中保存了代码段的基址(装入CS)和段内偏移(装入IP)。有了中断号,很容易就能完成上下文切换。

保护模式

为什么要有保护模式

其一:8086处理器只有20位地址总线,对应1MB的内存空间地址,寻址通过两个寄存器实现。而80386有32位地址总线,对应4GB内存空间,此时再用16位寄存器的话,最大段长64KB的限制显得十分突兀,因此保护模式增加了一些32位的寄存器,如下图:
在这里插入图片描述
其二:实模式适用于单任务操作系统。对于多任务操作系统,CPU对内存的访问应该受到限制。而保护模式实现了对指令访问权限资源访问权限的控制。

特权级
保护模式中,CPU实现了特权级,分0-3共4个等级,R0可以访问所有指令或者资源,其他的只能访问相应的子集:
在这里插入图片描述
段描述符

段描述符用来记录段的地址、大小信息以及控制权限,结构如下:
在这里插入图片描述
段描述符有64位,保存在GDT表中,其中的DPL字段用来控制内存访问权限。
保护模式下访问内存时,首先通过GDTR寄存器获取GDT表的起始地址和大小,然后再与段寄存器中存放的地址相加得到段描述符的地址:
在这里插入图片描述
在这里,段寄存器保存的是段选择子,段选择子结构如下:
在这里插入图片描述
这个影子寄存器是靠硬件实现的,在ARM架构中才有,x86是没有的。RPL(Request Priviliege Level 请求指令权限),通常情况下CPL(Current Privilege Level 当前指令权限)等于RPL。在访问内存时,只有CPL<=DPL时才能访问。

这里有个小问题:GDT表大小为64K,也就对应16位地址。但是由于段描述符位64位,所以实际上每个段描述符起始地址的低3位都是0,所以在段选择子中,我们用这低3位来记录TI和RPL。

保护模式下的中断

在实模式下,中断向量表中直接存放了段基址和偏移。在保护模式中,为了实现中断权限检查、特权级的转换,在中断向量表中存放中断门描述符,结构如下:
在这里插入图片描述
当CPL<=DPL,表示可以进行中断,这是第一步。然后,将CPL与目标段(段选择子指向的段描述符)的DPL对比,如果CPL=DPL,将CPL变为DPL;如果CPL>DPL 除了修改CPL外,还需要进行栈切换。 在做完这些之后,CPU把段选择子加载到CS寄存器,段偏移加载到EIP寄存器中。

保护模式下分页—平坦模式

分段模式缺点很多,但是x86架构并不能直接使用分页模型,平坦模式能够使分段模式形同虚设。

平坦模式是这样实现的:从之前段描述符结构那张图中可以看到,段描述符中有一个标识位G,G为0时表示使用分段模式,G为1时表示段的长度粒度为4KB(相当于页面大小为4KB)。也就是说如果G=1,段基址(base)为1,段限长(limit)为1,那么段的实际地址为0x1000 ~ 0x1FFF。

如果我们把所有的段基址都设置为0,段限长设置为0xFFFFF,那么每个段都指向4G的内存空间,分段模式也就形同虚设了。

与实模式最大段长64KB相比,在保护模式下,段描述符中段基址为32位,段限长为20位,也就说是如果G=0的话,段长最大为1MB。

长模式

长模式和保护模式非常相似,只是有了64位处理能力,其他差别不大。长模式下的寄存器:
在这里插入图片描述

总结

实模式、保护模式、长模式对应了处理器从 16位单任务->32位多任务->64位 的发展历史。另外x86CPU在第一次加电时会自动进入实模式,我们需要通过设置CR0寄存器,并且初始化GDT、GDTR等来切换到保护模式或者长模式。

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐