此时,段寄存器显然无法直接提供地址,但是它还是很有用的。
实模式下:段值是地址的一部分,如段值XXXXh标示xxxx0h开始的一段内存。
保护模式:段值仅是一个索引,用来指向一个数据结构(其实就是GDT)中的一个表项,此表项中详细定义了段的起始地址、界限、属性。
举例子:
“新政策下的地址仍然用:SEG:OFFSET这样的形式来表示”:这句话什么意思呢,
其实就是无论是实模式还是保护模式,在程序中都是这样来用的,如:(nasm不是masm)
mov [gs:edi],ax
但是样式虽然一样,不同模式的解析方式是不一样的,关于实模式的我就不说了,具体说下保护模式是如何理解上一句话的:
分析:
【
gs是段寄存器
edi指针在这里做偏移
ax是通用寄存器eax的低16位
在保护模式下:
如果使用上面那个句子,则肯定有类似下面的两条语句:
mov ax, SelectorVideo
mov gs, ax
这两句什么意思啊:
我们把这个Selector..叫做段选择子,顾名思义:段寄存器就是通过它来选择地址的。
这两句代码把gs地址指向SelectorVideo,不过它的内容是什么呢??
程序中式这样定义段选择子的:
SelectorVideo equ LABEL_DESC_VIDEO - LABEL_GDT
解释:LABEL_DESC_VIDEO 是什么东东呢,原来它就是全局描述符表中的一个表项,LABEL_GDT是第一个表项,那么这个SelectorVideo equ它们的差,说明就是LABEL_DESC_VIDEO这个描述符相对于GDT基址的偏移。
(当然,它还不仅仅如此,它一共16位,高13位的确是地址,但是低3位又有其他意思:分别是0,1位表示RPL(特权级别),2位TI:如果是0表示是GDT的段描述符,如果是1表示是LDT中的)
这里,我们看到:
通过SelectorVideo 我们又联系上了GDT(或者LDT),这样我们就寻到了GDT中的表项:
LABEL_DESC_VIDEO.
这个东东是干什么的??
看定义先:
[section .gdt]
;GDT
LABEL_GDT: Descriptor 0, 0, 0
...
LABEL_DESC_VIDEO: Descriptor 0B8000h, 0ffffh, DA_DRW ; base limit attr
; GDT结束
哈哈,我们终于寻到了段基地址,原来gs真实指向的地址就是0B8000h(显存的首地址),
所以寻址得到的物理地址就是:0B8000h加上edi(偏移地址)。
mov [gs:edi],ax
就是将ax的值写入显存中偏移edi的位置.
整个寻址过程如下:
逻辑地址SEG:OFFSEST-->
SET中的段选择子-->
段选择子中高13位的偏移地址-->
根据段段选择子2位TI的值判断是GDT还是LDT中对应的段描述符-->
根据这个段描述符结构(base,limit,attr)得到 段基地址-->
段基地址+OFFSET就得到线性地址(如果不分页就是物理地址)。
大功告成!!!
】