码迷,mamicode.com
首页 > 编程语言 > 详细

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

时间:2017-11-19 22:20:23      阅读:289      评论:0      收藏:0      [点我收藏+]

标签:读写   保护模式   位操作   字段   保护   状态   sch   模式   没有   

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位。

 

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

标签:读写   保护模式   位操作   字段   保护   状态   sch   模式   没有   

原文地址:http://www.cnblogs.com/SChivas/p/7862174.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!