《80X86汇编语言程序设计教程》十九 操作系统类指令与输入输出保护

1、  通常只在操作系统代码中使用,80386支持4个特权等级,操作系统指令也可分3种:实模式和任何特权级下可执行指令、实模式及特权级0下可执行的指令和仅在保护模式下执行的指令。

  1)  实模式和任何特权级下可执行的指令

    a)存储全局和中断描述符表寄存器指令

      GDT与IDT整个系统各只有一张,它们的定位信息分别保存在GDTR与IDTR中,这两个寄存器的值可以被保存。须注意,LDT表示任务私有,存储LDTR值的指令不属于这一类。

      i)存储全局描述符表寄存器指令:SGDT  DST

        DST是48位(6字节)存储器操作数,执行后GDTR的16位界限值存入DST低字,而GDTR中32位基地址存入DST高双字。对标志位无影响。

      ii)存储中断描述符表寄存器指令:SIDT  DST

        与“SGDT  DST”类似。

    b)存储机器状态字指令:SMSW  DST

      DST可以是16位通用寄存器或存储单元。对标志位无影响。

      说明:为了兼容80286指令集(386的CR0低字节等同于286机器状态字),在386中,存储机器字应该使用存储CR0寄存器指令。

  2)  实模式及特权级0下可执行的指令

    关键寄存器的设置指令等,在保护模式下CPL不为0的指令执行它们将引发错误码为0的通用保护故障。虚拟8086模式下(CPL = 3)同样如此。

    a)清任务切换标志指令:CLTS

      任务切换时,CR0的TS位(任务切换标志位)自动被置1(参考“《80X86汇编语言程序设计教程》十二 任务状态段、控制门和控制转移”),该指令功能是把TS标志位清0。不影响其它标志位。

    b)暂停指令:HLT

      该指令使处理器暂停执行,只有在接受一个已经启用的中断,或者让系统复位,才重新启动。对标志位没有影响。

    c)装载全局描述符表寄存器指令:LGDT   SRC

      SRC是48位(6字节)存储器操作数,执行后伪描述符SRC(PDESC结构)的低字送GDTR低字(段界限),高双字送GDTR高双字(段基址)。对标志位无影响。

    d)装载中断描述符表寄存器指令:LIDT  SRC

      与“LGDTR”类似。

    e)装载机器状态字指令:LMSW  SRC

      SRC可以是16位通用寄存器或存储单元。该指令将SRC装入机器状态字(CR0的低16位),不影响标志位。同样,是为了兼容286,386不应该用它。

    f)控制寄存器数据传送指令:MOV  DST,SRC

      实现386控制寄存器和32位通用寄存器之间的数据传送。所以,DST和SRC可以是3个控制寄存器(CR0、CR2、CR3---参考“《80X86汇编语言程序设计教程》八 80386程序设计基础”)和任一32位通用寄存器,但不能同时为控制寄存器。对标志位门影响。

    g)调试寄存器数据传送指令

      规则同上。调试寄存器为DR0~DR7(参考“《80X86汇编语言程序设计教程》八 80386程序设计基础”)。

    h)测试寄存器数据传送指令

      规则同上。测试寄存器为TR6和TR7(参考“《80X86汇编语言程序设计教程》八 80386程序设计基础”)。

  3)  只能在保护模式下执行的指令

    只能在保护模式下执行,在实模式下执行将引起非法操作码故障(向量号6)。

    a)装载局部描述符表寄存器指令:LLDT  SRC

      SRC可以为16位通用寄存器或存储单元(代表的选择子必须指示GDT中类型为LDT的描述符,为0则表示空选择子,及不使用LDT),不影响标志位。CPL不为0时(错误码为0)、选择子不指示GDT中描述符或描述符类型不是LDT时(  错误码由该选择子构成),执行它将产生通用保护故障。

    b)存储局部描述符表寄存器指令:SLDT  DST

      规则同上。

    c)装载和存储任务寄存器指令

      任务寄存器TR指示当前任务状态段TSS(参考“《80X86汇编语言程序设计教程》十二 任务状态段、控制门和控制转移”)。随着任务的切换而切换,如果任务嵌套,那么TR原值作为链接字保存在新任务TSS中。

      i) 装载任务寄存器指令:LTR  SRC

        SRC为16位通用寄存器或存储单元。SRC指示的选择子不能为空,必须索引位于GDT中的描述符,且类型为TSS。该指令不影响标志位。CPL不为0时(错误码为0)、选择子不指示GDT中描述符或描述符类型不是LDT时(错误码由该选择子构成),执行它将产生通用保护故障。

      ii)存储任务寄存器指令:STR  DST

        DST规则同上,不影响标志位。

    d)调整申请特权级指令:ARPL  OPRD1,OPRD2

      OPRD1为16位通用寄存器或存储单元,OPRD2为16位通用寄存器。该指令用选择子OPRD2的申请特权级(RPL)去检查选择子OPRD1的RPL,如果OPRD1.RPL < OPRD2.RPL,那么ZF = 1,OPRD1.RPL = OPRD2.RPL;否则ZF = 0。二者都可为空,不影响其它标志位。

    e)装载存取权指令:LAR  OPRD1,OPRD2

      两操作数都可以为16位或32位通用寄存器,OPRD2还可以是存储单元,但它们尺寸必须一样。如果选择子OPRD2(32位则使用低16位)所指示描述符满足下述条件,那么ZF = 1,并把描述符属性字段装入OPRD1;否则ZF = 0,OPRD1不变。

      i)在描述符表范围内

      ii)为存储段描述符或系统段描述符,或任务门、调用门描述符

      iii)CPL和OPRD2.RPL都不大于OPRD2.DPL

      描述符参考“《80X86汇编语言程序设计教程》九 分段管理机制及纯DOS环境搭建”与“《80X86汇编语言程序设计教程》十二 任务状态段、控制门和控制转移”。结果是高4字节与00FFXFF00相与的结果,X表示未定义,如果OPRD1为16位,那么只取结果低2字节(无G位、AVL位)。除ZF不影响其它标志位。

    f)装载段界限指令:LSL  OPRD1,OPRD2

      规则同上,区别在于转载的是段界限字段且条件第二点限制更加严格,不能为门描述符。在满足条件下,装载到OPRD1的OPRD2所指示描述符的界限字段值以字节为单位。如果描述符中界限字段以4K为单位(G = 1),那么装入到OPRD1时左移12位,空出的位全部填1。如果使用16位操作数,只有段界限低16位被装载到OPRD1。除ZF不影响其它标志位。

    g)读写检验指令

      检查在当前特权级上指定的段是否能读写,从而避免不必要的异常。

      i)读检验指令:VERR  OPRD

        OPRD可以是16位或32位通用寄存器和存储单元。如果为32位则使用低16位,功能是判断OPRD选择子指示的段在当前CPL是否可读,如果选择子合法,且在当前CPL可读,那么ZF置1,否则ZF清0。除ZF不影响其它标志位。

      ii)写检验指令:VERW  OPRD

        规则同上,只不过检查的属性是是否可写。

  4)  特权指令

    保护模式下只有CPL = 0才能执行的指令,否则引发通用保护异常。特权指令在构造完善保护机制上起重要作用。总结如下:


