由实模式进入保护模式来进行32位寻址

因为cpu在实模式下地址总线为20位,所以能访问到的内存在1M左右,为了能操作更多的内存,cpu生产商设计了保护模式,在此模式下总线地址可达32位,访问内存明显增加。

用保护模式来32位寻址的操作要用一个叫gdt的东西,这个gdt(Global Descriptor Table)叫全局描述表。我对它的理解是它像一个目录,每一条存着在内存里的一个段的头地址和这个段的大小。

这个段就理解为在内存中选取一小块,给它起个名字,那么他就是内存中的一个段了。

下边这个图更好描述

当然gdt在内存中的位置肯定要在实模式可以访问的范围内。

当要访问更大的地址的时候,要访问某个段就先访问该段在gdt中的条目,然后得到他的实际物理地址,启动保护模式的32位总线访问它。

move ax [0x5a1]

比方说实模式下想要把0x5a1位置的内存数据读到ax寄存器中那么用上边那个汇编语句就行,当然先把基地址寄存器设为0.

要是要访问5M位置的内存数据的话这种方式就行不通了,这时候要使用如下代码

[SECTION .gdt]
 ;                                  段基址          段界限                属性
LABEL_GDT:          Descriptor        0,            0,                   0  
LABEL_DESC_CODE32:  Descriptor        0,      SegCode32Len - 1,       DA_C + DA_32
LABEL_DESC_VIDEO:   Descriptor     0B8000h,         0ffffh,           DA_DRW
LABEL_DESC_5M:      Descriptor     0500000h,        0ffffh,           DA_DRW

GdtLen     equ    $ - LABEL_GDT
GdtPtr     dw     GdtLen - 1
           dd     0

SelectorCode32    equ   LABEL_DESC_CODE32 -  LABEL_GDT
SelectorVideo     equ   LABEL_DESC_VIDEO  -  LABEL_GDT
Selector5M        equ   LABEL_DESC_5M - LABEL_GDT
mov   bx, Selector5M    ;用 es 指向5M内存描述符
mov   es, bx
mov   edi, 0
mov   ax, [es:edi]

第一块代码是对gdt的一个编写,在这个表中给在内存5M位置的段起了个名字叫LABEL_DESC_5M,大小为0ffffh。我还写了其他的一些段,大家不要在意。

第二块代码就是使用了,其中Selector5M相当于LABEL_DESC_5M这个段在gdt这个表里是第几条,这里是第四条。把它通过bx寄存器传递给es寄存器。这个es寄存器就是专门来找gdt表中段的条目的。edi里的值是相对于5M这个位置的偏移,要是访问5M这个位置那么edi置为0,要是访问5M零1字节那么edi就置为1,以此类推,当然不能超过这个段的最大范围。然后最后一句话就是把5M位置的数据写入ax当中。

思考一下,若是用实模式的方法访问5M内存那么就是mov ax [0x500000],当然这个是运行不了的,寄存器和总线都不支持。

mov   ax ,[es:edi]这句话可以看成mov ax [0x500000+0],他之所以能运行是因为这个[es:edi]引发了保护模式,应该是在es上寻址的话会启动保护模式读取gdt访问更大内存,这种实现是一种硬件实现。

总结为下面这个图

发布了24 篇原创文章 · 获赞 9 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/qq_42794321/article/details/104904047
今日推荐