任务和特权级保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记34

5.2.7 在GDT中创建LDT描述符

处理器要求在GDT中安装每个LDT的描述符。当要使用这些LDT时,可以用它们的选择子来访问GDT,找到LDT描述符并把它加载到LDTR寄存器。

675         ;在GDT中登记LDT描述符
676         mov eax,[es:esi+0x0c]              ;LDT的起始线性地址
677         movzx ebx,word [es:esi+0x0a]       ;LDT段界限
678         mov ecx,0x00408200                 ;LDT描述符,特权级0
679         call sys_routine_seg_sel:make_seg_descriptor
680         call sys_routine_seg_sel:set_up_gdt_descriptor
681         mov [es:esi+0x10],cx               ;登记LDT选择子到TCB中

LDT描述符的格式如下图:

LDT本身也是一种特殊的段,最大尺寸为64KB;
G:粒度位,用来表示LDT的界限值是以字节为单位还是以4KB为单位;
D:固定为0;
L:固定为0;
AVL和P:含义与存储器的段描述符相同;
S:固定为0;表示系统的段描述符或者门描述符,以区别于存储器的段描述符(S=1);
TYPE:固定为0010b,表示这是一个LDT描述符;

第678行:我认为是作者的笔误,应该是

678         mov ecx,0x00008200     

第681行:将返回的选择子(RPL=0)登记到TCB中;

5.2.8 为用户程序创建TSS

关于TSS的知识,可以参考我的博文TSS详解 ——《x86汇编语言:从实模式到保护模式》读书笔记33

684         mov ecx,104                        ;tss的基本尺寸
685         mov [es:esi+0x12],cx
686         dec word [es:esi+0x12]             ;登记TSS界限值到TCB
687         call sys_routine_seg_sel:allocate_memory
688         mov [es:esi+0x14],ecx              ;登记TSS基地址到TCB

以上代码做的工作有:
1. 申请TSS所需的空间(104字节);
2. 登记TSS的界限值(104-1=103)和基地址到TCB;

接下来,填写TSS表格的内容。
1. Previous Task Link = 0;
2. 填写ESPx和SSx(x=0,1,2)(从TCB中拷贝);
3. 填写LDT选择子(从TCB中拷贝);
4. 填写I/O位图偏移(从TCB中拷贝,等于TSS的界限值103);
5. T=0;

5.2.9 在GDT中创建TSS描述符

和LDT一样,处理器要求必须在GDT中安装TSS的描述符。

719         ;在GDT中登记TSS描述符
720         mov eax,[es:esi+0x14]              ;TSS的起始线性地址
721         movzx ebx,word [es:esi+0x12]       ;段长度(界限)
722         mov ecx,0x00408900                 ;TSS描述符,特权级0
723         call sys_routine_seg_sel:make_seg_descriptor
724         call sys_routine_seg_sel:set_up_gdt_descriptor
725         mov [es:esi+0x18],cx               ;登记TSS选择子到TCB

第722行:我觉得是作者的笔误,应该是0x00008900. G=0,P=1,DPL=0,B=0;
第725行:登记TSS的选择子(RPL=0)到TCB;

以上5.2节的内容,算是把过程load_relocate_program说完了,接下来说如何转到户程序执行。

6. 如何转到用户程序执行

任务寄存器TR总是指向当前任务的TSS,而LDTR寄存器也总是指向当前任务的LDT。TSS是任务的主要标志,因此要使TR寄存器指向当前任务;而使用LDTR的原因是可以在任务执行期间加速对段的访问。

在多任务环境中,从旧任务切换的新任务的时候,TRLDTR寄存器的值都会更新,以指向新任务。但是,目前我们只有一个任务,而且是特权级为3的任务,我们遇到的问题可以表述为:如何从任务的全局空间(处于特权级0)转移到它自己的局部空间(处于特权级3)?

答案是分为两步:
1. 确立身份,使TRLDTR寄存器指向这个任务;
2. 假装从调用门返回;

6.1. TRLDTR寄存器

TRLDTR寄存器都包括16位的选择器部分和描述符高速缓存器部分(如下图所示)。选择器部分的内容是TSS和LDT描述符的选择子。

6.2. ltrlldt指令

