实模式与保护模式

本文对比了实模式和保护模式的主要特点,实模式下,16位处理器使用段地址+偏移地址寻址1MB内存,而保护模式提供32位内部寄存器和4GB最大寻址空间,通过描述符表实现更安全的内存访问,增强了系统安全性。

实模式:

实模式简单来说就是16位模式(也有16位保护模式,但由于地址线的限制,实则都差不多),在16位模式下是使用20根地址线,可以寻址1MB内存,但又由于处理器内部的寄存器只有16位(以前的处理器),因此为了能访问整个1M内存,所以采用段地址+偏移地址的寻址方式(段地址*16+偏移地址)。

主要特点

1.内部寄存器为16位
2.最大寻址空间为1MB
3.可访问内存中的任意位置

保护模式:

保护模式是工作在32位模式下,具有32位的内部寄存器,以及32(or64)根地址线,最大访问空间为4GB内存,可以访问整个4G内存空间,但由于依然是在x86处理器的架构下,为了兼容,而依然采用段式寻址空间。

主要特点

1.内部寄存器有32位
2.最大寻址空间为4GB
3.段寄存器中保存段的选择子(不再是段基地址)

比较:

实模式和保护模式之间差别挺大的,保护模式运算能力、寻址能力都增强,但最大的差别还是保护模式的安全性能大大加强,而实模式下几乎没有安茜可讲,因为随便一个程序都可以自由访问内存中的任意空间,因此加强安全性能的方法莫过于对内存访问模式的改变:

内存访问模式:

本质上还是采用段+偏移的方法,

1.实模式

段寄存器(cs,ss,es,ds…)中存储的就是段基地址,可以没有限制的读写,也就是使用段寄存器时,就是直接用的里面存储的内容

2.描述符表

在来看保护模式之前,先来看一下描述符表:

描述符表就是描述符的集合,描述符存储的是段相关的信息,描述符统一的一个挨着一个的放在内存的一段空间中,这就构成了一个描述符表。

1.全局描述符表(GDT)是为整个软硬件系统服务的,必须在进入保护模式之前定义。

2.局部描述符表(LDT)是用户程序自己使用的,因此每个用户程序都有一个LDT,并且每个LDT在GDT中都有一个对应的描述符。

并且为了跟踪GDT,处理器内部专门有一个寄存器来负责:

1.全局描述符表寄存器(GDTR)

该寄存器称为全局描述表寄存器(GDTR),该寄存器为48位,分别是32位的基地址和16位的边界
gdtr
描述符边界也就是表的大小,最大为64KB,又由于一个描述符占8字节,因此最多可以定义8192个描述符。

2.描述符

描述符
P.S.上面一大堆参数,就简单介绍吧。。。
G=0:段界限以字节为单位;1:段界限以4KB为单位
D/B=0:指令中的偏移地址或者操作数是16位;1:32位
L=64位代码段标志
AVL=
P=0:段不在内存中;1段在内存中
DPL=描述符的特权级(0,1,2,3)
S=0:系统段;1:代码段或者数据段
TYPE=指示描述符的类别,有4位
对于数据段分别为(X,E,W,A)

XEWA描述符类别含义
000x数据只读
001x数据读、写
010x数据只读,向下扩展
011x数据读、写,向下扩展

对于代码段分别为(X,C,R,A)

XCRA描述符类别含义
100x代码只执行
101x代码执行、读
110x代码只执行,依从的代码段
111x代码执行、读,依从的代码段
3.安装段描述符并加载GDTR
         ;创建0#描述符,它是空描述符,这是处理器的要求
         mov dword [bx+0x00],0x00
         mov dword [bx+0x04],0x00  

         ;创建#1描述符,保护模式下的代码段描述符
         mov dword [bx+0x08],0x7c0001ff     
         mov dword [bx+0x0c],0x00409800     

         ;创建#2描述符,保护模式下的数据段描述符(文本模式下的显示缓冲区) 
         mov dword [bx+0x10],0x8000ffff     
         mov dword [bx+0x14],0x0040920b     

         ;创建#3描述符,保护模式下的堆栈段描述符
         mov dword [bx+0x18],0x00007a00
         mov dword [bx+0x1c],0x00409600

         ;初始化描述符表寄存器GDTR
         mov word [cs: gdt_size+0x7c00],31  ;描述符表的界限(总字节数减一)   

         lgdt [cs: gdt_size+0x7c00];把从标号gdt_size开始的6字节加载到GDTR寄存器

局部描述符的安装类似,也是选取一块内存用于LDT存储局部描述符,然后使用lldt指令,加载到局部描述符表(LDT不需要空描述符)

        ;创建描述符
         mov dword [...],0x...
         mov dword [...],0x...

         ...

         ;初始化描述符表寄存器LDTR
         mov word [...],...    

         lldt [...]

3.保护模式

段寄存器(cs,ss,es,ds,gs,fs)不再存储段基地址,而是段的选择子,而且段寄存器还包括一个不可见的部分,描述符高速缓冲器

保护模式下访问模式:

1.每当引用一个段时,可理解为改变段地址内容的指令,如

jmp ...
;or
call ...
mov ax,...
mov ds,ax

调用该类指令时,会将段地址左移4位,并传送到描述符高速缓冲器,并且之后如没有改变段地址(调用上面一类的指令),访问该段寄存器时,便一直使用改地址。

2.要访问内存时,传送给段选择器(段寄存器)的内容不再是逻辑段地址(就是实模式中的直接可用的地址),而是段描述符在描述符表中的索引号
段选择子
传送给段选择器的段选择子如上图所示
由<描述符索引号(3~15)+TI(2)+RPL(0~3)>3部分组成:
1.描述符索引号:用于在描述符表中选择一个段描述符
2.TI:0:描述符在GDT(全局描述符表)中,1:描述符在LDT(局部描述符表)中
3.RPL:请求特权级

这里以2.描述表中创建的描述表为例,里面有4个描述符:

描述符名称索引号
空描述符0
代码段描述符1
数据段描述符2
堆栈段描述符3

举个选择堆栈段的例子:

;以下用简单的示例来帮助阐述32位保护模式下的堆栈操作 
mov cx,00000000000_11_000B         ;加载堆栈段选择子
mov ss,cx

上面的索引号就是0000000000011,也就是3
TI:0
RPL:0

3.最后在实际访问中,根据段描述符以及段选择子的信息,来决定这次访问是否合法,特别是特权级是否合法的问题。

P.S.关于保护模式下的内存访问,看完上面内容后,可配合保护模式下的内存访问一起看

总结

实模式和保护模式有很多不同,但是对于写代码来说,其实最大的影响就是32位下面的内存访问模式:

实模式:

随意访问,但是最大只能访问1MB内存

保护模式:

可以访问全部的4GB内存,但是受到限制,程序不能随意访问自身空间外的内存,因此保护模式比实模式安全。

#

最后上面的代码、图片引用自《x86汇编语言 从实模式到保护模式》里面的(还没写32位下的代码。。。借用一下)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值