输入输出保护.docx
- 文档编号:29907966
- 上传时间:2023-08-03
- 格式:DOCX
- 页数:25
- 大小:23.77KB
输入输出保护.docx
《输入输出保护.docx》由会员分享,可在线阅读,更多相关《输入输出保护.docx(25页珍藏版)》请在冰豆网上搜索。
输入输出保护
九.输入/输出保护
为了支持多任务,80386不仅要有效地实现任务隔离,而且还要有效地控制各任务的输入/输出,避免输入/输出冲突。
本文将介绍输入输出保护。
这里下载本文源代码。
<一>输入/输出保护
80386采用I/O特权级IPOL和I/O许可位图的方法来控制输入/输出,实现输入/输出保护。
1.I/O敏感指令
输入输出特权级(I/OPrivilegeLevel)规定了可以执行所有与I/O相关的指令和访问I/O空间中所有地址的最外层特权级。
IOPL的值在如下图所示的标志寄存器中。
标 志
寄存器
BIT31—BIT18
BIT17
BIT16
BIT15
BIT14
BIT13—BIT12
BIT11
BIT10
BIT9
BIT8
BIT7
BIT6
BIT5
BIT4
BIT3
BIT2
BIT1
BIT0
00000000000000
V
M
R
F
0
N
T
IOPL
OF
D
F
I
F
T
F
S
F
Z
F
0
A
F
0
P
F
1
C
F
I/O许可位图规定了I/O空间中的哪些地址可以由在任何特权级执行的程序所访问。
I/O许可位图在任务状态段TSS中。
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位图许可
上表所列指令称为I/O敏感指令,由于这些指令与I/O有关,并且只有在满足所列条件时才可以执行,所以把它们称为I/O敏感指令。
从表中可见,当前特权级不在I/O特权级外层时,可以正常执行所列的全部I/O敏感指令;当特权级在I/O特权级外层时,执行CLI和STI指令将引起通用保护异常,而其它四条指令是否能够被执行要根据访问的I/O地址及I/O许可位图情况而定(在下面论述),如果条件不满足而执行,那么将引起出错码为0的通用保护异常。
由于每个任务使用各自的EFLAGS值和拥有自己的TSS,所以每个任务可以有不同的IOPL,并且可以定义不同的I/O许可位图。
注意,这些I/O敏感指令在实模式下总是可执行的。
2.I/O许可位图
如果只用IOPL限制I/O指令的执行是很不方便的,不能满足实际要求需要。
因为这样做会使得在特权级3执行的应用程序要么可访问所有I/O地址,要么不可访问所有I/O地址。
实际需要与此刚好相反,只允许任务甲的应用程序访问部分I/O地址,只允许任务乙的应用程序访问另一部分I/O地址,以避免任务甲和任务乙在访问I/O地址时发生冲突,从而避免任务甲和任务乙使用使用独享设备时发生冲突。
因此,在IOPL的基础上又采用了I/O许可位图。
I/O许可位图由二进制位串组成。
位串中的每一位依次对应一个I/O地址,位串的第0位对应I/O地址0,位串的第n位对应I/O地址n。
如果位串中的第位为0,那么对应的I/O地址m可以由在任何特权级执行的程序访问;否则对应的I/O地址m只能由在IOPL特权级或更内层特权级执行的程序访问。
如果在I/O外层特权级执行的程序访问位串中位值为1的位所对应的I/O地址,那么将引起通用保护异常。
I/O地址空间按字节进行编址。
一条I/O指令最多可涉及四个I/O地址。
在需要根据I/O位图决定是否可访问I/O地址的情况下,当一条I/O指令涉及多个I/O地址时,只有这多个I/O地址所对应的I/O许可位图中的位都为0时,该I/O指令才能被正常执行,如果对应位中任一位为1,就会引起通用保护异常。
80386支持的I/O地址空间大小是64K,所以构成I/O许可位图的二进制位串最大长度是64K个位,即位图的有效部分最大为8K字节。
一个任务实际需要使用的I/O许可位图大小通常要远小于这个数目。
当前任务使用的I/O许可位图存储在当前任务TSS中低端的64K字节内。
I/O许可位图总以字节为单位存储,所以位串所含的位数总被认为是8的倍数。
从前文中所述的TSS格式可见,TSS内偏移66H的字确定I/O许可位图的开始偏移。
由于I/O许可位图最长可达8K字节,所以开始偏移应小于56K,但必须大于等于104,因为TSS中前104字节为TSS的固定格式,用于保存任务的状态。
1.I/O访问许可检查细节
保护模式下处理器在执行I/O指令时进行许可检查的细节如下所示。
(1)若CPL<=IOPL,则直接转步骤(8);
(2)取得I/O位图开始偏移;
(3)计算I/O地址对应位所在字节在I/O许可位图内的偏移;
(4)计算位偏移以形成屏蔽码值,即计算I/O地址对应位在字节中的第几位;
(5)把字节偏移加上位图开始偏移,再加1,所得值与TSS界限比较,若越界,则产生出错码为0的通用保护故障;
(6)若不越界,则从位图中读对应字节及下一个字节;
(7)把读出的两个字节与屏蔽码进行与运算,若结果不为0表示检查未通过,则产生出错码为0的通用保护故障;
(8)进行I/O访问。
设某一任务的TSS段如下:
TSSSEGSEGMENTPARAUSE16
TSS<>;TSS低端固定格式部分
DB8DUP(0);对应I/O端口00H—3FH
DB10000000B;对应I/O端口40H—47H
DB01100000B;对用I/O端口48H—4FH
DB8182DUP(0ffH);对应I/O端口50H—0FFFFH
DB0FFH;位图结束字节
TSSLen=$
TSSSEGENDS
再假设IOPL=1,CPL=3。
那么如下I/O指令有些能正常执行,有些会引起通用保护异常:
inal,21h;
(1)正常执行
inal,47h;
(2)引起异常
out20h,al;(3)正常实行
out4eh,al;(4)引起异常
inal,20h;(5)正常执行
out20h,eax;(6)正常执行
out4ch,ax;(7)引起异常
inax,46h;(8)引起异常
ineax,42h;(9)正常执行
由上述I/O许可检查的细节可见,不论是否必要,当进行许可位检查时,80386总是从I/O许可位图中读取两个字节。
目的是为了尽快地执行I/O许可检查。
一方面,常常要读取I/O许可位图的两个字节。
例如,上面的第(8)条指令要对I/O位图中的两个位进行检查,其低位是某个字节的最高位,高位是下一个字节的最低位。
可见即使只要检查两个位,也可能需要读取两个字节。
另一方面,最多检查四个连续的位,即最多也只需读取两个字节。
所以每次要读取两个字节。
这也是在判别是否越界时再加1的原因。
为此,为了避免在读取I/O许可位图的最高字节时产生越界,必须在I/O许可位图的最后填加一个全1的字节,即0FFH。
此全1的字节应填加在最后一个位图字节之后,TSS界限范围之前,即让填加的全1字节在TSS界限之内。
I/O许可位图开始偏移加8K所得的值与TSS界限值二者中较小的值决定I/O许可位图的末端。
当TSS的界限大于I/O许可位图开始偏移加8K时,I/O许可位图的有效部分就有8K字节,I/O许可检查全部根据全部根据该位图进行。
当TSS的界限不大于I/O许可位图开始偏移加8K时,I/O许可位图有效部分就不到8K字节,于是对较小I/O地址访问的许可检查根据位图进行,而对较大I/O地址访问的许可检查总被认为不可访问而引起通用保护故障。
因为这时会发生字节越界而引起通用保护异常,所以在这种情况下,可认为不足的I/O许可位图的高端部分全为1。
利用这个特点,可大大节约TSS中I/O许可位图占用的存储单元,也就大大减小了TSS段的长度。
<二>重要标志保护
输入输出的保护与存储在标志寄存器EFLAGS中的IOPL密切相关,显然不能允许随便地改变IOPL,否则就不能有效地实现输入输出保护。
类似地,对EFLAGS中的IF位也必须加以保护,否则CLI和STI作为敏感指令对待是无意义的。
此外,EFLAGS中的VM位决定着处理器是否按虚拟8086方式工作。
80386对EFLAGS中的这三个字段的处理比较特殊,只有在较高特权级执行的程序才能执行IRET、POPF、CLI和STI等指令改变它们。
下表列出了不同特权级下对这三个字段的处理情况。
不同特权级对
标志寄存器特
殊字段的处理
特权级
VM标志字段
IOPL标志字段
IF标志字段
CPL=0
可变(初POPF指令外)
可变
可变
0
不变
不变
可变
CPL>IOPL
不变
不变
不变
从表中可见,只有在特权级0执行的程序才可以修改IOPL位及VM位;只能由相对于IOPL同级或更内层特权级执行的程序才可以修改IF位。
与CLI和STI指令不同,在特权级不满足上述条件的情况下,当执行POPF指令和IRET指令时,如果试图修改这些字段中的任何一个字段,并不引起异常,但试图要修改的字段也未被修改,也不给出任何特别的信息。
此外,指令POPF总不能改变VM位,而PUSHF指令所压入的标志中的VM位总为0。
<三>演示输入输出保护的实例(实例九)
下面给出一个用于演示输入输出保护的实例。
演示内容包括:
I/O许可位图的作用、I/O敏感指令引起的异常和特权指令引起的异常;使用段间调用指令CALL通过任务门调用任务,实现任务嵌套。
1.演示步骤
实例演示的内容比较丰富,具体演示步骤如下:
(1)在实模式下做必要准备后,切换到保护模式;
(2)进入保护模式的临时代码段后,把演示任务的TSS段描述符装入TR,并设置演示任务的堆栈;
(3)进入演示代码段,演示代码段的特权级是0;
(4)通过任务门调用测试任务1。
测试任务1能够顺利进行;
(5)通过任务门调用测试任务2。
测试任务2演示由于违反I/O许可位图规定而导致通用保护异常;
(6)通过任务门调用测试任务3。
测试任务3演示I/O敏感指令如何引起通用保护异常;
(7)通过任务门调用测试任务4。
测试任务4演示特权指令如何引起通用保护异常;
(8)从演示代码转临时代码,准备返回实模式;
(9)返回实模式,并作结束处理。
2.源程序组织和清单
为了达到演示目的,实例除了演示任务外,还涉及四个测试任务和一个通用保护故障处理任务。
实例由如下几部分组成。
(1)全局描述符表GDT和中断描述符表IDT;
(2)其它中断/异常处理程序代码段;
(3)通用保护故障处理任务的任务状态段、堆栈段和代码段;
(4)四个测试任务合用的任务状态段、堆栈段和代码段;
(5)演示任务的任务状态段、堆栈段和代码段;
(6)演示任务的临时代码段;
(7)实模式下执行的启动与结束程序代码段和数据段。
实例九源程序清单如下:
;名称:
ASM9.ASM
;功能:
演示I/O保护及I/O敏感指令的作用
;编译:
TASMASM9.ASM
;连接:
TLINK/32ASM9.OBJ
;----------------------------------------------------------------------------
INCLUDE386SCD.INC
;----------------------------------------------------------------------------
GDTSegSEGMENTPARAUSE16;全局描述符表段(16位)
GDTLABELBYTE
;空描述符
DUMMYDesc<>
;规范段描述符及选择子
NormalDesc<0ffffh,,,ATDW,,>
Normal_Sel=Normal-GDT
;视频缓冲区段描述符(DPL=3)及选择子(任何特权级可写)
VideoBufDesc<07fffh,8000h,0bh,ATDW,,>
VideoBuf_Sel=VideoBuf-GDT
;----------------------------------------------------------------------------
EFFGDTLABELBYTE
;演示任务TSS段描述符及选择子
DemoTSSDesc
DemoTSS_Sel=DemoTSS-GDT
;演示任务堆栈段描述符及选择子
DemoStackDesc
DemoStack_Sel=DemoStack-GDT
;演示代码段描述符及选择子
DemoCodeDesc
DemoCode_Sel=DemoCode-GDT
;属于演示任务的临时代码段描述符及选择子
TempCodeDesc<0ffffh,TempCodeSeg,,ATCE,,>
TempCode_Sel=TempCode-GDT
;指向GDT的存储段描述符及选择子
ToGDTDesc
ToGDT_Sel=ToGDT-GDT
;指向通用保护故障处理任务TSS的存储段描述符及选择子
ToGPTSSDesc
ToGPTSS_Sel=ToGPTSS-GDT
;指向测试任务TSS的存储段描述符及选择子
ToTestTSSDesc
ToTestTSS_Sel=ToTestTSS-GDT
;测试任务TSS段描述符及选择子
TestTSSDesc
TestTSS_Sel=TestTSS-GDT
;测试任务1堆栈段描述符(DPL=1)及选择子
Test1StackDesc
Test1Stack_Sel=Test1Stack-GDT+RPL1
;测试任务1代码段描述符(DPL=1)及选择子
Test1CodeDesc
Test1Code_Sel=Test1Code-GDT+RPL1
;测试任务2堆栈段描述符(DPL=2)及选择子
Test2StackDesc
Test2Stack_Sel=Test2Stack-GDT+RPL2
;测试任务2代码段描述符(DPL=2)及选择子
Test2CodeDesc
Test2Code_Sel=Test2Code-GDT+RPL2
;测试任务3堆栈段描述符(DPL=3)及选择子
Test3StackDesc
Test3Stack_Sel=Test3Stack-GDT+RPL3
;测试任务3代码段描述符(DPL=3)及选择子
Test3CodeDesc
Test3Code_Sel=Test3Code-GDT+RPL3
;通用保护故障处理任务的TSS段描述符及选择子
GPTSSDesc
GPTSS_Sel=GPTSS-GDT
;通用保护故障处理任务的堆栈段描述符及选择子
GPStackDesc
GPStack_Sel=GPStack-GDT
;通用保护故障处理任务的代码段描述符及选择子
GPCodeDesc
GPCode_Sel=GPCode-GDT
;其它中断或异常处理程序代码段(一致可读)描述符及选择子
ErrCodeDesc
ErrCode_Sel=ErrCode-GDT
;----------------------------------------------------------------------------
GDNum=($-EFFGDT)/(SIZEDesc);需处理基地址的描述符个数
;----------------------------------------------------------------------------
;指向测试任务的任务门
TestTaskGate<,TestTSS_Sel,,ATTaskGate,>
Test_Sel=TestTask-GDT
;----------------------------------------------------------------------------
GDTLen=$-GDT;全局描述符表长度
GDTSegENDS;全局描述符表段定义结束
;----------------------------------------------------------------------------
IDTSegSEGMENTPARAUSE16;中断描述符表段(16位)
IDTLABELBYTE;中断描述符表
REPT13
Gate
ENDM
Gate<,GPTSS_Sel,,ATTaskGate,>;通用故障处理程序门描述符
REPT242
Gate
ENDM
;----------------------------------------------------------------------------
IDTLen=$-IDT
;----------------------------------------------------------------------------
IDTSegENDS;中断描述符表段定义结束
;----------------------------------------------------------------------------
;其它中断或异常处理程序的代码段(一致可读)
;----------------------------------------------------------------------------
ErrCodeSegSEGMENTPARAUSE32
ASSUMECS:
ErrCodeSeg
;----------------------------------------------------------------------------
ErrMessDB'Error!
!
!
'
ErrMessLen=$-ErrMess
;----------------------------------------------------------------------------
ErrBeginPROCFAR
cld
movax,ErrCode_Sel
movds,ax
leaesi,ErrMess
movax,VideoBuf_Sel
moves,ax
movedi,1992
movecx,ErrMessLen
movah,4eh
Err1:
lodsb
stosw
loopErr1
jmp$
ErrBeginENDP
;----------------------------------------------------------------------------
ErrCodeLen=$
ErrCodeSegENDS
;----------------------------------------------------------------------------
GPTSSSegSEGMENTPARAUSE16;通用保护故障处理任务的TSS
GPTaskSSLABELBYTE
DD0;任务嵌套时的链接指针
DD0;0级堆栈偏移
DW0,0;0级堆栈选择子
DD0;1级堆栈偏移
DW0,0;1级堆栈选择子
DD0;2级堆栈偏移
DW0,0;2级堆栈选择子
DD0;CR3
DWGPBegin,0;EIP
DD0;EFLAGS
DD0;EAX
DD0;ECX
DD0;EDX
DD0;EBX
DDGPStackLen;ESP
DD0;EBP
DD0;ESI
DD0;EDI
DWVideoBuf_Sel,0;ES
DWGPCode_Sel,0;CS
DWGPStack_Sel,0;SS
DWToTestTSS_Sel,0;DS
DWToGPTSS_Sel,0;FS
DW0,0;GS
DW0,0;LDTR
DW0;调试陷阱标志
DW$+2;指向I/O许可位图的偏移
DB0ffh;I/O许可位图结束标志
GPTSSLen=$
GPTSSSegENDS
;----------------------------------------------------------------------------
GPStackSegSEGMENTPARAUSE32;通用保护故障处理任务堆栈段
GPStackLen=512
DBGPStackLenDUP(0)
GPStackSegENDS
;----------------------------------------------------------------------------
;通用保护故障处理程序代码段
;--------------------------------------------------------
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 输入输出 保护