指令


功能


指令


功能


CLTS


清除CR0的TS位


LTR


装入TR


HLT


停机


MOV  CRn,reg


装入控制寄存器


LGDT


装入GDTR


MOV  reg,CRn


保存控制寄存器


LIDT


装入IDTR


MOV  DRn,reg


装入测试寄存器


LLDT


装入LDTR


MOV  reg,DRn


保存测试寄存器


LMSW


装入MSW(CR0低16位)

    可见,设置GDTR、IDTR和LDTR是特权指令,而存储它们不是。而设置和存储控制和测试寄存器都是特权指令。

2、  输入/输出保护

  1)  输入/输出保护

    a)I/O敏感指令

      输入/输出特权级(I/O Privilege Level)规定可执行I/O有关指令和访问I/O空间地址的最外层特权级(在标志寄存器EFLAGS中,参考“《80X86汇编语言程序设计教程》八 80386程序设计基础”)。I/O许可位图(在TSS中)规定I/O空间哪些地址可以在任何特权级执行的代码访问。I/O敏感指令如下:


指令


功能


保护模式下执行条件


CLI


清除EFLAGS中IF位


CPL <= IOPL


STI


设置EFLAGS中IF位


CPL <= IOPL


IN


从I/O地址读出数据


CPL <= IOPL或I/O位图允许


INS


从I/O地址读出字符串


CPL <= IOPL或I/O位图允许


OUT


从I/O地址写入数据


CPL <= IOPL或I/O位图允许


OUTS


从I/O地址写入字符串