加载任务寄存器TR的指令是ltr,其格式为

    ltr r/m16
  1. 这条指令的操作数是通用寄存器或者16位的内存单元,里面的内容是16位的TSS选择子。
  2. 执行这条指令后,处理器用选择子访问GDT,找到TSS描述符,将基地址、段界限、段属性加载到描述符高速缓存器中,同时将该描述符中的B位置1,但并不执行任务切换。
  3. 该指令属于特权指令,只能在0特权级下执行。
  4. 该指令不影响EFLAGS的任何标志位。

加载局部描述符表寄存器LDTR的指令是lldt,其格式为

    lldt r/m16

原理与上述类似,只不过操作数是16位的LDT选择子。

848         mov eax,mem_0_4_gb_seg_sel
849         mov ds,eax
850
851         ltr [ecx+0x18]                     ;加载任务状态段
852         lldt [ecx+0x10]                    ;加载LDT

注意,851~852中的ECX的值是TCB的基地址。以上的代码执行完,用户任务的身份算是确立了。

6.3. 假装从调用门返回

854         mov eax,[ecx+0x44]
855         mov ds,eax                         ;切换到用户程序头部段 

以上两行,向DS中加载用户程序头部段的选择子(RPL=3,TI=1)。

857         ;以下假装是从调用门返回。摹仿处理器压入返回参数
858         push dword [0x08]                  ;调用前的堆栈段选择子
859         push dword 0                       ;调用前的esp
860
861         push dword [0x14]                  ;调用前的代码段选择子
862         push dword [0x10]                  ;调用前的eip
863
864         retf

这段代码要结合用户程序头部的格式和调用门的返回过程来分析。

用户程序头部的格式如下图(为了方便阅读,我总是乐此不疲地贴图)。
注意,被内核重定位后的选择子,其RPL的值都等于3.

关于调用门的返回过程,强烈建议复习一下我的博文调用门详解

这篇博文中讲解的从调用门的返回过程是:

  1. 检测被调用者栈中CS寄存器的RPL字段值,以确定在返回时特权级是否发生改变。
  2. 弹出并使用被调用过程栈上的值加载EIP和CS寄存器。在此过程中会对代码段描述符和代码段选择子的RPL进行特权级与类型检查。
  3. 如果远返回指令是带参数的,则将参数和ESP寄存器的当前值相加,以跳过被调用者栈中的参数部分,最后的结果是ESP寄存器指向调用者SS和ESP的压栈值。注意,retf指令的参数必须等于调用门中所有参数的总字节数之和。
  4. 如果返回时需要改变特权级,则从栈中将ESP和SS弹出,并把值代入寄存器ESP和SS,切换到调用者的栈。
  5. 如果远返回指令是带参数的,则将参数和ESP寄存器的当前值相加,以跳过调用者栈中的参数部分,最后的结果是调用者的栈恢复平衡。
  6. 如果返回时需要改变特权级,则检查DS,ES,FS和GS的内容,如果段选择子指向数据段或者非一致代码段且段描述符的DPL在数值上小于返回后的新CPL,那么就把数值0传送到该段寄存器。

858~862执行完后,栈的布局如下(这其实是内核的栈,并不是用户的0特权级栈):

我们对着上面的返回步骤,一步一步来看。
1. 因为用户程序的CS寄存器中的RPL=3,所以在返回的时候特权级要发生改变。
2. 弹出用户程序的EIP和CS(绿色部分)加载EIP和CS寄存器。
3. 第864行的retf指令不带参数,所以这步跳过。
4. 从栈中将用户程序的ESP和SS(蓝色部分)弹出,并把值代入寄存器ESP和SS,切换到调用者的栈(实际是用户程序的3特权级栈)。
5. 第864行的retf指令不带参数,所以这步跳过。
6. 因为DS中的内容是用户程序头部段的选择子,其DPL=3,所以不会把数值0传到DS;至于ES、FS和GS,它们一般会指向内核数据段,其DPL=0,所以这些寄存器很可能被数值0加载,所以用户程序中应该对它们先初始化再引用。

囿于篇幅,就写到这里吧。下次我们正式进入用户程序的执行…

