GDT与LDT

保护模式下的段寄存器 由 16位的选择器 与 64位的段描述符寄存器 构成
段描述符寄存器: 存储段描述符
选择器:存储段描述符的索引

PS:原先实模式下的各个段寄存器作为保护模式下的段选择器,80486中有6个(即CS,SS,DS,ES,FS,GS)80位的段寄存器,同时提供6个段左右机器当前运行的地址空间。由选择器CS对应表示的段仍为代码段,选择器SS对应表示的段仍为堆栈段

 

(1)全局描述符表GDT(Global Descriptor Table)在整个系统中,全局描述符表GDT只有一张(一个处理器对应一个GDT),GDT可以被放在内存的任何位置,但CPU必须知道GDT的入口,也就是基地址放在哪里,Intel的设计者门提供了一个寄存器GDTR用来存放GDT的入口地址,程序员将GDT设定在内存中某个位置之后,可以通过LGDT指令将GDT的入口地址装入此积存器,从此以后,CPU就根据此寄存器中的内容作为GDT的入口来访问GDT了。GDTR中存放的是GDT在内存中的基地址和其表长界限。

GDTR结构

(2)段选择子(Selector)由GDTR访问全局描述符表是通过“段选择子”(实模式下的段寄存器)来完成的,如图三①步。段选择子是一个16位的寄存器(同实模式下的段寄存器相同)如图四

 

selector
段选择子包括三部分:描述符索引(index)、TI、请求特权级(RPL)。他的index(描述符索引)部分表示所需要的段的描述符在描述符表的位置,由这个位置再根据在GDTR中存储的描述符表基址就可以找到相应的描述符(如图三①步)。然后用描述符表中的段基址加上逻辑地址(SEL:OFFSET)的OFFSET就可以转换成线性地址(如图三②步),段选择子中的TI值只有一位0或1,0代表选择子是在GDT选择,1代表选择子是在LDT选择。请求特权级(RPL)则代表选择子的特权级,共有4个特权级(0级、1级、2级、3级)。

关于特权级的说明:任务中的每一个段都有一个特定的级别。每当一个程序试图访问某一个段时,就将该程序所拥有的特权级与要访问的特权级进行比较,以决定能否访问该段。系统约定,CPU只能访问同一特权级或级别较低特权级的段。

例如给出逻辑地址:21h:12345678h转换为线性地址
a. 选择子SEL=21h=0000000000100 0 01b 他代表的意思是:选择子的index=4即100b选择GDT中的第4个描述符;TI=0代表选择子是在GDT选择;左后的01b代表特权级RPL=1
b. OFFSET=12345678h若此时GDT第四个描述符中描述的段基址(Base)为11111111h,则线性地址=11111111h+12345678h=23456789h

(3)局部描述符表LDT(Local Descriptor Table)局部描述符表可以有若干张,每个任务可以有一张。我们可以这样理解GDT和LDT:GDT为一级描述符表,LDT为二级描述符表。如图

gdt寻址

LDT和GDT从本质上说是相同的,只是LDT嵌套在GDT之中。LDTR记录局部描述符表的起始位置,与GDTR不同LDTR的内容是一个段选择子。由于LDT本身同样是一段内存,也是一个段,所以它也有个描述符描述它,这个描述符就存储在GDT中,对应这个表述符也会有一个选择子,LDTR装载的就是这样一个选择子。LDTR可以在程序中随时改变,通过使用lldt指令。如上图,如果装载的是Selector 2则LDTR指向的是表LDT2。举个例子:如果我们想在表LDT2中选择第三个描述符所描述的段的地址12345678h。
1. 首先需要装载LDTR使它指向LDT2 使用指令lldt将Select2装载到LDTR
2. 通过逻辑地址(SEL:OFFSET)访问时SEL的index=3代表选择第三个描述符;TI=1代表选择子是在LDT选择,此时LDTR指向的是LDT2,所以是在LDT2中选择,此时的SEL值为1Ch(二进制为11 1 00b)。OFFSET=12345678h。逻辑地址为1C:12345678h
3. 由SEL选择出描述符,由描述符中的基址(Base)加上OFFSET可得到线性地址,例如基址是11111111h,则线性地址=11111111h+12345678h=23456789h
4. 此时若再想访问LDT1中的第三个描述符,只要使用lldt指令将选择子Selector 1装入再执行2、3两步就可以了(因为此时LDTR又指向了LDT1)
由于每个进程都有自己的一套程序段、数据段、堆栈段,有了局部描述符表则可以将每个进程的程序段、数据段、堆栈段封装在一起,只要改变LDTR就可以实现对不同进程的段进行访问。

 

-----------------------------------------------我是分割线------------------------

 

段描述符

 

P,present位,1表示所描述的段存在(有效),为0表示所描述的段无效,使用该描述符会引起异常 
DPL,Descriptor privilege,描述符特权级别,说明所描述段的特权级别 

DT,描述符类型位,1说明当前描述符为存储段描述符,0为系统描述符或门描述符. 

TYPE: 
位0:A(accessed)位,表明描述符是否已被访问;把选择子装入段寄存器时,该位被标记为1 
位3:E(EXECUTABLE?)位,0说明所描述段为数据段;1为可执行段(代码段) 

当为数据段时, 
   位1为W位,说明该数据段是否可写(0只读,1可写) 
   位2为ED位,说明该段的扩展方向(0向高位扩展,1向低位扩展) 
当为可执行段是, 
   位1为R位,说明该执行段是否可读(0只执行,1可读) 
   位2为C位,0说明该段不是一致码段(普通代码段),1为一致码段 

G为粒度位,0说明LIMIT粒度为字节,1为4K字节. 

D位: 
   1.在可执行段中,D为1,表示使用32位地址,32/8位操作数;为0表示使用16位地址,16/8位操作数 
   2.在由SS寻址的段描述符(堆栈段?)中,D为1表示隐含操作(如PUSH/POP)使用ESP为堆栈指针,/
     为0使用SP(隐含操作:未明确定义段属性类型USE16/USE32?66H,67H?) 
   3.在向低扩展的存储段中,D为1,表示段的上限为4G;为0上限为64K
 
存储段描述符的结构表示:

 

分段管理可以把虚拟地址转换成线性地址,而分页管理可以进一步将线性地址转换成物理地址。当CR0中的PG位置1时,启动分页管理功能,为0时,这禁止启动分页管理功能,并且把线性地址作物理地址使用。

虚拟地址转为线性地址:

线性地址= 段基指 + 偏移地址

 

32位线性地址转为物理地址
32位分为:
页目录索引:占最高10位,指示页目录表中第几个页表描述符
页表索引:占12位到21位,也是10位。指示这页表中第几个页描述符
页描述符:线性地址的低12位为页内偏移量。

 

 

展开阅读全文

WINDOWS下的gdtldt

04-13

是这样的,我想问下Windows 在Intel Protection Mode下工作的问题。rn在指令手册第三卷system programming 可以看到,通常GDT只有一个,而LDT可以有很多的。rn本来我很天真地想:rn那么我又多少个进程在running 就应该有多少个LDT才对。rn于是我打开softice, 输入GDTrn结构只有一个被标为LDT,参考了using softice,只看到如下一段:rnUnder Winnt , LDT are per process data structures and are only used for virtual dos machines.rnThe 16 bit WOW box is executed within a NTVDM process and has an LDT.rnLike Windows 3.1 the LDT for a WOW contains the selectors for every 16 bit proteced mode code and data segment for each 16 bit application or DLL that is loaded. It also contains the selectors for each task database, module database, local heaps, global allocation, and all USER and GDI objects that require the creation of a selector. Under a WOW, because the number of selectors needed can be quite large, a full LDT is created with a majority of the entries initially reserved. These reserved selectors are allocated as needed. Under a non-WOW VDM, the size of the LDT is significant smaller.rnrn老实说我不知道它在说什么,最后的结果就是我只能看到一个LDT.rn这实在太奇怪了,请问难道windows不用LDT? rnrn第二个奇怪的是rnGDTbase=80036000 Limit=03FF rn0008 Code32 Base=00000000 Lim=FFFFFFFF DPL=0 P R rn0010 Data32 Base=00000000 Lim=FFFFFFFF DPL=0 P R rn001B Code32 Base=00000000 Lim=FFFFFFFF DPL=3 P R rn0023 Data32 Base=00000000 Lim=FFFFFFFF DPL=3 P R rn0028 TSS32 Base=8000B000 Lim=000020AB DPL=0 P B rn0030 Data32 Base=FFDFF000 Lim=00001FFF DPL=0 P R rn003B Data32 Base=7FFDE000 Lim=00000FFF DPL=3 P R rn0043 Data16 Base=00000400 Lim=0000FFFF DPL=3 P R rn0048 LDT Base=E156C000 Lim=0000FFEF DPL=0 P rnrn显然code32 data32也就是从0008-001brn这段是固定的,所谓的flat mode,可是真的不明白,rn明明规定4g地址只有低2g空间是用户可以访问的。rn高2G操作系统用,也就是ring0才能访问。rn那么这里有两个Code32,一个是ring3(0008),一个是ring0(001B)rn那么同一句汇编指令,访问32位偏移0xYYYYYYYY地址,rn操作系统怎么知道是访问上面那个还是下面那个,rn有两个段,这两个段根本都覆盖了4g空间,却具有不同的权限,dpl 不同,rn同一个地址到底要怎么解释呢?rnrn晕眩。rn 论坛

WIN9X下保护GDT,IDT,LDT!!!

03-06

