Windows,RedHat等通用型操作系统都是工作在保护模式下面。他们的存储机制是段式存储,这种机制是通过段寄存器(386以上的CPU的段寄存器是gdtr)和GDT中的描述符共同提供的。操作系统维护着一个结构书组,数组里面每个元素就是一个GDT全局描述符,描述符的种类很多,有程序段描述符、数据段描述符、系统段描述符、门描述符等。下面的例子详细描述了操作系统是如何通过段寄存器(gdtr)和描述符来达到段式存储机制的。
0101h LABEL_GDT: Descriptor
0,0,0
0105h
LABEL_DESC_CODE32: Descriptor 0, SegCode32Len -1,
DA_C+DA_32
0109h LABEL_DESC_VIDEO:
Descriptor 0B8000h, 0ffffh, DA_DRW
;上面这几行代码定义个操作系统全局描述符数组,一个是空描述符,一个是程序段描述符,一个是视频段,最左边的0101h,0105h,0109h是编译以后这个数组的各个描述符所对应的地址
.......
.......
SelectorCode32 equ
LABEL_DESC_CODE32 - LABEL_GDT
SelectorVideo equ
LABEL_DESC_VIDEO - LABEL_GDT
;书面两行代码定义了两个选择子,其实就是两个描述符相对于描述符数组GDT基地址的偏移量
.......
.......
xor eax, eax
mov ax, ds
shl eax, 4
add eax, LABEL_GDT
mov dword [GdtPtr + 2], eax
;这几行代码就是将结构数组的基地址赋值给了段寄存器gdtr,自此以后cs,gs,ds等寄存器只需要存储各个描述符相对于GDT数组基地址的偏移就可以,即选择字
.......
.......
mov ax, SelectorVideo
mov gs, ax
mov edi, (80*10+0)*2
mov al, 0Ch
mov al, 'p'
mov [gs:edi], ax
;上面几行代码就是让gs寄存器指向视频段选择子,来达到向显存里面输出内容的。注意方框号的应用,方括号是访问的内容,不是地址,比如GS对应的其实是0109,[gs]!=0109h,
而是[gs]=0B8000h(这个地址里面的数据)。所以,mov [gs:edi],
ax不是把ax的数据送到0109h这个地址中,而是放到了0B8000h这个显存地址中
到此就完成了段式访问。描述比较粗糙甚至还有不确切的地方,整个机理应该无误。随着学习进程再补充完善吧。