提炼:
1 对于数据段 ,处理器进行特权级检查的时机 就是为段寄存器赋值的那一个时刻

在保护模式下 当处理器对段寄存器进行赋值的时候,处理器就会使用规则进行特权级的检查。如:
mov ax, Data32Selector
mov ds, ax

2 数据段的特权级保护规则就是
CPL <= DPL && RPL <= DPL,即代码段特权级 与 数据段选择子请求特权级RPL 都要高于或等于 DPL特权级

3 对于栈段,当为SS寄存器赋值的时候,使用规则 :
(CPL == RPL) && (CPL == DPL) 保证特权级的匹配

回顾:特权级的表现形式
CPL : 当前可执行代码段的特权级,由CS寄存器最低2位定义
DPL : 内存段的特权级,在段描述符表中定义
RPL : 选择子的特权级,由选择子的最低两位定义

回顾 CPL与DPL 的关系
代码段DPL
在保护模式中,每一个代码段都定义了一个DPL,当处理器从A代码段 成功跳转到B代码段执行。
跳转前:CPL = DPL(A)
跳转后:CPL = DPL(B)

即:
当代码段A执行的时候,当前的特权级CPL就是我们所定义的A代码段的特权级DPL,当成功跳转到B代码段的时候,当前的特权级CPL就变换成B代码段的特权级DPL

数据段DPL
在保护模式中,每一个数据段都定义了一个DPL,当处理器执行过程中需要访问数据时:
CPL <= DPL(数据段)

可执行代码访问数据段时,当前可执行代码段的特权级CPL 要高于等于 要访问的内存段的特权级DPL,否则权限不够



CPL: 代码段执行特权级
RPL: 选择子请求特权级
DPL: 目标内存段特权级

场景:

当前代码段的执行权限是CPL,他想访问某个数据段中的数据,那么他需要使用该数据段的选择子访问该数据段,这时候选择子也有一个请求特权级RPL,而目标数据段本身也是有一个DPL内存段特权级

如 :
当前代码段执行特权级CPL=2
目标数据段 选择子请求特权级RPL=1
目标数据段 内存段特权级DPL=3

那么当前代码段是能够访问该数据段的,因为它本身的执行权限大于数据段内存特权级,并且使用选择子请求访问数据段时,请求特权级也是高于数据段内存段特权级的。

可以将 代码段执行特权级 理解为某个人,将选择子请求特权级 理解为 访问内存段的大门密码,将内存段特权级理解为门后面的物品。

实验1

当: CPL = 2, RPL = 1, DPL = 3, 访问是否合法? ===> yes
32位代码段 代码段执行特权级CPL = 2,
32数据段 目标内存段特权级 = 3
32数据段 选择子请求特权级 = 1

;代码段 内存段特权级是2
CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_C + DA_32 + DA_DPL2

;数据段 内存段特权级是3
DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_DR + DA_32 + DA_DPL3

;代码段 选择子请求特权级是2
Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL2
;数据段 选择子请求特权级是1
Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL1

很明显 代码段的执行特权级 与 数据内存段的选择子请求特权级 权限都高于 数据段目标内存段特权级。所以可以访问
注意: 当前32位代码段特权级是2,而16位是模式代码段执行特权级是0,高于32位保护模式代码段执行特权级,所以跳转到32位代码段需要 降特权级!!! retf指令