任务和特权级保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记34相关推荐

  1. 访问数据段时的特权级检查,修改SS时的特权级检查——《x86汇编语言:从实模式到保护模式》读书笔记30

    1. 访问数据段时的特权级检查 为了访问数据段,数据段的选择子必须被加载进段寄存器(ES,ES,FS,GS,SS).在把一个段选择子加载进段寄存器之前,处理器会进行特权级检查(如下图所示). 在数值上 ...

  2. X86汇编语言从实模式到保护模式16:特权级和特权级保护

    目录 1. 特权级保护机制 1.1 基础段保护机制的不足 1.2 特权级划分 1.3 特权级的表示 1.3.1 当前特权级CPL 1.3.2 描述符特权级DPL 1.3.3 请求特权级RPL 1.4 ...

  3. x86汇编语言从实模式百度云_Intel x86 CPU 32位保护模式杂谈之任务切换 上

    目录: 什么是任务 任务由什么组成 任务门描述符是什么东东?有了TSS描述符为什么要有任务门描述符? 参考文献 什么是任务 任务(task)是处理器可以分配.执行.挂起的工作单位,笔者认为和我们操作系 ...

  4. 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表

    学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...

  5. x86汇编语言从实模式百度云_x86汇编语言:从实模式到保护模式

    x86汇编语言:从实模式到保护模式2013年1月由电子工业出版社出版发行,总共6000行的源代码,全方位地向读者展现汇编语言程序设计之美.尽管汇编语言也是一种计算机语言,但却是与众不同的,与它的同类们 ...

  6. [书]x86汇编语言:从实模式到保护模式 -- 第14章 任务和特权级保护,调用门、LDT、TSS、TCB

    # 加载用户程序 Part 1.TCB, Task Control Block, 任务控制块 分配内存作为该任务的TCB,并插入至TCB链表. Part 2.LDT, Locak Descriptor ...

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

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

  8. ASM:《X86汇编语言-从实模式到保护模式》第10章:32位x86处理器的编程架构

    ★PART1:32位的x86处理器执行方式和架构 1. 寄存器的拓展(IA-32) 从80386开始,处理器内的寄存器从16位拓展到32位,命名其实就是在前面加上e(Extend)就好了,8个通用寄存 ...

  9. X86汇编语言从实模式到保护模式20:平坦模型

    1 引入平坦模型(Flat Model)的原因 1.1 内存管理模型变迁 1.1.1 分段模型 1.1.1.1 基本特点 1. 在程序中按结构组织为多个段 2. 在加载程序时,为程序中的每个段创建段描 ...

最新文章

  1. java如何用c 的方法_JAVA如何调用C/C++方法
  2. Unity中那些事半功倍的好插件
  3. linux中下载ftp文件
  4. 未来不是计算机发展的方向,未来人类的方向,或许不是人工智能,而是智能人类...
  5. python字符串解释_python基础之字符串详解
  6. 用php 用拼出一个菱形_这可是我没来过的杭州呀!远在开封的他,用一种特殊的方式,拼出一个彩色杭州...
  7. mongodb 统计内嵌文档中某一属性的方法
  8. PHP双码率视频云转码服务网站源码 支持M3u8秒切
  9. Apache Licene 2.0 协议说明
  10. [转]阿里云配置mysql远程连接
  11. 微软力挺Silverlight 反击美棒球赛用Flash直播
  12. winxp 升级远程连接方法
  13. 学生宿舍管理系统HTML代码,学生宿舍管理系统源代码.doc
  14. 前端应用 - 汉字笔顺书写演示带拼音及发音
  15. 只用一个div制作太极图
  16. 速卖通奇门+聚石塔流程
  17. 苹果手机微信怎么接龙_微信又更新了:群接龙怎么玩?文件如何备份?怎么发高清大视频?...
  18. Android中获取系统所认为的最小滑动距离TouchSlop
  19. linux 安装xamp
  20. 正确设置 pip,避免There was a problem confirming the ssl certificate问题

热门文章

  1. 查阅文献时向原作者发邮件要文献的简单模板
  2. Unity UGUI - Canvas / Camera
  3. mysql.user表中Host为%的含义
  4. tom大叔blog--------深入理解javascript系列-----------笔记
  5. 数据库 'SqlPersistenceService' 的版本为 655,无法打开。此服务器支持 611 版及更低版...
  6. jQuery UI Download
  7. 图像中值处理MATLAB实现
  8. Python列表排序 reverse、sort、sorted 操作方法详解
  9. [云炬创业基础笔记]第二章创业者测试22
  10. Android通用开发笔记和高性能安卓开发框架源码