CPL <= IOPL或I/O位图允许

      如果权限不够,则引发通用保护异常。每个任务有自己的EFLAGS与TSS,所以各个任务IOPL可以有不同,并且可定义不同的I/O许可位图。注意:实模式下全部可执行。

    b)I/O许可位图

      由二进制位串组成,每一位对应一个I/O地址,如果m位为0,那么I/O地址m可由本任何特权等级代码的程序访问,否则只能在IOPL特权级或更内层特权级执行的程序访问,不然引发通用保护异常。 一条I/O指令最多涉及4个I/O地址(如IN  EAX,71H),只有涉及到的全部I/O许可位为0才能顺利访问。386支持I/O地址空间大小64K,所以I/O许可位有效部分最大为8KB。当前任务使用的I/O许可位图在TSS低端64K(用16位偏移,最大为64K)字节内,位串以字节为存储单位,所以要存储整个I/O许可位图时,偏移尽量保证低于64K – 8K = 56K。

    c)I/O访问许可检查细节

      步骤如下:

      i)CPL <= IOPL是否成立,成立则直接跳转到第8步直接进行I/O访问

      ii)取得位图开始偏移(TSS的I/O许可位图I偏移字段---TSS内偏移66H字节单元)

      iii)计算字节偏移(I/O地址值右移3位---即除以8)

      iv)计算位偏移以形成屏蔽码值(I/O地址右移出来的3位放字单元)

      v)字节是否越界,是则引发通用保护异常(位图偏移+字节偏移+1<=段界限)

      vi)从位图中读出两个字节(读写最快)

      vii)进行位检查,不通过则引发通用保护异常

      ix)进行I/O访问

      在读取时,总是读取两个字节,由于I/O访问最多同时访问4个连续端口,最多也是分布在连续2个字节之内,所以在判断是否越界时要也仅要加1处理,为了在判断I/O许可位图最高字节上述流程同样适用,必须在I/O许可位图最后添加一个全1字节0ffh。I/O许可位图开始偏移加上8K所得值与TSS界限值二者较小者决定I/O许可位图有效末端偏移。当许可位图开始偏移大于56K时,将有部分位越过位图界限,从而无法因无法访问而触发通用保护异常(那部分位被认为是全1)。利用这个特点,可以大大减小I/O许可位图占用的存储单元,从而大大减小TSS。如:

1 ;演示任务任务状态段(TSS)
2 DemoTSSSeg    segment    para    use16
3     DTSS    TASKSS<>                      ;TSS低端部分
4             db    100h/8 dup(0ffh)        ;对应I/O端口00H~0FFH
5             db    100h/8 dup(0)           ;对应I/O端口100H~1FFH
6             db    0ffh                    ;IO许可位结束标志
7     DemoTSSLen = $ - DemoTSSSeg
8 DemoTSSSeg    

      上面的TSS只含有许可位图最初的200H位,对应端口0~1FFH,而其它位都被认为是1。之前实例中使用的格式,高度区只带IO许可位结束标志表示所有的位都为1。

  2)  重要标志保护

    386对EFLAGS标志中的IOPL、IF和VM这3个字段的处理比较特殊,只有较高权限等级的代码才能通过IRET、POPF、CLI和STI等指令来改变它们。下面是不同特权等级下对3个字段的处理情况:


特权等级


标志字段


VM


IOPL


IF


CPL = 0


可变(除POPF指令外)


可变


可变


0 < CPL <= IOPL


不变


不变


可变


CPL > IOPL


不变


不变


不变

    可见,只有CPL = 0的情况下才能修改VM和IOPL,必须在IOPL同级或者更内层才能修改IF。须注意,在特权级不满足的条件下,其中IRET和POPF指令试图更改这3个字段并不引发异常,只是试图的修改操作并不会被成功执行。此外,POPF总是不能改变VM位,而PUSHF指令总是把0压入到VM位。

时间: 2024-08-29 11:04:15

《80X86汇编语言程序设计教程》十九 操作系统类指令与输入输出保护的相关文章

《80X86汇编语言程序设计教程》十 实模式与保护模式的切换实例

1.  再次声明,需要纯DOS系统才能看到满意测试效果.内容是演示实模式与保护模式切换实例,实现功能是16进制显示从110000H开始的256个字节的值 2.  源代码如下: 1 ;功能:演示实模式与保护模式的切换,16进制显示从110000H开始的256个字节的值 2 ;16位偏移的段间直接转移指令的宏定义,这是一个JMP指令到所描述的地址 3 4 JUMP macro selector,offsetv 5 db 0eah ;操作码 6 dw offsetv ;16位偏移 7 dw selec

《80X86汇编语言程序设计教程》二十四 进入与离开V86模式实例

1.  这是我这本书调得最失败的一个实例,而且问题都是超出了这本书能教会我的范畴.作者对调试环境几乎只字不提,这让我有点费解.原作者使用TASM的编译代码,而我使用的MASM加虚拟机进行测试,不知道这两样东西哪里有问题还是源代码要做哪些修正.理论知识参考"<80X86汇编语言程序设计教程>二十二 分页管理机制与虚拟8086模式". 2.  进入和离开V86模式实例:各2种方式进入和离开V86模式.V86模式下8086程序调用实模式软中断处理程序.逻辑功能:以驻留方式结束程序