%include "inc.asm"org 0x9000jmp ENTRY_SEGMENT[section .gdt]
; GDT definition
;                                 段基址,       段界限,       段属性
GDT_ENTRY       :     Descriptor    0,            0,           0
;代码段 内存段特权级是2
CODE32_DESC     :     Descriptor    0,    Code32SegLen - 1,    DA_C + DA_32 + DA_DPL2
;显存段 内存段特权级是3
VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32 + DA_DPL3
;数据段 内存段特权级是2
DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32 + DA_DPL3
;栈段   内存段特权级是2
STACK32_DESC    :     Descriptor    0,     TopOfStack32,       DA_DRW + DA_32 + DA_DPL2
; GDT endGdtLen    equ   $ - GDT_ENTRYGdtPtr:dw   GdtLen - 1dd   0; GDT Selector
;代码段 选择子请求特权级是0
Code32Selector     equ (0x0001 << 3) + SA_TIG + SA_RPL2
;显存段 选择子请求特权级是3
VideoSelector      equ (0x0002 << 3) + SA_TIG + SA_RPL3
;数据段 选择子请求特权级是1
Data32Selector     equ (0x0003 << 3) + SA_TIG + SA_RPL1
;栈  段 选择子请求特权级是0
Stack32Selector    equ (0x0004 << 3) + SA_TIG + SA_RPL2; end of [section .gdt]TopOfStack16    equ 0x7c00[section .s16]
[bits 16]
ENTRY_SEGMENT:mov ax, csmov ds, axmov es, axmov ss, axmov sp, TopOfStack16; initialize GDT for 32 bits code segmentmov esi, CODE32_SEGMENTmov edi, CODE32_DESCcall InitDescItemmov esi, DATA32_SEGMENTmov edi, DATA32_DESCcall InitDescItemmov esi, STACK32_SEGMENTmov edi, STACK32_DESCcall InitDescItem; initialize GDT pointer structmov eax, 0mov ax, dsshl eax, 4add eax, GDT_ENTRYmov dword [GdtPtr + 2], eax; 1. load GDTlgdt [GdtPtr]; 2. close interruptcli ; 3. open A20in al, 0x92or al, 00000010bout 0x92, al; 4. enter protect modemov eax, cr0or eax, 0x01mov cr0, eax; 5. jump to 32 bits code;降特权级跳转 由高到低push Stack32Selector   ; 目标栈段选择子push TopOfStack32      ; 栈顶指针位置push Code32Selector    ; 目标代码段选择子push 0                 ; 目标代码段偏移retf;jmp word Code32Selector : 0; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:push eaxmov eax, 0mov ax, csshl eax, 4add eax, esimov word [edi + 2], axshr eax, 16mov byte [edi + 4], almov byte [edi + 7], ahpop eaxret[section .dat]
[bits 32]
DATA32_SEGMENT:DTOS               db  "D.T.OS!", 0DTOS_OFFSET        equ DTOS - $$Data32SegLen equ $ - DATA32_SEGMENT[section .s32]
[bits 32]
CODE32_SEGMENT:mov ax, VideoSelectormov gs, axmov ax, Data32Selectormov ds, axmov ax, Stack32Selectormov ss, axmov eax, TopOfStack32mov esp, eaxmov ebp, DTOS_OFFSETmov bx, 0x0Cmov dh, 12mov dl, 33call PrintString ;打印jmp $; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:push ebppush eaxpush edipush cxpush dxprint:mov cl, [ds:ebp]cmp cl, 0je endmov eax, 80mul dhadd al, dlshl eax, 1mov edi, eaxmov ah, blmov al, clmov [gs:edi], axinc ebpinc dljmp printend:pop dxpop cxpop edipop eaxpop ebpretCode32SegLen    equ    $ - CODE32_SEGMENT;显存段
[section .gs]
[bits 32]
STACK32_SEGMENT:times 1024 * 4 db 0Stack32SegLen equ $ - STACK32_SEGMENT
TopOfStack32  equ Stack32SegLen - 1


实验2
CPL = 0, RPL = 3, DPL = 2, 访问是否合法? ===> no

注意1 此时
32位代码段 代码段执行特权级CPL = 0
32数据段 目标内存段特权级 = 2
32数据段 选择子请求特权级 = 3

很明显 选择子请求特权级 低于 目标内存段特权级。不符合数据段的反问规则,无权访问

注意2:当前32位代码段特权级是0,16位是模式代码段执行特权级也是0,所以此时跳转 不涉及特权级转移,直接使用选择子跳转

;代码段 内存段特权级是0
CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_C + DA_32 + DA_DPL0

;数据段 内存段特权级是2
DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_DR + DA_32 + DA_DPL2

