标签:
设计用于系统编程的系统寄存器主要包括以下几类:
标志寄存器EFLAGS, 内存管理寄存器, 控制寄存器, 调试寄存器, 测试寄存器。
系统标志寄存器EFLAGS 控制着I/O、可屏蔽中断、调试、任务切换以及保护模式和多任务环境下虚拟8086 程序的执行。
内存管理寄存器有4 个,用于分段内存管理:
• GDTR – 全局描述符表寄存器(Global Descriptor Table Register);
• LDTR – 局部描述符表寄存器(Local Descriptor Table Register);
• IDTR – 中断描述符表寄存器(Interrupt Descriptor Table Register);
• TR – 任务寄存器。
其中前两个寄存器(GDTR,LDTR)分别指向段描述符表GDT 和LDT。IDTR 寄存器指向中断向量表。TR寄存器指向处理器所需的当前任务的信息。
控制寄存器有4个,分别是CR0、CR1、CR2 和CR3。
控制寄存器CR0 含有系统整体的控制标志。其中:
• PE – 保护模式开启位(Protection Enable,比特位0)。如果设置了该比特位,就会使处理器开始在保护模式下运行。
• MP – 协处理器存在标志(Math Present,比特位1)。用于控制WAIT 指令的功能,以配合协处理的运行。
• EM – 仿真控制(Emulation,比特位2)。指示是否需要仿真协处理器的功能。
• TS – 任务切换(Task Switch,比特位3)。每当任务切换时处理器就会设置该比特位,并且在解释协处理器指令之前测试该位。
• ET – 扩展类型(Extention Type,比特位4)。该位指出了系统中所含有的协处理器类型(是80287 还是80387)。
• PG – 分页操作(Paging,比特位31)。该位指示出是否使用页表将线性地址变换成物理地址。
逻辑地址(Logical Address) 包含在机器语言指令中用来指定一个操作数或一条指令的地址。这种寻址方式在80x86著名的分段结构中表现得尤为具体,它促使windows 程序员把程序分成若干段。每个逻辑地址都由一个段和偏移量组成,偏移量指明了从段开始的地方到实际地址之间的距离。如:编译好的程序的入口地址可以看作是首地址,逻辑地址是在这个程序中,编译器为我们分配好的相对于这个首地址的偏移。逻辑地址是由一个段标识符加上一个指定段内相对地址的偏移量,表示为 [段标识符:段内偏移量])。总之,逻辑地址是相对于应用程序而言的。
线性地址(linear address)(也称虚拟地址 virtual address)是一个32位无符号整数,可以用来表示高达4GB的地址,线性地址通常用十六进制数字表示,值的范围从0x00000000到0xffffffff。
物理地址(physical address)用于内存芯片级内存单元寻址。它们与从微处理器的地址引脚按发送到内存总线上的电信号相对应。物理地址由32位或36位无符号整数表示。80x86 使用两步将一个分段形式的逻辑地址转换为实际物理内存地址。
• 段变换,将一个由段选择符和段内偏移构成的逻辑地址转换为一个线性地址;
• 页变换,将线性地址转换为对应的物理地址。该步是可选的。
在分页机制开启时,通过将前面所述的段转换和页转换组合在一起,即实现了从逻辑地址到物理地址的两个转换阶段。
段变换:
逻辑地址中的选择符部分是用于指定一描述符的,它是通过指定一描述符表并且索引其中的一个描 述符项完成的。选择符中的索引值(3bit位-15bit位)用于选择指定描述符中8192个描述符中的一个。处理器将该值乘以8,并加上描述符表的基地 址即可访问表中指定的段描述符。表指示器(TI,2bit位)用于指定选择符所引用的描述符表。0为GDT表,1为LDT表。请求特权级 (RPL,0-1bit位)用于保护机制。
所谓的描述符表分为两类:
GDT(全局描述符表)- 通过GDTR寄存器定位的,指令lgdt和sgdt用于访问GDTR寄存器,lgdt使用内存中一个6字节操作数来加载GDTR寄存器。头两个字节代表描述符长度, 后4字节是描述符表的基地址。
LDT(局部描述符表) - 通过LDTR寄存器定位的,指令lldt和sldt用于访问LDTR寄存器,用法基本与GDTR相同,不过lldt指令所使用的操作数却是一个2字节的操作数,表示全 局描述符表GDT中的一个描述符项的选择符。该选择符所对应的GDT表中的描述符项应该对应一个局部描述符表。
在描述符表中存放的是段描述符,段描述符有两种一般格式。取出描述符表中的基地址部分加上逻辑地址中的偏移值的结果,就是我们所需要的线性地址。
段寄存器:
处理器将描述符中的信息保存在段寄存器中,因而可以避免在每次访问内存时查询描述符表。每个段寄存器都有一个“可见”部分和一个“不可见”部分。这些段地址寄存器的可见部分是由程序来操作的,就好象它们只是简单的16 位寄存器。不可见部分则是由处理器来处理的。对这些寄存器的加载操作使用的是普通程序指令,这些指令可以分为两类:
1. 直接加载指令;例如,MOV,POP,LDS,LSS,LGS,LFS。这些指令显式地引用了指定的段寄存器。
2. 隐式加载指令;例如,远调用CALL 和远跳转JMP。这些指令隐式地引用了CS 段寄存器,并用新值加载到CS 中。
程序使用这些指令会把16 位的选择符加载到段寄存器的可见部分,而处理器则会自动地从描述符表中将一个描述符的基地址、段限长、类型以及其它信息加载到段寄存器中的不可见部分中去。
页变换:
页变换指的是将段变换形成的线性地址转化成内存中的物理地址。首先32位的线性地址被分为页目录项(22-31bit位),页表项(12-21bit位),页内偏移值(0-11bit位)。我们从CR3中获取页目录的基地址加上线性地址中的页目录项,从中获取到页表项的基地址再加上线性地址中的页表项就是我们所需要的页表项。页表项共32 位,其中12-31bit位为页框地址,我们把页框地址左移12bit位再加上页内偏移值,就得到该线性地址对应的逻辑地址了。
任务寄存器(Task Register – TR)的作用与一般段寄存器的类似,它通过指向TSS 来确定当前执行的任务。它也有16 位的可见部分和不可见部分。可见部分中的选择符用于在GDT 表中选择一个TSS描述符,处理器使用不可见部分来存放描述符中的基地址和段限长值。指令LTR 和STR 用于修改和读取任务寄存器中的可见部分,指令所使用的操作数是一16 位的选择符。LTR(Load task register)加载一个选择子操作数到任务寄存器的可见部分,这个选择子必须指定一个在GDT中的TSS描述符。LTR也用TSS中的信息来加载任务寄存器的不可见部分。LTR是一条特权指令,只能当CPL是0时才能执行这条执令。LTR一般是当操作系统初始化过程执行的,用来初始化任务寄存器。以后任务寄存器(TR)的内容由每次任务切换来改变。STR(Store task register)存储任务寄存器的可见部分到一个通用寄存器或者到一个内存的字内。STR不是特权指令。
在以下4 种情况下,CPU 会切换执行的任务:
1. 当前任务执行了一条引用TSS 描述符的JMP 或CALL 指令;
2. 当前任务执行了一条引用任务门的JMP 或CALL 指令;
3. 引用了中断描述符表(IDT)中任务门的中断或异常;
4. 当嵌套任务标志NT 置位时,当前任务执行了一个IRET 指令。
中断描述符表(Interrupt Descriptor Table – IDT)将每个中断或异常标识号与处理相应事件程序指令的一个描述符相关联。与GDT 和LDT 相似,IDT 是一个8 字节描述符数组,但其第1 项可以含有一个描述符。处理器通过将中断号异常号乘上8 即可索引IDT 中对应的描述符。IDT 可以位于物理内存的任何地方。处理器是使用IDT 寄存器(IDTR)来定位IDT 的。修改和复制IDT 的指令是LIDT 和SIDT。与GDT 表的操作一样,IDT 也是使用6 字节数据的内存地址作为操作数的。前两个字节表示表的限长,后4 个字节是表的线性基地址。
在中断描述符表IDT 中可以含有三类描述符中的任意一种:
• 任务门(Task gates);
• 中断门(Interrupt gates);
• 陷阱门(Trap gates);
当响应一个中断或异常时,CPU 使用中断或异常的标识号来索引IDT 表中的描述符。如果CPU 索引到一个中断门或陷阱门时,它就调用处理过程;如果是一个任务门,它就引起任务切换。
标签:
原文地址:http://www.cnblogs.com/ht-beyond/p/4299376.html