|
楼主 |
发表于 2006-12-11 14:23:58
|
显示全部楼层
查阅资料,明白了些。说说体会。
80386采用了比8086更加巧妙的办法得到段基地址和段内偏移量。段寄存器作为进入存储器中的一张表的变址寄存器。根据段寄存器的值可以从表中找到一个项。setup.s 132行,
lidt idt_48 ! load idt with 0,0
lgdt gdt_48 ! load gdt with whatever appropriate
表明加载中断描述符表和全局描述符表。它们都是由6个字节组成。第一个字节表示表的大小。第二和第三个表示其线性地址。
如gdt_48: .word 0x800 ;表示全局描述符表为2kb,而每个描述符占4个字(8个字节)
.word 512+gdt,0x9 ;其线性地址为9<<16+512+gdt=0x90200+gdt
即跳到setup.s程序中的gdt的位置运行程序。
...
gdt:
.word 0,0,0,0 ;没有用到,但是不能除掉,等会讲
;cs 寄存器的段描述符
.word 0x07ff ;中午提的问题。不完全,:-),
.word 0x0000
.word 0x9a00
.word 0x00c0
;ds寄存器的段描述符
......
根据上面的描述cs段描述符占8个字节。而段描述符的定义为:(按字分)
31................................................1615...................................0
段基地址(15--0) 段界限值15...........0
段基地址(31-24)GD00段界限值(19-16)PDPLS 段类型A段基地址(23--16)
不好画图。在微型计算机技术与应用(戴梅萼第3版)p60页。有图:-)
所以说:上面题的问题不全,因为段界限的高4位没有写上,在这里虽然是0。
因而,根据linux中的描述,则为非系统段。P=1,代表对应段已装入内存。粒度为1,即G=1。D=1为32位代码,寻址空间为4kb---4Gb。E=1,代表代码段。A=0代表未被访问过。等等吧。
然后再setup.s的第193行, 为 jmpi 0,8 ;即调到段8,偏移量为0的地方运行,其实就是gdt的位置。这里说明的是,这里的0为32位地址。8也是,故表达为0000 0000 0000 1000。其含义自己有兴趣可查。
由于现在linux已经system模块考到0000的位置,故而可运行。运行的大小最大应为512kb,其cs段的段界限值为0x7ff即2047*4096=8Mb。问题解决。
G=0时,段内寻址空间是1M,limit是20位的,G=1时,limit是32位的,段内寻址空间是4G.
刚看lunix内核,挺不错的,欢迎交流。qq:76172724 |
|