1.setup中获取扩展内存大小:
! Get memory size (extended mem, kB)
mov ah,#0x88
int 0x15
mov [2],ax
返回:ax=从0x100000(1M)处开始的扩展内存大小
2.保护模式
setup切换保护模式位于[0x00090348] 9020:0148
mov ax,#0x0001 ! protected mode (PE) bit
lmsw ax ! This is it!
此时CPU已经进入32位保护模式
jmpi 0,8 ! jmp offset 0 of segment 8 (cs)
这句话在16位实模式下解释如下:
CPU跳转至cs = 8,IP = 0 即0x80处开始执行
而到了32位,CS称为选择子。此时的寻址方式为:
通过选择子配合gdt表查到一个值,把这个值重新组合作为新的地址。
此时GDTR = 0x0009035b
意味着当前gdt表起始位置在内存中的0x0009035b处。cs=8代表,以GDTR
位起始位置,偏移8个字节。也就是选择‘0x00090363’。存放的东西是什么呢?
0x00090363 <bogus+ 8>: 0xff 0x07 0x00 0x00 0x00 0x9a 0xc0 0x00
p.s. 为了方便起见,将低地址放到低位,高地址放到高位于是乎:
0x00090363-0x00090371:
00C09A00000007FF
上面的东西代表的是什么意思呢?其是,它是一段LDT(Local Descriptor Table)。一共64个bit,其解释方式如下图所示:
重点关心黑色字体部分:
00C09A00000007FF
前面的就是32位保护模式下的基址,后面的就是保护模式下的偏移地址。所以,接下来CPU就到了00:000000
处。
用一张图概况保护模式下的寻址方式,一定就是这样了:
2018.10/27
为了加深理解,补充一张 GDT 的图片:
可以看到,除了 LDT 外,GDT 还包含有 TSS。而 TSS 却跟任务调度有着莫大的联系…
来源:赵炯《Linux 内核完全注释》
2019/2/2
可以这样理解,对于计算机来说,操作系统可以当作是一个庞大的进程。这个进程一方面处理用户交互(管理硬件),一方面用于支持其他的进程去运行。
分段机制让内存管理变得高效,但需要记录下来每个段的地址。这就需要有一份段表。
操作系统的段表就是 GDT,进程的段表就是 LDT