《80X86汇编语言程序设计教程》二十五 结语(读后感:这本书怎么样)

这本书的推荐星级是:5星.毕竟是经典书籍,没什么好说的. 就汇编本身而言,在编写高效率程序以及对程序的优化,调试,工程的逆向都是一门基础:就理论上的操作系统而言,汇编让你了解CPU,了解计算机的体系结构,它是阅读操作系统源码的前提,这也是<80X86汇编语言程序设计教程>做得比较好的一点,它对386的保护方式下的编程写得比较详实,读完整本书,会发现这学的不仅仅是汇编语言,还有CPU的体系架构,它让你基本猜测得到在编写基于80386CPU的操作系统时,大概要做一些什么事情. 阅读前,我选过几本书

《80X86汇编语言程序设计教程》十五 任务切换实例

1.  理论知识参考"<80X86汇编语言程序设计教程>十二 任务状态段.控制门和控制转移",演示内容:直接通过TSS段的任务切换.通过任务门的任务切换.任务内特权级的变换及参数传递.实现的逻辑功能是:从Temp任务切换到Demo任务以后显示原任务(Temp)的挂起点EIP的值. 2.  源代码 "386scd.asm"不再贴上来.参考"<80X86汇编语言程序设计教程>十三 任务内无特权级变换转移实例",演示代码如下:

《80X86汇编语言程序设计教程》二十三 分页管理机制实例

1.  理论知识参考"<80X86汇编语言程序设计教程>二十二 分页管理机制与虚拟8086模式".演示分页机制实例:初始化页目录表和部分页表:启用分页管理机制:关闭分页管理机制等.逻辑功能:在屏幕上显示一条表示已启用分页管理机制的提示信息.大体步骤是:在实模式下拷贝显示串程序的代码到预定义区域,转保护模式,初始化页目录和2个页表,开启分页机制,转入预定义区执行显示代码,然后关闭分页机制,重新回到实模式,程序终止. 2.  源代码 "386scd.asm"

《80X86汇编语言程序设计教程》十一 32位代码段和16位代码段切换实例

1.  演示32位代码段与16位代码段之间的切换.实现的功能是以十六进制和ASCII码字符两种形式显示从内存地址100000H开始的16个字节的内容. 2.  源代码如下: 1 ;DosTest.Asm 2 ;16位偏移的段间转移指令的宏定义 3 ;使用于16位段,用于跳转到32位目的段 4 ;注意:标号偏移必须在16位二进制符号数数能表示的范围之内 5 JUMP16 macro selector,offsetv 6 db 0eah ;操作码 7 dw offsetv ;16位偏移 8 dw s

无废话ExtJs 入门教程十九[API的使用]

无废话ExtJs 入门教程十九[API的使用] extjs技术交流,欢迎加群(201926085) 首先解释什么是 API 来自百度百科的官方解释:API(Application Programming Interface,应用程序编程接口)是一些预先定义的函数,目的是提供应用程序与开发人员基于某软件或硬件的以访问一组例程的能力,而又无需访问源码,或理解内部工作机制的细节. ExtJs的Api必须部署到IIS上,ExtJS的API首页如下图所示: 左侧是搜索栏,可以搜索所有的Ext的组件,如上图

ComicEnhancerPro 系列教程十九:用JpegQuality看JPG文件的压缩参数

作者:马健邮箱:[email protected] 主页:http://www.comicer.com/stronghorse/ 发布:2017.07.23 教程十九:用JpegQuality看JPG文件的压缩参数 事先声明: 严格说来这篇教程是讲JpegQuality的,其实与CEP本身关系不大,但因为我自己经常从CEP启动JpegQuality查看JPG压缩参数, 我觉得其他人可能也有类似的需求,所以就在CEP系列教程里加了这么一篇,并不是有意给JpegQuality打广告. JpegQua

《80x86汇编语言程序设计》保护模式第一个例题

<80x86汇编语言程序设计>保护模式第一个例题的一些个人理解和注释 ; 16位偏移的段间直接转移指令的宏定义 02.jump macro selector, offsetv 03. 04. db 0eah ; jmp far 的操作码 05. dw offsetv 06. dw selector 07. 08.endm 09. 10.; 字符显示宏指令定义 11.echoch macro ascii 12. 13. mov ah, 2 14. mov dl, ascii 15. int 21