您的位置:首页 > 其它

转:80386的保护机制

2013-03-06 13:18 176 查看
摘自罗云彬的《Windows环境下32位汇编语言程序设计》

80386采用保护机制主要为了检查和防止低级别代码的越权操作,如访问不该访问的数据、端口以及调用高优先级的代码等。保护机制主要由下列几方面组成:

● 段的类型检查——段的类型是由段描述符指定的,主要属性有是否可执行,是否可读和是否可写等。而CS,DS和SS等段选择器是否能装入某种类型的段描述符是有限制的。如不可执行的段不能装入CS;不可读的段不能装入DS与ES等数据段寄存器;不可写的段不能装入SS等。如果段类型检查通不过,则处理器会产生一般性保护异常或堆栈异常。

● 页的类型检查——除了可以在段级别上指定整个段是否可读写外,在页表中也可以为每个页指定是否可写。对于特权级下的执行代码,所有的页都是可写的。但对于1,2和3级的代码,还要根据页表中的R/W项决定是否可写,企图对只读的页进行写操作会产生页异常。

● 访问数据时的级别检查——优先级低的代码不能访问优先级高的数据段。80386的段描述符中有一个DPL域(描述符优先级),表示这个段可以被访问的最低优先级。而段选择器中含有RPL域(请求优先级),表示当前执行代码的优先级。只有DPL在数值上大于或等于RPL值的时候,该段才是可以访问的,否则会产生一般性保护异常。

● 控制转移的检查——在处理器中,有很多指令可以实现控制转移,如jmp,call,ret,int和iret等指令。但优先级低的代码不能随意转移到优先级高的代码中,所以遇到这些指令的时候,处理器要检查转移的目的位置是否合法。

● 指令集的检查——有两类指令可以影响保护机制。第一类是改变GDT,LDT,IDT以及控制寄存器等关键寄存器的指令,称为特权指令;第二类是操作I/O端口的指令以及cli和sti等改变中断允许的指令,称为敏感指令。试想一下,如果用户级程序可以用sti禁止一切中断(包括时钟中断),那么整个系统就无法正常运行,所以这些指令的运行要受到限制。特权指令只能在优先级0上才能运行,而敏感指令取决于eflags寄存器中的IOPL位。只有IOPL位表示的优先级高于等于当前代码段的优先级时,指令才能执行。

● I/O操作的保护——I/O地址也是受保护的对象。因为通过I/O操作可以绕过系统对很多硬件进行控制。80386可以单独为I/O空间提供保护,每个任务有个TSS(任务状态段)来记录任务切换的信息。TSS中有个I/O允许位图,用来表示对应的I/O端口是否可以操作。某个I/O地址在位图中的对应数据位为0则表示可以操作;如果为1则还要看eflags中的IPOL位,这时只有IOPL位表示的优先级高于等于当前代码段的优先级,才允许访问该I/O端口。

3. Windows的保护机制

在Windows下,操作系统运行于0级,应用程序运行于3级。因为Alpha计算机只支持两个优先级,为了便于将应用程序移植到Alpha计算机上,Windows操作系统不使用1和2级这两个优先级。

Windows操作系统充分利用80386的保护机制,所有和操作系统密切相关的东西都是受保护的。运行于优先级3上的用户程序有很多限制,只有在写VxD等驱动程序的时候才可以使用全部资源。在Win32汇编编程中要注意避免以下的越权操作(当然写驱动程序不在此列):

● 显而易见,所有的特权指令都是不可执行的,如lgdt,lldt,lidt指令和对CRx与TRx等寄存器赋值。但是,读取重要寄存器的指令是可以执行的,如sgdt,sldt和sidt等。

● Windows在页表中把代码段和数据段中的内存页赋予不同的属性。代码段是不可写的,数据段中也只有变量部分的页面是可写的。所以虽然可以寻址所有的4 GB空间,但访问超出权限规定以外的东西还是会引发保护异常。

● 在Windows 98中,系统硬件用的I/O端口是受保护的,但其余的则可以操作。如果用户在机器中插了一块自己的卡,用的是300h等系统未定义的端口,那么在应用程序中就可以直接操作,但要操作3f8h(串口)和1f0h(硬盘端口)等系统已定义的端口就不行了。在Windows NT中,任何的端口操作都是不允许的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: