保护模式及其编程
- 格式:ppt
- 大小:182.50 KB
- 文档页数:35
在IA32下,CPU有两种工作模式:实模式和保护模式。
在实模式下,段寄存器含有段值,为访问存储器形成物理地址时,处理器引用相应的某个段寄存器并将其值乘以16,形成20位的段基地址。
计算公式如下:物理地址= 段值*16 + 偏移其中段值和偏移都是16位的,这样通过“段:偏移”的方式达到了1MB的寻址能力。
在保护模式下,寄存器是32位的,但是为了兼容性,地址仍然用“段:偏移”的方式来表示,只不过这时的保护模式下的“段”的概念已经发生了根本的改变,虽然段值仍然由原来的cs、ds等寄存器表示,但是此时它仅仅是一个索引,叫做选择子,指向一个数据结构(叫做GDT,Global Descriptor Table全局描述符表或者LDT,Local Descriptor Table局部描述符表)的一个表项(叫做Descriptor描述符)。
1.全局描述符表寄存器GDTR(/u/16292/showart_396896.html)GDTR长48位,其中高32位为基地址,低16位为界限。
由于GDT 不能有GDT本身之内的描述符进行描述定义,所以处理器采用GDTR为GDT这一特殊的系统段提供一个伪描述符。
GDTR给定了GDT,如下图所示。
GDTR中的段界限以字节为单位。
由于段选择子中只有13位作为描述符索引,而每个描述符长8个字节,所以用16位的界限足够。
2.局部描述符表寄存器LDTR局部描述符表寄存器LDTR规定当前任务使用的局部描述符表LDT。
LDTR类似于段寄存器,由程序员可见的16位的寄存器和程序员不可见的高速缓冲寄存器组成。
实际上,每个任务的局部描述符表LDT作为系统的一个特殊段,由一个描述符描述。
而用于描述符LDT 的描述符存放在GDT中。
在初始化或任务切换过程中,把描述符对应任务LDT的描述符的选择子装入LDTR,处理器根据装入LDTR可见部分的选择子,从GDT中取出对应的描述符,并把LDT的基地址、界限和属性等信息保存到LDTR的不可见的高速缓冲寄存器中。
80X86保护模式及其编程(⼀)80x86系统寄存器和系统指令1、标志寄存器(EFLAGS)标志寄存器EFLAGS的标志位含义如下图:TF 位8是跟踪标志(Trace flag),当设置该位时可为调试操作启动单步执⾏⽅式。
复位时则禁⽌单步执⾏。
在单步执⾏⽅式下,处理器会在每个指令执⾏后产⽣⼀个调试异常,这样我们可以观察执⾏程序在每条指令执⾏后的状态。
IOPL 位13-12时I/O特权级(I/O Privilege Level)字段。
该字段指明当前运⾏程序或任务的I/O特权级别IOPL。
当前任务或程序的CPL必须⼩于这个IOPL才能访问I/O地址空间。
只有当CPL位特权级0时,程序才可以使⽤POPF或IRET指令修改这个字段,IOPL也是控制对IF标志修改的机制之⼀NT 位14是嵌套任务标志(Nested Task)。
它控制着被中断任务和调⽤任务之间的链接关系。
在使⽤CALL指令、中断或异常执⾏任务调⽤时,处理器会设置该标志,在通过IRET指令从⼀个任务返回时,处理器会检查并修改这个NT标志。
使⽤POPF/POPFD指令也可以修改这个标志,但是在应⽤程序中改变这个标志的状态会产⽣不可意料的异常RF 位16时恢复标志(Resume Flag)。
该标志⽤于控制处理器对断点指令的响应。
当设置时,这个标志会临时禁⽌断点指令产⽣调试异常;当标志复位时,则断点指令将会产⽣异常。
RF的主要功能是允许调试异常后重⾏执⾏⼀条指令。
当调试软件使⽤IRETD指令返回被中断程序之前,需要设置堆栈上EFLAGS内容中的RF标志,以防⽌指令断点造成另⼀个异常,处理器会在指令返回之后⾃动清除该标志,从⽽再次允许指令断点异常。
VM位17是虚拟-8086⽅式标志,当设置该标志时,新开启虚拟-8086⽅式,当复位该标志时,则回到保护模式内存管理寄存器处理器提供了4个内存管理寄存器(GDTR、LDTR、IDTR和TR),⽤于指定分段内存管理所使⽤的系统表的基地址,其中包含有分段机制的重要信息。
保护模式详解在ia32下,cpu有两种⼯作模式:实模式和保护模式。
在实模式下,16位的寄存器⽤“段+偏移”的⽅法计算有效地址。
段寄存器始终是16位的。
在实模式下,段值xxxxh表⽰的以xxxx0h开始的⼀段内存。
但在保护模式下,段寄存器的值变成了⼀个索引(还有附加信息)这个索引指向了⼀个数据结构的表(gdt/ldt)项,表项(描述符)中详细定义了段的其实地址、界限、属性等内容。
保护模式需要理解:描述符,选择⼦描述符包括,存储段描述符(代码段,数据段,堆栈段),系统描述符(任务状态段TSS,局部描述符表LDT),门描述符(调⽤门,任务门,中断门,陷阱门),下⾯以存储段描述符位例我们看⼀下描述符的结构:描述符共8个字节:0,1字节是段界限(2字节)2,3,4字节是段基址的低24位(3字节)5,6字节是段基址的属性(2字节)7字节是段机制的⾼8位(1字节)属性:(1) P:存在(Present)位。
P=1 表⽰描述符对地址转换是有效的,或者说该描述符所描述的段存在,即在内存中;P=0 表⽰描述符对地址转换⽆效,即该段不存在。
使⽤该描述符进⾏内存访问时会引起异常。
(2) DPL: 表⽰描述符特权级(Descriptor Privilege level),共2位。
它规定了所描述段的特权级,⽤于特权检查,以决定对该段能否访问。
(3) DT:说明描述符的类型。
对于存储段描述符⽽⾔,DT=1,以区别与系统段描述符和门描述符(DT=0)。
(4) TYPE: 说明存储段描述符所描述的存储段的具体属性。
数据段类型类型值说明----------------------------------0只读1只读、已访问2读/写3读/写、已访问4只读、向下扩展5只读、向下扩展、已访问6读/写、向下扩展7读/写、向下扩展、已访问选择⼦的结构:RPL(Requested Privilege Level): 请求特权级,⽤于特权检查。
保护模式知识序!对于学习任何编程语言的朋友来说掌握CPU的操作模式都是一件非常重要的事,其中就数保护模式这部分最重要了,现在关于保护模式的中文资料就只有杨季文先生那一家还算全面,但有些人还是觉得看不太懂,为此我就写了这篇文章,看看是否对您的胃口!一、保护模式概述顾名思义,就是对程序的运行加以保护。
我们知道在实模式下通常只能寻址1M的内存空间,且只能是单任务,就是说同一时间不能有两个任务被激活。
从8086/8088的20根地址线,80286的24根地址线到80386的32根地址线,直至今天Puntium4已经发展到了36根地址线,它们分别可以寻址1M、16M、4G、64G的内存空间,然而在实模式下,通常的寻址范围还是1M。
也就是对于在纯DOS下运行的Puntium4也只能是一个快速的8086。
前面已经说了,保护模式就是对程序的运行加以保护,所以说保护模式较实模式的增强的最主要体现还不是寻址能力而是对多任务的支持,所提到的保护就是对不同任务间和同一任务内的程序加以保护,使它们的运行不受对方“有意”或“无意”影响,但同时也要对两个任务都要用到的部分代码实现共享。
另外一个重要的增强就是对虚拟存储器的支持,从一定意义上说可以使程序设计人员不必考虑物理内存的大小。
有了新的模式,当然要有大量的新增寄存器的支持,学习这些寄存器也是学习保护模式的关键.新增寄存器如下:注:不可见的寄存器用红色标明,在后面会有讲解.以上这些都是要在后面讲到的,并且还会讲一下扩展的保护模式和扩展的V86模式!三个重要的系统表GDT、LDT和IDT首先说明的是,这三个表是在内存中由操作系统或系统程序员所建,并不是固化在哪里,所以从理论上是可以被读写的。
这三个表都是描述符表.描述符表是由若干个描述符组成,每个描述符占用8个字节的内存空间,每个描述符表内最多可以有8129个描述符.描述符是描述一个段的大小,地址及各种状态的.描述符表有三种,分别为全局描述符表GDT、局部描述符表LDT和中断描述符表IDT。
进⼊保护模式完整代码(汇编)⼀开始使⽤C编写进⼊PM代码,因为内嵌汇编太多,不易查询汇编如何出错,所以改⽤纯汇编编写。
过程中学到⼀个⼩技巧,当赋值的数太⼤时,编译会报错,这时在数前加个0即可解决。
程序编译完成,基本过程已然了解,但是在测试机上跑的时候会⾃动重启。
;;;;;;;;;;;;;;;;;;;程序开始;;;;;;;;;;;;;;;;;;;data structjump macro selector, offsetdb 0eahdw offsetdw selectorendmdesp strucsegLimit dw 0; byte0, 1segBaseLow dw 0; byte2, 3segBaseMid db 0; byte4segAttribute dw 0; byte5, 6segBaseHigh db 0; byte7desp endspgdt strucsegLimit dw 0ffffh; byte 0, 1segBase dd 0; byte 2, 3, 4, 5pgdt ends;--------------------------------------------------------------------; real mode data segment begin;.data.386p; if not p, lgdt is not defineddseg segment use16; gdt segment begingdt label byteDUMMY desp <>; 空描述符dataSegDesp desp <0ffffh,0h,0h,092h,> ; data segment isstarted with: 0x00000000hdataSegSel = dataSegDesp - gdtcodeSegDesp desp <0ffffh,,,098h,>codeSegSel = codeSegDesp - gdtextSegDesp desp <0ffffh,,88h,092h,> ; ext segment is started with: 0x00880000hextSegSel = extSegDesp - gdtgdtLen = $ - gdtpgdtr pgdt <gdtLen-1, >; gdt segment end; pmode data segment beginbuffers db 256 dup('@')bufferLen = $ - offset buffersmsgLen = $ - offset msg; pmode data segment endbufferd db 256 dup('y')bufferd2 db 256 dup('x')dseg ends; real mode data segment end;--------------------------------------------------------------------cseg segment use16;.codeassume cs:cseg, ds:dsegstart:MOV ax, dsegMOV ds, ax;prepare to jump to pmode;1>. init gdtr;2>. init code descriptor;3>. init data descriptor;4>. enable a20 address;5>. set cr0;6>. jump pmode;1>. init gdtrMOV bx, 16MUL bxADD ax, offset gdtADC dx, 0MOV WORD PTR pgdtr.segBase, ax MOV WORD PTR pgdtr.segBase+2, dx ;2>. init code descriptorMOV ax, csMUL bxMOV codeSegDesp.segBaseLow, ax MOV codeSegDesp.segBaseMid, dl MOV codeSegDesp.segBaseHigh, dh ;3>. init data descriptorMOV ax, dsMUL bxADD ax, offset buffersadc dx, 0MOV dataSegDesp.segBaseLow, ax MOV dataSegDesp.segBaseMid, dl MOV dataSegDesp.segBaseHigh, dh lgdt pgdtr;4>. enable A20 addresscli;call enableA20PUSH axin al, 92hor al, 2out 92h, alPOP ax;5>. set cr0MOV eax, cr0or eax, 1MOV cr0, eax;6>. jump to pmode;JMP pmodejump <codeSegSel>,<offset pmode> pmode:MOV ax, dataSegSelMOV ds, axMOV ax, extSegSelMOV es, ax;;;;;;;访问SPI空间的内容;;;;;;;;;mov ebx,[0fed1f800h]mov ds:[0000],ebxmov dx,0mov ah,9int 21h ;;;;;;;;;;;;;;;;MOV eax, cr0and eax, 0fffffffehMOV cr0, eaxJMP rmodermode:call disableA20stiMOV ax, dsegMOV ds, axdisableA20 procPUSH axin al, 92hand al, 0fdhout 92h, alPOP axRETdisableA20 endpMOV ah, 4ch int 21h cseg ends END start。
保护模式汇编实例
保护模式(Protected Mode)是x86架构的一种工作模式,在这种模式下,操作系统可以更好地保护硬件资源,防止软件对硬件的非法访问。
下面是一个简单的x86汇编语言程序,演示如何在保护模式下进行简单的内存操作。
```assembly
section .data
msg db 'Hello, World!', 0
section .text
global _start
_start:
; 进入保护模式
mov eax, cr0
or eax, 0x1
mov cr0, eax
; 跳转到保护模式代码段
mov ebx, 0x1000 ; 段地址
mov ecx, 0x10 ; 偏移量
call ebx
_exit:
; 退出保护模式
mov eax, cr0
and eax, 0xfffffffe
mov cr0, eax
; 退出程序
mov eax, 1 ; 系统调用号(sys_exit)
xor ebx, ebx ; 返回值
int 0x80 ; 中断0x80
```
在上面的程序中,首先将cr0寄存器的值设置为1,表示进入保护模式。
然后,通过调用0x10段的代码来执行保护模式下的代码。
在这个例子中,只是简单地显示一条“Hello, World!”的消息。
最后,将cr0寄存器的值设置为0,表示退出保护模式,并使用系统调用号1来退出程序。
保护模式汇编入门1.引言1.1 概述概述保护模式汇编是一种计算机编程语言,用于在计算机系统的保护模式下编写程序。
保护模式是一种操作系统提供的模式,它能够提供更高的系统资源访问权限和更强大的功能,相比实模式和其他模式,保护模式具有更大的内存地址空间和更多的指令集。
随着计算机技术的发展,保护模式汇编已经成为了程序员必备的工具之一。
它不仅可以用于编写高效的操作系统内核,还可以用于编写底层设备驱动程序和系统工具。
在保护模式汇编中,可以直接访问内存和硬件设备,并且能够利用专门的指令和特性来提高程序的性能和效率。
保护模式汇编的学习曲线较为陡峭,需要对计算机系统的底层原理有一定的了解。
首先,需要熟悉汇编语言的语法和特性,包括寄存器、指令、标志位等的使用。
其次,需要了解保护模式的特点和限制,比如段机制、特权级和中断处理等。
最后,需要学习如何通过汇编语言来编写具体的程序,包括如何访问内存、处理中断和异常等。
在本文中,我们将介绍保护模式汇编的基本概念和特点。
首先,我们将详细解释什么是保护模式汇编,以及它与其他模式的区别。
然后,我们将介绍保护模式汇编的特点,包括扩展的内存地址空间、多任务处理和特权级机制。
最后,我们将总结保护模式汇编的重要性,并展望它的未来发展。
通过本文的学习,读者将能够了解保护模式汇编的基本知识,并能够开始编写简单的保护模式汇编程序。
1.2 文章结构文章结构部分的内容可以包括以下内容:在本文中,我们将按照以下结构来进行讲解和介绍保护模式汇编的相关知识:1. 引言:首先,我们将通过一个概述来引入本文的主题,简要介绍保护模式汇编的基本概念和其在计算机系统中的重要性。
接着,我们会说明本文的结构和目的,为读者提供一个整体的导读。
2. 正文:在正文部分,我们将详细介绍保护模式汇编的基本概念和特点。
首先,我们会解释什么是保护模式汇编,并对其与实模式汇编的区别进行对比。
然后,我们将深入探讨保护模式汇编的特点,如分段机制、特权级和中断处理等方面的内容。
探寻cpu保护模式保护模式是自80386以来x86系列处理器一直沿用的工作模式。
保护模式,概括的介绍为保护多任务之间代码访问的完全隔离,规范单任务的用户代码和系统代码的访问格式,限制程序访问数据的自由性,使计算更加安全的进行。
本文将介绍保护方式的体系结构,以及保护模式工作原理,并与实模式的工作方式进行对比,介绍存储管理,地址转换以及多任务之间的联系及隔离的原理以及其实现的保护方式,深入了解处理器保护模式。
一、存储管理与地址转换保护方式下的存储管理与地址转换相对于实模式而言,虚拟实现较大的地址访问空间,对实现虚拟存储器提供硬件支持。
那么保护模式下,处理器是通过什么样具体的内存管理模式实现该种优点?在实模式下,内存地址的访问是通过(段基地址:偏移量)的方式来进行的,偏移量是相对于此段基地址而言。
基地址+偏移量得到一个内存绝对地址。
由此,我们可以看出,一个段具备两个因素:段基地址+段的最大长度,而对一个内存地址的访问,则是通过确定访问的段以及相对于这个段的偏移量,从而得到实际访问的内存地址。
在保护模式下,内存的管理模式分为两种,段模式和页模式,事实上保护模式的内存管理模式是:纯段模式和段页式。
用段模式的方式来说明保护模式下内存管理的方式。
因此在段管理模式下仍然采用的是(段基地址:偏移量)的方式。
运行在32位系统的保护模式,那么影响段值的两个因素即基地址以及偏移地址也都是32位的。
IA-32允许将一个段的基地址设为32位所能表示的任何值,而不再是实时模式下,一个段的基地址只能是16的倍数,而一个段的限定大小只能为固定值64 KB。
另外,保护模式下要为段模式提供了保护机制,也就说一个段的描述符需要规定对自身的访问权限。
所以,在保护模式下,对一个段的描述则包括3方面因素:基地址,限定段大小,权限,它们加在一起被放在一个64位长的数据结构中,被称为段描述符(GDT)。
这种情况下,段地址转换如图(1)如果我们直接通过一个64位段描述符来引用一个段的时候,就必须使用一个64位长的段寄存器装入这个段描述符。