;代码段 选择子请求特权级是0
Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
;数据段 选择子请求特权级是1
Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL3


%include "inc.asm"org 0x9000jmp ENTRY_SEGMENT[section .gdt]
; GDT definition
;                                 段基址,       段界限,       段属性
GDT_ENTRY       :     Descriptor    0,            0,           0
;代码段 内存段特权级是2
CODE32_DESC     :     Descriptor    0,    Code32SegLen - 1,    DA_C + DA_32 + DA_DPL0
;显存段 内存段特权级是3
VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32 + DA_DPL3
;数据段 内存段特权级是2
DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32 + DA_DPL2
;栈段   内存段特权级是2
STACK32_DESC    :     Descriptor    0,     TopOfStack32,       DA_DRW + DA_32 + DA_DPL2
; GDT endGdtLen    equ   $ - GDT_ENTRYGdtPtr:dw   GdtLen - 1dd   0; GDT Selector
;代码段 选择子请求特权级是0
Code32Selector     equ (0x0001 << 3) + SA_TIG + SA_RPL0
;显存段 选择子请求特权级是3
VideoSelector      equ (0x0002 << 3) + SA_TIG + SA_RPL3
;数据段 选择子请求特权级是1
Data32Selector     equ (0x0003 << 3) + SA_TIG + SA_RPL3
;栈  段 选择子请求特权级是0
Stack32Selector    equ (0x0004 << 3) + SA_TIG + SA_RPL2; end of [section .gdt]TopOfStack16    equ 0x7c00[section .s16]
[bits 16]
ENTRY_SEGMENT:mov ax, csmov ds, axmov es, axmov ss, axmov sp, TopOfStack16; initialize GDT for 32 bits code segmentmov esi, CODE32_SEGMENTmov edi, CODE32_DESCcall InitDescItemmov esi, DATA32_SEGMENTmov edi, DATA32_DESCcall InitDescItemmov esi, STACK32_SEGMENTmov edi, STACK32_DESCcall InitDescItem; initialize GDT pointer structmov eax, 0mov ax, dsshl eax, 4add eax, GDT_ENTRYmov dword [GdtPtr + 2], eax; 1. load GDTlgdt [GdtPtr]; 2. close interruptcli ; 3. open A20in al, 0x92or al, 00000010bout 0x92, al; 4. enter protect modemov eax, cr0or eax, 0x01mov cr0, eax; 5. jump to 32 bits code;降特权级跳转 由高到低; push Stack32Selector   ; 目标栈段选择子;push TopOfStack32      ; 栈顶指针位置; push Code32Selector    ; 目标代码段选择子; push 0                 ; 目标代码段偏移; retfjmp word Code32Selector : 0; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:push eaxmov eax, 0mov ax, csshl eax, 4add eax, esimov word [edi + 2], axshr eax, 16mov byte [edi + 4], almov byte [edi + 7], ahpop eaxret[section .dat]
[bits 32]
DATA32_SEGMENT:DTOS               db  "balabala zhang bao bao!", 0DTOS_OFFSET        equ DTOS - $$Data32SegLen equ $ - DATA32_SEGMENT[section .s32]
[bits 32]
CODE32_SEGMENT:mov ax, VideoSelectormov gs, axmov ax, Data32Selectormov ds, axmov ax, Stack32Selectormov ss, axmov eax, TopOfStack32mov esp, eaxmov ebp, DTOS_OFFSETmov bx, 0x0Cmov dh, 12mov dl, 33call PrintString ;打印jmp $; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:push ebppush eaxpush edipush cxpush dxprint:mov cl, [ds:ebp]cmp cl, 0je endmov eax, 80mul dhadd al, dlshl eax, 1mov edi, eaxmov ah, blmov al, clmov [gs:edi], axinc ebpinc dljmp printend:pop dxpop cxpop edipop eaxpop ebpretCode32SegLen    equ    $ - CODE32_SEGMENT;显存段
[section .gs]
[bits 32]
STACK32_SEGMENT:times 1024 * 4 db 0Stack32SegLen equ $ - STACK32_SEGMENT
TopOfStack32  equ Stack32SegLen - 1


在加载DS寄存器的值时, RPL的值 和 CPL的值 都应该小于等于DPL。处理在执行 mov dx, ax 语句时,发现了RPL的值 和 CPL的值 不合法。从这里我们就可以看出,处理器在进行特权级检查的时机 就是为段寄存器赋值的那一个时刻。

在保护模式下 当处理器对段寄存器进行赋值的时候,处理器就会使用规则进行特权级的检查。如:
mov ax, Data32Selector
mov ds, ax


实验3
; CPL = 0, RPL = 1, DPL = 2, 访问是否合法? ===> yes

;代码段 内存段特权级是0
CODE32_DESC : Descriptor 0, Code32SegLen - 1, DA_C + DA_32 + DA_DPL0

;数据段 内存段特权级是2
DATA32_DESC : Descriptor 0, Data32SegLen - 1, DA_DR + DA_32 + DA_DPL2

;代码段 选择子请求特权级是0
Code32Selector equ (0x0001 << 3) + SA_TIG + SA_RPL0
;数据段 选择子请求特权级是1
Data32Selector equ (0x0003 << 3) + SA_TIG + SA_RPL1


%include "inc.asm"org 0x9000jmp ENTRY_SEGMENT[section .gdt]
; GDT definition
;                                 段基址,       段界限,       段属性
GDT_ENTRY       :     Descriptor    0,            0,           0
;代码段 内存段特权级是2
CODE32_DESC     :     Descriptor    0,    Code32SegLen - 1,    DA_C + DA_32 + DA_DPL0
;显存段 内存段特权级是3
VIDEO_DESC      :     Descriptor 0xB8000,     0x07FFF,         DA_DRWA + DA_32 + DA_DPL3
;数据段 内存段特权级是2
DATA32_DESC     :     Descriptor    0,    Data32SegLen - 1,    DA_DR + DA_32 + DA_DPL2
;栈段   内存段特权级是2
STACK32_DESC    :     Descriptor    0,     TopOfStack32,       DA_DRW + DA_32 + DA_DPL2
; GDT endGdtLen    equ   $ - GDT_ENTRYGdtPtr:dw   GdtLen - 1dd   0; GDT Selector
;代码段 选择子请求特权级是0
Code32Selector     equ (0x0001 << 3) + SA_TIG + SA_RPL0
;显存段 选择子请求特权级是3
VideoSelector      equ (0x0002 << 3) + SA_TIG + SA_RPL3
;数据段 选择子请求特权级是1
Data32Selector     equ (0x0003 << 3) + SA_TIG + SA_RPL1
;栈  段 选择子请求特权级是0
Stack32Selector    equ (0x0004 << 3) + SA_TIG + SA_RPL2; end of [section .gdt]TopOfStack16    equ 0x7c00[section .s16]
[bits 16]
ENTRY_SEGMENT:mov ax, csmov ds, axmov es, axmov ss, axmov sp, TopOfStack16; initialize GDT for 32 bits code segmentmov esi, CODE32_SEGMENTmov edi, CODE32_DESCcall InitDescItemmov esi, DATA32_SEGMENTmov edi, DATA32_DESCcall InitDescItemmov esi, STACK32_SEGMENTmov edi, STACK32_DESCcall InitDescItem; initialize GDT pointer structmov eax, 0mov ax, dsshl eax, 4add eax, GDT_ENTRYmov dword [GdtPtr + 2], eax; 1. load GDTlgdt [GdtPtr]; 2. close interruptcli ; 3. open A20in al, 0x92or al, 00000010bout 0x92, al; 4. enter protect modemov eax, cr0or eax, 0x01mov cr0, eax; 5. jump to 32 bits code;降特权级跳转 由高到低; push Stack32Selector   ; 目标栈段选择子;push TopOfStack32      ; 栈顶指针位置; push Code32Selector    ; 目标代码段选择子; push 0                 ; 目标代码段偏移; retfjmp word Code32Selector : 0; esi    --> code segment label
; edi    --> descriptor label
InitDescItem:push eaxmov eax, 0mov ax, csshl eax, 4add eax, esimov word [edi + 2], axshr eax, 16mov byte [edi + 4], almov byte [edi + 7], ahpop eaxret[section .dat]
[bits 32]
DATA32_SEGMENT:DTOS               db  "balabala zhang bao bao!", 0DTOS_OFFSET        equ DTOS - $$Data32SegLen equ $ - DATA32_SEGMENT[section .s32]
[bits 32]
CODE32_SEGMENT:mov ax, VideoSelectormov gs, axmov ax, Data32Selectormov ds, axmov ax, Stack32Selectormov ss, axmov eax, TopOfStack32mov esp, eaxmov ebp, DTOS_OFFSETmov bx, 0x0Cmov dh, 12mov dl, 33call PrintString ;打印jmp $; ds:ebp    --> string address
; bx        --> attribute
; dx        --> dh : row, dl : col
PrintString:push ebppush eaxpush edipush cxpush dxprint:mov cl, [ds:ebp]cmp cl, 0je endmov eax, 80mul dhadd al, dlshl eax, 1mov edi, eaxmov ah, blmov al, clmov [gs:edi], axinc ebpinc dljmp printend:pop dxpop cxpop edipop eaxpop ebpretCode32SegLen    equ    $ - CODE32_SEGMENT;显存段
[section .gs]
[bits 32]
STACK32_SEGMENT:times 1024 * 4 db 0Stack32SegLen equ $ - STACK32_SEGMENT
TopOfStack32  equ Stack32SegLen - 1