众所周知WINNT下的GDT,IDT,LDT都被保护起来,一般程序无法访问,而WIN9X下却可以访问,从而导致众多病毒进入RING0层,大搞破坏,让我等菜鸟防不胜防,最好能象NT那样将这些系统表格保护起来,经过研究发现一种行之有效的方法,与大家讨论一下rn 大家都知道,80X86下保护模式采用2级保护,即段级保护和页级保护,在WIN9X下的这些系统表格都存放于3级数据段,所以只能从页级保护着手。在WIN9X下这些表格所在页的页属性都是USER/WRITABLE,即都是用户级,可被读写的,估计NT就是对这些表格采用页级保护,不过我们也可以自己进行保护。rn 通过获取这些表格的线性地址,找到其物理地址,及页属性,将其属性改为USER/READONLY从而达到保护的目的。以下程序通过修改IDT的物理页属性,达到禁止修改IDT的目的,当然也可以将LDT,GDT都保护起来,这样不论是通过修改GDT,LDT的调用门,还是IDT的中断门进入RING0都不行了。rn 由于本程序是通过GDT,生成一个调用门进入RING0,修改页属性,所以一旦你将GDT保护起来,就不要再运行该程序了。rn 本程序用MASM32V7编译,在WIN98下通过,原先所有通过修改IDT中断门进入RING0的程序,都会产生一个EXCEPTION。rn .386prn .model flat, stdcallrn option casemap :none ; case sensitivern include \masm32\include\windows.incrn include \masm32\include\kernel32.incrn include \masm32\include\user32.incrn includelib \masm32\lib\kernel32.librn includelib \masm32\lib\user32.librn Call32 macro Selector,Offsetvrn db 09ahrn dd Offsetvrn dw Selectorrn endmrnrnrn .datarnAddressToWritePhy dd ?rnAddressToWriteLinear dd ?rnPageAddress dd ?rnText db 'IdtBase 的物理地址是:%8xH',0dh,0ahrn db 'IdtBase 的线性地址是:%8xH',0dh,0ahrn db '页属性是:%s/%s',0rnUser db 'User',0rnSysten db 'System',0rnRead db 'Read',0rnWrite db 'Write',0rnChanger db 100 dup(0)rnCaption db 'P2L',0rn; #########################################################################rn .codernrn GetLdtAddress procrn push ebxrn sgdt [esp-2]rn pop ebxrn sldt axrn and eax,0fff8hrn add ebx,eaxrn mov eax,[ebx+2]rn and eax,0ffffffhrn mov dl,[ebx+7]rn shl edx,24rn or eax,edxrn retrn GetLdtAddress endprnrn GetGdtAddress procrn push ebxrn sgdt[esp-2]rn pop ebxrn mov eax,ebxrn retrn GetGdtAddress endprn rn ToRing0Code proc Ring0Proc:DWORDrn local temp1,temp2rn call GetGdtAddressrn add eax,8rn mov ecx,[eax]rn mov temp1,ecxrn mov ecx,[eax+4]rn mov temp2,ecxrn mov edx,Ring0Procrn mov [eax],dxrn mov cx,28hrn mov [eax+2],cxrn mov cx,0ec00hrn mov [eax+4],cxrn shr edx,16rn mov [eax+6],dxrn push eaxrn Call32 0bh,0 rn pop ebxrn mov edx,temp1rn mov [ebx],edxrn mov edx,temp2rn mov [ebx+4],edxrn retrn ToRing0Code endprnrn start:rn rn push offset L2Prn call ToRing0Codern mov eax,PageAddressrn lea esi,Readrn lea edi,Userrn test eax,10brn jnz Writablern test eax,100brn jz Systemablern jmp ShowrnWritable:rn lea esi,Writern jmp ShowrnSystemable:rn lea edi,SystenrnShow: rn invoke wsprintfA,addr Changer,addr Text,AddressToWritePhy,AddressToWriteLinear,edi,esirn invoke MessageBoxA,0,addr Changer,addr Caption,MB_OKrn invoke ExitProcess,0rnrn P2L proc P2LAddress:DWORDrn push P2LAddressrn int 20hrn dd 0001006ch ;VmmCall_MapPhysToLinearrn add esp,4rn retrn P2L endprnrn L2P proc rn push ebxrn sidt [esp-2]rn pop ebxrn mov AddressToWriteLinear,ebxrn mov eax,cr3rn and eax,0fffff000hrn push eaxrn call P2Lrn mov edx,AddressToWriteLinearrn shr edx,22rn shl edx,2rn mov eax,[eax+edx]rn cmp eax,1rn jz Exitrn and eax,0fffff000hrn push eaxrn call P2Lrn push eaxrn mov edx,AddressToWriteLinearrn shl edx,10rn shr edx,22rn shl edx,2rn mov eax,[eax+edx]rn cmp eax,1rn jz Exitrn pop ecxrn and eax,0fffffffdhrn mov [ecx+edx],eaxrn mov PageAddress,eaxrn and eax,0fffff000hrn mov edx,AddressToWriteLinearrn and edx,00000fffhrn or eax,edxrn mov AddressToWritePhy,eaxrn Exit: rn retfrn L2P endprn end start 论坛

没有更多推荐了,返回首页