任务切换——《x86汇编语言:从实模式到保护模式》读书笔记38
任务切换——《x86汇编语言:从实模式到保护模式》读书笔记38
- 本文及后面的几篇博文是原书第15章的学习笔记。
- 本章依然使用第13章的主引导程序。
1. 协同式多任务与抢占式多任务
有两种基本的任务切换方式,一种是协同式的,一种是抢占式的。
1.1 协同式
从一个任务切换到另一个任务,需要当前任务主动地请求暂时放弃执行权,或者在通过调用门请求操作系统服务时,由操作系统趁机将控制转移到另一个任务。这种方式依赖于每个任务的“自律”性,当一个任务失控时,其他任务可能得不到执行的机会。
1.2 抢占式
可以安装一个定时器中断,并在中断服务例程中实施任务切换。硬件中断信号总会定时出现,在这种情况下,每个任务都能获得平等的执行机会。而且,即使一个任务失控,也不会导致其他任务没有机会执行。
抢占式多任务将在第17章学习。这一章,我们通过代码学习任务切换的几种方法,以及它们各自的特点。
关于任务切换的几种方法,可以参考我的博文:
任务切换的方法——《x86汇编语言:从实模式到保护模式》读书笔记36
2. 代码清单
本章实验需要3个源文件,分别是:
c13_mbr.asm
(依然用第13章的引导程序)
c15_core.asm
(第689和706行少了dword
,应该加上)
c15.asm
3. 代码讲解
首先有几点需要说明:
1. 处理器在刚进入保护模式的时候,是以0特权级运行的;
2. 任务不一定非得是3特权级,也可以是0特权级;
3. 操作系统除了为每一个任务提供服务外,也会有一个作为任务而独立存在的部分,而且是0特权级别的任务,以完成一些管理和控制的功能。
内核开始的工作和上一章相同:主要是显示处理器的品牌信息,安装调用门。接下来的工作是创建0特权级的内核任务。
3.1 创建0特权级的内核任务——程序管理器
3.1.1 为程序管理器的TSS分配内存
908 ;为程序管理器的TSS分配内存空间
909 mov ecx,104 ;为该任务的TSS分配内存
910 call sys_routine_seg_sel:allocate_memory
911 mov [prgman_tss+0x00],ecx ;保存程序管理器的TSS基地址
注意,为了追踪程序管理器的TSS,需要保存它的基地址和选择子。为此,作者在内核数据段声明并且初始化了6个字节。
430 ;程序管理器的任务信息
431 prgman_tss dd 0 ;程序管理器的TSS基地址
432 dw 0 ;程序管理器的TSS描述符选择子
3.1.2 填写程序管理器的TSS
913 ;在程序管理器的TSS中设置必要的项目
914 mov word [es:ecx+96],0 ;没有LDT。处理器允许没有LDT的任务。
915 mov word [es:ecx+102],103 ;没有I/O位图。0特权级事实上不需要。
916 mov word [es:ecx+0],0 ;反向链=0
917 mov dword [es:ecx+28],0 ;登记CR3(PDBR)
918 mov word [es:ecx+100],0 ;T=0
919 ;不需要0、1、2特权级堆栈。0特级不
920 ;会向低特权级转移控制。
3.1.3 在GDT中创建TSS描述符
922 ;创建TSS描述符,并安装到GDT中
923 mov eax,ecx ;TSS的起始线性地址
924 mov ebx,103 ;段长度(界限)
925 mov ecx,0x00408900 ;TSS描述符,特权级0
926 call sys_routine_seg_sel:make_seg_descriptor
927 call sys_routine_seg_sel:set_up_gdt_descriptor
928 mov [prgman_tss+0x04],cx ;保存程序管理器的TSS描述符选择子
注意:TSS描述符只能安装在GDT中。
3.1.4 加载TR
寄存器
930 ;任务寄存器TR中的内容是任务存在的标志,该内容也决定了当前任务是谁。
931 ;下面的指令为当前正在执行的0特权级任务“程序管理器”后补手续(TSS)。
932 ltr cx
第932行执行后,处理器用该选择子(CX的值)访问GDT,找到对应的TSS描述符,将其B位置1,表示该任务正在执行中(或者处于挂起状态);同时,还要把该TSS描述符传送到TR的描述符高速缓存器中。此时,可认为“程序管理器”任务正在执行中。
3.2 加载用户程序
3.2.1 分配一个任务控制块(TCB)
938 mov ecx,0x46
939 call sys_routine_seg_sel:allocate_memory
940 call append_to_tcb_link ;将此TCB添加到TCB链中
任务控制块依然用第14章的结构。
3.2.2 调用过程load_relocate_program
942 push dword 50 ;用户程序位于逻辑50扇区
943 push ecx ;压入任务控制块起始线性地址
944
945 call load_relocate_program
过程load_relocate_program
的代码和上一章相比没有太大的变化,仅仅是对TSS的填写比较完整。
3.2.3 通过CALL指令切换到用户任务
947 call far [es:ecx+0x14] ;执行任务切换。和上一章不同,任务切
948 ;换时要恢复TSS内容,所以在创建任务
949 ;时TSS要填写完整
第947行是一个间接远调用指令,在TCB偏移为0x14的地方,应该先是一个32位的段内偏移,然后是一个16位的代码段选择子或者调用门选择子。
但是,结合TCB的结构图,我们发现先是一个TSS基地址(丢弃不用),然后是一个TSS的选择子。虽然有点奇怪,但是却合法。当处理器发现是TSS的选择子,就会执行任务切换。主要过程如下:
1. 保护现场,因为当前正在执行的任务是由TR指示的,所以要把每个寄存器的快照保存到由TR指向的TSS中。这些寄存器包括:GS,FS,DS,SS,CS,ES,EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX,EFLAGS,EIP.
2. 处理器根据TSS选择子索引GDT,找到新任务的TSS描述符,进而找到新任务的TSS,从中恢复各个寄存器的内容,包括通用寄存器、EFLAGES、段寄存器、EIP、ESP、LDTR等。
3. TR指向新任务的TSS,处理器开始执行新的任务。
下图对理解这个过程很有帮助。
不过,上面的总结不够完整,还隐去了一些细节,比如权限的检查(以后的博文会提到)。
另外,新旧任务的TSS的B位,EFLAGS的NT位,任务链接域的变化也是需要关注的。好在作者已经总结成了表格,这里我们再次复习一下。
3.3 用户程序的执行与切换到程序管理器
用户代码比较简单。请注意最后一行
74 call far [fs:TerminateProgram]
这句是通过调用门转到全局空间执行。
354 terminate_current_task: ;终止当前任务
355 ;注意,执行此例程时,当前任务仍在
356 ;运行中。此例程其实也是当前任务的
357 ;一部分
358 pushfd
359 mov edx,[esp] ;获得EFLAGS寄存器内容
360 add esp,4 ;恢复堆栈指针
361
362 mov eax,core_data_seg_sel
363 mov ds,eax
364
365 test dx,0100_0000_0000_0000B ;测试NT位
366 jnz .b1 ;当前任务是嵌套的,到.b1执行iretd
367 mov ebx,core_msg1 ;当前任务不是嵌套的,直接切换到
368 call sys_routine_seg_sel:put_string
369 jmp far [prgman_tss] ;程序管理器任务
370
371 .b1:
372 mov ebx,core_msg0
373 call sys_routine_seg_sel:put_string
374 iretd
358~360:获得EFLAGS寄存器的值,值保存在EDX中;
365:测试EFLAGS的NT位。本实验的场景是,程序管理器可以用JMP指令或者CALL指令切换到用户任务。如果是前者,那么用户任务的NT=0,需要用JMP指令切换到程序管理器;如果是后者,那么用户任务的NT=1,需要用IRET指令返回到程序管理器。
3.4 程序管理器再次加载用户任务
因为之前程序管理器通过CALL切换到了用户任务,所以用户任务会通过IRET返回,所以第374行会执行。接下来又回到了程序管理器,从它中断的地方继续执行,也就是第952行。
51 ;重新加载并切换任务
952 mov ebx,prgman_msg2
953 call sys_routine_seg_sel:put_string
954
955 mov ecx,0x46
956 call sys_routine_seg_sel:allocate_memory
957 call append_to_tcb_link ;将此TCB添加到TCB链中
958
959 push dword 50 ;用户程序位于逻辑50扇区
960 push ecx ;压入任务控制块起始线性地址
961
962 call load_relocate_program
955~962:再次加载用户任务,依然是第50扇区的程序。这充分说明:一个程序可以对应着多个运行中的副本,或者说多个任务。
3.5 管理器通过JMP指令切换到用户任务
963
964 jmp far [es:ecx+0x14] ;执行任务切换
3.6 用户程序通过JMP指令切换到管理器
因为用户任务是同一份代码,所以也会执行到365行。不同的是这个任务不是嵌套于程序管理器的,所以会执行369行,用JMP指令返回。
3.7 程序管理器停机
966 mov ebx,prgman_msg3
967 call sys_routine_seg_sel:put_string
968
969 hlt
这章的代码就说到这里。感谢关注!
任务切换——《x86汇编语言:从实模式到保护模式》读书笔记38相关推荐
- x86汇编语言从实模式百度云_Intel x86 CPU 32位保护模式杂谈之任务切换 上
目录: 什么是任务 任务由什么组成 任务门描述符是什么东东?有了TSS描述符为什么要有任务门描述符? 参考文献 什么是任务 任务(task)是处理器可以分配.执行.挂起的工作单位,笔者认为和我们操作系 ...
- 处理器在实施任务切换时的操作——《x86汇编语言:从实模式到保护模式》读书笔记39
处理器在实施任务切换时的操作--<x86汇编语言:从实模式到保护模式>读书笔记39 处理器可以通过以下四种方法实施任务切换: 1. call指令或者jmp指令的操作数是GDT内的某个TSS ...
- 任务切换的方法——《x86汇编语言:从实模式到保护模式》读书笔记37
任务切换的方法--<x86汇编语言:从实模式到保护模式>读书笔记37 1. 中断门和陷阱门 在实模式下,内存最低端的1M是中断向量表,保存着256个中断处理过程的段地址和偏移.当中断发生时 ...
- 硬盘和显卡的访问与控制(一)——《x86汇编语言:从实模式到保护模式》读书笔记01
本文是<x86汇编语言:从实模式到保护模式>(电子工业出版社)的读书实验笔记. 这篇文章我们先不分析代码,而是说一下在Bochs环境下如何看到实验结果. 需要的源码文件 第一个文件是加载程 ...
- 任务和特权级保护(三)——《x86汇编语言:从实模式到保护模式》读书笔记34
任务和特权级保护(三)--<x86汇编语言:从实模式到保护模式>读书笔记34 5.2.7 在GDT中创建LDT描述符 处理器要求在GDT中安装每个LDT的描述符.当要使用这些LDT时,可以 ...
- 程序的加载和执行(五)——《x86汇编语言:从实模式到保护模式》读书笔记25
程序的加载和执行(五)--<x86汇编语言:从实模式到保护模式>读书笔记25 前面几篇博文终于把代码分析完了.这篇就来说说代码的编译.运行和调试. 1.代码的编译及写入镜像文件 之前我们都 ...
- 程序的加载和执行(四)——《x86汇编语言:从实模式到保护模式》读书笔记24
程序的加载和执行(四)--<x86汇编语言:从实模式到保护模式>读书笔记24 通过本文能学到什么? 怎样跳转到用户程序 用户程序通过调用内核过程完成自己的功能 怎样从用户程序返回到内核 接 ...
- 【OS修炼指南目录】----《X86汇编语言-从实模式到保护模式》读书笔记目录表
学习交流加(可免费帮忙下载CSDN资源): 个人微信: liu1126137994 学习交流资源分享qq群1(已满): 962535112 学习交流资源分享qq群2: 780902027 本文是将个人 ...
- x86汇编语言从实模式百度云_x86汇编语言:从实模式到保护模式
x86汇编语言:从实模式到保护模式2013年1月由电子工业出版社出版发行,总共6000行的源代码,全方位地向读者展现汇编语言程序设计之美.尽管汇编语言也是一种计算机语言,但却是与众不同的,与它的同类们 ...
最新文章
- python之路---装饰器函数
- mysql日常有哪些用_mysql日常笔记(持续更新)
- Appium 命令行安装教程
- ABAP入门程序,你会了嘛?
- 设计模式:代理模式是什么,Spring AOP还和它有关系?
- IDEA远程部署调试Java应用程序
- Java学习之数据类型的转换
- spring boot(一):Hello World
- Java 8 (5) Stream 流 - 收集数据
- 凸优化第二章凸集 2.5分离与支撑超平面
- 大学生python心得1000字_大学生读书心得1000字3篇
- dx11 将纹理保存到dds
- 《自拍教程74》Python 假装企业微信电脑在线并定时关机,骗老板的好方法!
- python实现误差逆传播算法
- javamail模拟邮箱功能--邮件删除-中级实战篇【邮件标记方法】(javamail API电子邮件实例)
- 郭店楚简——原简整理,文物出版社
- 先验概率和后验概率那点事儿
- nginx upstream 健康检查
- 实验吧CTF逆向题1000writeup
- Qt Creator打造VScode one dark pro主题配色
热门文章
- Python中的遇到的错误(持续更新)
- Adnroid提高效率之资源移动
- ALGO-117_蓝桥杯_算法训练_友好数
- 使用正則表達式对URL进行解析
- 尝试.Net Core—使用.Net Core + Entity FrameWork Core构建WebAPI(一)
- 线段树--codevs 1690 开关灯
- CentOS 6.5系统安装配置图解教程(详细图文)
- ChartDirector资料小结
- 超长数列中n个整数排序C++代码实现
- 转:c/c++ 运行库