在当前的代码当中 数据段的访问已经合法了,然而此时栈段的内存特权级是2,所以在32位保护模式下 因为需要函数调用 所以必须要使用栈段,所以在使用栈段时候,处理器发现,特权级为0的代码 想使用特权级为2的栈段,肯定有问题啊!! 因为 不同的特权级要使用对应的不同的栈段!!! 0特权级就要使用0特权级的栈。而这里不匹配 当然会有异常!!! 所以处理器提示我们 在访问ss栈段的时候 cpl != rpl

将 栈段改成如下即可
;栈段 内存段特权级是0
STACK32_DESC : Descriptor 0, TopOfStack32, DA_DRW + DA_32 + DA_DPL0

;栈 段 选择子请求特权级是0
Stack32Selector equ (0x0004 << 3) + SA_TIG + SA_RPL0


结论:
对于栈段,当为SS寄存器赋值的时候,使用规则 :
(CPL == RPL) && (CPL == DPL) 保证特权级的匹配

所以在定义段的时候,我们绝大数情况下 我们会让 DPL == RPL, 即 让内存段特权级 == 选择子请求特权级 ,避免出现访问权限问题。

特权级转移 之 保护模式下数据段特权级保护依据相关推荐

  1. 12、(12.4.2)保护模式下数据段和栈段保护

    1/向下扩展的栈段 实际使用的段界限就是段内不允许访问的最低端偏移地址, (基地址+0)~(基地址+段界限)这段空间是不属于栈段. 举例画图说明: 例1, 基地址为0x00000010,段界限为0x1 ...

  2. MIT-JOS系列1:实模式和保护模式下的段寻址方式

    实模式下的段寻址 以8086为例 8086 段寄存器16位(段地址/基地址),寄存器16位(偏移地址),地址总线20位(寻址1M:2^20) 实际物理地址 = (段寄存器 << 4) + ...

  3. ASM:《X86汇编语言-从实模式到保护模式》第14章:保护模式下的特权保护和任务概述...

    ★PART1:32位保护模式下任务的隔离和特权级保护  这一章是全书的重点之一,这一张必须要理解特权级(包括CPL,RPL和DPL的含义)是什么,调用门的使用,还有LDT和TSS的工作原理(15章着重 ...

  4. IA-32 Intel手册学习笔记(二)保护模式下的内存管理

    内存管理概述(Memory Management Overview) Inter体系结构的内存管理可分为两部分:分段和分页. 分段提供了一种机制,这种机制可以为每个程序或者任务提供单独的代码.数据和栈 ...

  5. 内核基础 - 实模式与保护模式下的寄存器计算机的启动过程(by quqi99)

    作者:张华  发表于:2016-03-01 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 ( http://blog.csdn.net/quqi99 ) CP ...

  6. 保护模式下的CPL,RPL,DPL与特权级检查(二)

    X86汇编语言:从事模式到保护模式读书笔记 ----------特权级保护 PS:此文并没有多长,只不过末尾附上了完整源代码占了90%的篇幅 <这是链接--保护模式下的RPL(一)--–> ...

  7. 【OS学习笔记】二十三 保护模式七:保护模式下任务的隔离与任务的特权级概念

    上一篇文章学习了保护模式下操作系统内核如何加载程序并运行:点击链接查看上一篇文章 本篇文章接着上一篇文章学习保护模式下任务的隔离. 包括以下学习内容: 任务的全局空间和局部空间 任务的TSS 任务的L ...

  8. 实地址模式与保护模式下的中断与异常处理

    在中断和异常的处理过程中,很重要的一件事是如何识别中断源,获取中断服务子程序的入口地址.在80486 CPU系统中,因为CPU的工作模式不同而获取中断向量的方式有所不同,本节讨论CPU工作在实地址模式 ...

  9. 保护模式下的RPL(一)

    <x86汇编语言:从实模式到保护模式>读书笔记 源码面前,了无秘密 --jjhou <这是链接-保护模式下的CPL,RPL,DPL(二)(两篇文章一起看最好,由于先写的二,后写的一, ...

最新文章

  1. 大脑使用交叉存储,来区分现在和过去
  2. c语言程序计算p q真值表,C语言程序设计第2章数据类型﹒运算符和表达式.ppt
  3. mysql增量备份二进制日志,mysql增量备份二进制日志shell脚本
  4. 【2018山东省赛 - A】Anagram(贪心,费用流,KM算法)
  5. python判断当前时间是否在两个时间之间_Python 判断时间是否在时间区间内的实例...
  6. 宝石光是什么石头_沙漠戈壁的漂亮“石头”让人见了流口水
  7. 三大运营商回复 4G 降速;微信上线语音转文字功能;IntelliJ IDEA 2019.2.1 发布 | 极客头条...
  8. iOS开发之在地图上绘制出你运行的轨迹
  9. php管理员登陆问题,discuz论坛管理员无法登录后台的原因和解决方法
  10. 《计算机系统:系统架构与操作系统的高度集成》——1.3 操作系统的作用
  11. Java面向对象㈡ -- 继承与多态
  12. 汇编语言 王爽 第四版 课后检测点 课后实验 包括解释 持续更新~~
  13. js中获取浏览器和屏幕高度
  14. C++写的简易的控制台游戏
  15. 大数据阿里云工具之DataWorks(一)
  16. Dubbox框架简介
  17. 2021年河南高考--各高校在河南录取分数线预测(本科二批——理科)
  18. 1-17 Set集合和Map集合
  19. 小学生趣味C++编程第27课 老狼老狼几点钟
  20. Android阿拉伯语UI适配问题汇总

热门文章

  1. Android vold介绍
  2. 扩展Lucas定理 扩展Lucas板子
  3. win7计算机可何创建域,win7系统创建域控制器的图文步骤
  4. Visitor模式(访问者设计模式)
  5. 邮件服务器hMailServer管理工具hMailServer Administrator汉化
  6. 极兔速递快递批量查询工具箱
  7. 在线编辑器 支持php 手机,javascript - PC 手机兼容的 编辑器
  8. php sl4,闪电顶级公路车--Sworks Tarmac sl4
  9. 《数据结构》—— 串的模式匹配算法
  10. 如何利用微博搜索进行引流?