机子启动时内存变化
从BIOS开始,内存中从0000到FFFF这段空间是什么?
那个中断向量什么时候加载进来?
问题点数:20、回复次数:58Top
1 楼VxD1(Dump)回复于 2005-03-09 11:44:59 得分 5
我只知道从0000到4*256这段为中断向量表
中断向量表什么时候加载进来就不知道了Top
2 楼fifo2003(o奇迹再现o)回复于 2005-03-09 18:18:51 得分 0
UPTop
3 楼aecho()回复于 2005-03-10 10:21:46 得分 0
期待Top
4 楼terry_followwind()回复于 2005-03-11 09:04:12 得分 0
这段内存的分配是很麻烦的,首先,会reserved出来一块给dos用,然后是BIOS Data Area(BDA).如果你想知道怎么分配的话,细说起来,有的地方每个byte都有它代表的意思,比如40:0,还有一个办法可以大概知道你的内存是怎么分配的,用INT15,下E820的参数,这里真的写不下,如果有兴趣,再开个帖子讨论吧Top
5 楼xxyifan(一帆)回复于 2005-03-11 15:18:53 得分 0
TO terry_followwind() :为什么再开一个,分数不够吗?那样的话,可以再开,呵呵!
只要大家能明白这段时间内的内存变化就可以,呵呵Top
6 楼terry_followwind()回复于 2005-03-11 16:45:32 得分 0
不是这个意思啦,我是觉得用这个题目讲,别人不一定愿意看,来个吸引人的吗!Top
7 楼qlmi(大米)回复于 2005-03-11 20:39:23 得分 0
我对这个也比较感兴趣:究竟中断向量表是什么时候加载的?Top
8 楼terry_followwind()回复于 2005-03-12 14:26:53 得分 0
对BIOS来讲,中断向量表加载的时候,BIOS已经跑了快一半了Top
9 楼xxyifan(一帆)回复于 2005-03-14 08:12:40 得分 0
可能是这样:
CPU把ROM和RAM统一编址,BIOS是ROM,这样的话,呵呵
Top
10 楼sxianz(爱老虎)回复于 2005-03-14 09:59:58 得分 0
内存中从0000到FFFF这段空间:什么都没有。只有从FFFF这段开始才有BIOS,机器载入BIOs后,从0000开始执行。Top
11 楼terry_followwind()回复于 2005-03-14 14:02:19 得分 0
楼上的说的不对Top
12 楼terry_followwind()回复于 2005-03-14 14:28:18 得分 0
如果想知道怎么分配,那把这篇帖子顶起来,我来写段详细的Top
13 楼daineng(纸玉鸢尾)回复于 2005-03-14 14:42:24 得分 0
启动PC机时,系统首先对硬件设备进行测试,测试成功后进入自举程序INT 19H,然后读系统磁盘0柱面、0磁头、1扇区的主引导记录(MBR)内容到内存指定单元0:7C00地址开始的区域,并执行MBR程序段。
硬盘的主引导记录(MBR)是不属于任何一个操作系统的,它先于所有的操作系统而被调入内存,并发挥作用,然后才将控制权交给主分区(活动分区)内的操作系统,并用主分区信息表来管理硬盘。
MBR程序段的主要功能如下:
·检查硬盘分区表是否完好。
·在分区表中寻找可引导的“活动”分区。
·将活动分区的第一逻辑扇区内容装入内存。在DOS分区中,此扇区内容称为DOS引导记录(DBR)。
MBR引导程序段的执行流程如图6-16所示。Top
14 楼daineng(纸玉鸢尾)回复于 2005-03-14 14:56:21 得分 0
BIOS扮演的最重要的角色之一就是启动系统。当PC被打开时,它的系统内存中是空的,它需要马上找到一条代码以启动机器。这些代码就在BIOS中,因为BIOS被放置在ROM中,所以即使系统内存的其它部分是空的,但BIOS中的程序却总是可以使用的。
我们来看一看在Power-on之后的“硬件”Booting阶段,系统到底都做了些什么。同时,也看一看通过硬盘启动OS和软盘启动OS之间究竟存在着哪些不同。
第一推动力:CPU的第一条指令
CPU从物理地址FFFFFFF0h取出并执行硬件Reset之后的第一条指令。这个地址到最大物理地址4 GB之间只有16 Bytes的空间,包含软件初始化代码的EPROM必须被影射到这个地址。在Real Mode下,地址FFFFFFF0h超过了1 MB的物理地址范围。CS寄存器被分为两部分:可见的“Segment Selector”部分和隐藏的"Base Address"部分。
在Real Address Mode下,"Base Address"部分的值,等于将16-bit的"Segment Selector"左移4-bit所形成的20-bit地址,"Segment Selector"部分并不参与物理地址的计算,在Real Mode下,它仅仅被用来计算"Base Address"部分。而"Base Address"部分被真正的用于实际物理地址的计算。
在硬件Reset期间,CS中的"Segment Selector"部分被初始化为F000h,而"Base Address"部分被初始化为FFFF0000h,这与上述的原则不相符,但没有关系,因为"Base Address"已经有一个值了。所以,第一条指令的地址为Base Address + EIP = FFFF0000h + FFF0h = FFFFFFF0。
EPROM中放置着PC厂商所编写的代码(BIOS),被影射在地址FFFFFFF0h的代码必须为一条"far jump"或者"far call"指令或者产生一个中断,这样CS的"Segment Selector"的值将会被改变,从而"Base Address"部分的值也按照上述计算原则被改变为BIOS代码的影射地址。
POST - Cold Boot / Power On Self Test Activities
POST - 冷启动、开机自检
- power supply starts Clock Generator (8284) with Power
通电后8284时序发生器开始工作
Good signal on BUS
总线产生正常信号
- CPU reset line is pulsed resetting CPU
CPU的复位引脚被触发,CPU复位
- DS, ES, and SS are cleared to zero
DS,ES,SS初始值为0(CPU处于实模式下)
Cold and Warm Boot both execute the following sequence
冷启动和热启动都会执行一下序列
- CS:IP are set to FFFF:0000 (address of ROM POST code)
CS:IP初始值为FFFF:0000(该地址为BIOS的ROM POST代码)
- jump to CS:IP (execute POST, Power On Self test)
CPU工作,开始取第一条指令(执行POST,开机自检)
- interrupts are disabled
关中断
- CPU flags are set, read/write/read test of CPU registers
设置CPU标志位,用读、写、读来测试CPU寄存器
- checksum test of ROM BIOS
检测ROM BIOS的校验和
- Initialize DMA (verify/init 8237 timer, begin DMA RAM refresh)
初始化DMA(校验、初始化 8237时钟控制器,开始DMA 内存刷新)
- save reset flag then read/write test the first 32K of memory
保存复位标志,然后对内存的前32K字节进行读写测试
- Initialize the Programmable Interrupt Controller (8259)
and set 8 major BIOS ~interrupt~ vectors (interrupts 10h-17h)
初始化8259可编程中断控制器,设置好8个主要的BIOS中断向量(INT 10h-17H)
- determine and set configuration information
检测并设置好CMOS配置信息
- initialize/test CRT controller & test video memory (unless 1234h
found in reset word)
初始化/测试CRT控制器,测试显存(除非在复位字的位置找到1234h)
- test ~8259~ Programmable Interrupt Controller
测试8259可编程中断控制器
- test Programmable Interrupt Timer (~8253~)
测试8253可编程时钟中断控制器
- reset/enable keyboard, verify scan code (AAh), clear keyboard,
check for stuck keys, setup interrupt vector lookup table
复位、激活键盘,校验扫描码,清除键盘缓冲区,检查是否有卡住的键,设置中断查找表
- hardware interrupt vectors are set
设置硬件中断向量
- test for expansion box, test additional RAM
测试扩展设备,测试扩充内存
- read/write memory above 32K (unless 1234h found in reset word)
读写测试32K字节以上的内存(除非在复位字的位置找到1234h)
- addresses C800:0 through F400:0 are scanned in 2Kb blocks in
search of valid ROM. If found, a far call to byte 3 of the ROM
is executed.
以2K字节大小的块为单位,从c800:0到f400:0扫描,查找有效映射的ROM。找到后,对ROM的第3个字节进行远程调用。
- test ROM cassette BASIC (checksum test)
检测ROM BASIC(校验和测试,现在的BIOS已取消ROM BASIC了……)
- test for installed diskette drives & ~FDC~ recalibration & seek
检测安装了的硬盘驱动器、软盘控制器。
- test printer and RS-232 ports. store printer port addresses
at 400h and RS-232 port addresses at 408h. store printer
time-out values at 478h and Serial time-out values at 47Ch.
检测打印机口和RS-232串口。把打印口地址保存在内存的400h,串口地址保存在408h。打印机超时值保存在478h,串口超时值保存在47Ch。
- NMI interrupts are enabled
激活NMI中断
- perform ~INT 19~ (bootstrap loader), pass control to boot record
or cassette BASIC if no bootable disk found
执行INT 19h(引导装载程序),把控制权转交给引导程序
- ~WARM BOOT~ procedure is now executed
现在热启动已经执行完毕了
Top
15 楼xxyifan(一帆)回复于 2005-03-14 15:27:14 得分 0
再顶吧,大家都想明白这里Top
16 楼xxyifan(一帆)回复于 2005-03-14 15:31:50 得分 0
TO terry_followwind() :
来一段呀,呵呵Top
17 楼terry_followwind()回复于 2005-03-14 15:52:05 得分 0
首先,在机器刚开始启动的时候,内存没有被初始化,是不能用的,在内存开始之前,我们要对内存开始检测,就是往内存里面写值,然后读回来,看看是不是一样的,如果是一样的,那表明这段内存可用,可以用来当做堆栈(只test 用做堆栈那部门),在这之前,内存初始化就是填一些内存的参数,这个也很多(希望知道再写)可能超频的发烧友知道,比如Cas latency等等,在内存可以用了以后,好多资料都可以放在内存里了,也可以用堆栈了,这样方便多了.
TO 一帆:你想知道什么,能不能说的具体一点,POST很复杂的,上面的朋友贴的讲的很对,基本就是这样做的,你是想知道的详细一点吗?Top
18 楼xxyifan(一帆)回复于 2005-03-14 16:30:25 得分 0
是的,我想知道得详细一点,比如,
这个CPU是不是把ROM和RAM统一编址?
那么各个ROM或是RAM是从哪里开始呢?
上面那位大哥说的:“可见的“Segment Selector”部分和隐藏的"Base Address"部分”,“在Real Address Mode下,"Base Address"部分的值,等于将16-bit的"Segment Selector"左移4-bit所形成的20-bit地址,"Segment Selector"部分并不参与物理地址的计算,在Real Mode下,它仅仅被用来计算"Base Address"部分。而"Base Address"部分被真正的用于实际物理地址的计算。”
他说的一定是32位的机子,对吧,那么CS是32位的,在这里我有点不明白,隐藏的"Base Address"部分是16位的吧,呵呵,那么“Base Address"部分的值,等于将16-bit的"Segment Selector"左移4-bit所形成的20-bit地址”是什么意思?
我记得有一选择子的概念,指的是不是这个Segment Selector?
中断向量是什么时候加载入内存的呢?还是这样,它就在ROM中,只是它的入口地址在某个内存的1K空间内?那么这里的内存指的是条子的空间吗?
Top
19 楼xxyifan(一帆)回复于 2005-03-14 16:32:06 得分 0
TO:terry_followwind() :呵呵,我再UPTop
20 楼xxyifan(一帆)回复于 2005-03-14 16:43:02 得分 0
UPTop
21 楼daineng(纸玉鸢尾)回复于 2005-03-15 09:07:26 得分 0
我也是刚好看到关于BIOS的信息,就顺手贴过来了,关于Segment Selector和Base Address等,我认为在加电时相当于CS寄存器被置成全1,而IP被置0,16位的机器就大致是0xFFFF:0,构成真实的20位地质就是0xFFFF0了,32位的我就不清楚了Top
22 楼xxyifan(一帆)回复于 2005-03-15 09:12:21 得分 0
看这个:
在Real Mode下,地址FFFFFFF0h超过了1 MB的物理地址范围。CS寄存器被分为两部分:可见的“Segment Selector”部分和隐藏的"Base Address"部分。
这里,CS是多少位?可见的是哪部分?在protected模式呢又是怎样的呢?Top
23 楼ZivWang(王朝)回复于 2005-03-15 09:28:34 得分 0
开机后,之所以能看到4g左右的空间是硬件连线决定的.
Top
24 楼xxyifan(一帆)回复于 2005-03-15 09:34:00 得分 0
没有人回答我的问题吗?呵呵,真的是不明白呀,TO ZivWang(王朝) ,你想表达什么?Top
25 楼daineng(纸玉鸢尾)回复于 2005-03-15 09:43:30 得分 0
我觉得我们可以从“Cold and Warm Boot both execute the following sequence 冷启动和热启动
都会执行一下序列”开始研究,到“保存复位标志,然后对内存的前32K字节进行读写测试”为止,
现在内存的前32K应该都是可以使用的了,最低地址的1K空间被用来存放256个Interrupt Vecotr。
“设置好8个主要的BIOS中断向量(INT 10h-17H)”,我觉得这个地方需要讨论一下,这几个中断向量
指向的代码是存放在哪里的?按理说也应该是在32K之内。顺便说一下,我觉得这前32K内存肯定是不
受MCB控制的,MCB应该是DOS系统的管理内存的,仅仅是整个可用内存的一部分(中断向量表肯定不
受MCB控制),我可以写个程序测试MCB在哪里结束,但不知道它是从哪里开始的。
下面是在Windows2000 DOS BOX中的MCB,以‘|’分割,第一个是MCB所控制的内存开始的段址(不包
括MCB本身所占的一段(16字节)),在段址E000之后就不受MCB控制了。顺便说一下,我觉得MCB控
制的所有内存就是DOS的所有可以使用内存,包括给系统程序使用和用户程序使用的。(中断向量表
当然也可以被DOS使用,但应该不是被DOS独占使用,所以不被包括于上面所说的‘可以使用内存’,
如果再准确点,可以说MCB控制的是DOS可以用来分配的内存。
再从头说,每一段是MCB所控制的内存开始的段址,第二个是是否MCB链尾的标志,第三个是程序ID,
通常是程序的PSP段址,但也未必,比如如果属于DOS,这里就是0008,如果未分配,这里就是0000
1C3D Z 1C3D 83C2 | A000 M 0008 2D00 | CD01 M 0008 0335 | D037 M 0000 0071 | D0A9 M D0A9
001D | D0C7 M D0C7 00A7 | D16F M D16F 087A | D9EA M D16F 0008 | D9F3 Z 0000 060D || END
BELOW: E000
下面是DOS7的MCB,这个DOS是虚拟机
1993 Z 1993 85EC | 9F80 M 0008 29DC | C95D M 0008 0578 | CED6 M CED6 0165 | D03C M CED6
0069 | D0A6 M 0000 000B | D0B2 M D0B2 0018 | D0CB M D0CB 00F7 | D1C3 M 0000 000C | D1D0
M D1D0 02E1 | D4B2 M D4B2 0163 | D616 M D616 00CF | D6E6 M 0000 01AE | D895 Z 0000 036B
|| END BELOW: DC00
扯远了,现在回到“设置好8个主要的BIOS中断向量(INT 10h-17H)”,下面与内存相关的是“设置中
断查找表”、“设置硬件中断向量”、“测试扩充内存”、“读写测试32K字节以上的内存”、“查
找有效映射的ROM”、“把打印口地址保存在内存的400h,串口地址保存在408h。打印机超时值保存
在478h,串口超时值保存在47Ch”
关于“查找有效映射的ROM”,这里我不大明白,有效的ROM是什么时候被映射的,它的功能是什么?
最后“执行INT 19h(引导装载程序),把控制权转交给引导程序”,BIOS这部分就介绍完了,剩下
就是说引导程序MBR的功能了,MBR的功能如下:
·检查硬盘分区表是否完好。
·在分区表中寻找可引导的“活动”分区。
·将活动分区的第一逻辑扇区内容装入内存。在DOS分区中,此扇区内容称为DOS引导记录(DBR)。
可见没有怎么影响内存,下面就应该是DOS所干的事了。有关DBR的具体资料我现在还没有,希望其他兄弟补充一下。Top
26 楼daineng(纸玉鸢尾)回复于 2005-03-15 09:46:31 得分 0
对了,上面说的MCB,我觉得至少从32K以后开始,也就是说MCB本身所在的段的最小段址是0x0800,如果是这样,那么它控制的第一块内存段址应该是0x0801Top
27 楼xxyifan(一帆)回复于 2005-03-15 09:55:07 得分 0
我是不明白它的那个可见部分和隐藏部分是怎么来分的,每个段寄存器都是32位的,在实械下,高16位是不是不用,这样的话,段寄存器中的16位地址给出的是segment slector的地址吗?这个segment slector是可见部分,那么不可见部分是不是这个地址所指向的地址?这个地址是32位的吧?
呵呵,不明白的地方太多了,还有EPROM的地址是从哪里开始的?Top
28 楼daineng(纸玉鸢尾)回复于 2005-03-15 10:34:13 得分 0
忘了说MCB最后一个是什么意思了,是这个内存控制块MCB所控制的内存块大小,
以段(16字节)为单位,不包括MCB本身
下面是DOS7虚拟机的8个主要的BIOS中断向量,代码地址似乎在MCB内和MCB外的都有,
不能说明什么问题,有点是肯定的,这些BIOS的程序地址在设置之初肯定不在MCB内,
但仍不矛盾,因为DOS有可能改变这些中断
┍━━━━━┯━━━━━┯━━━━━━━━━━━━━━━━━━━━━┑
│Interrupt │Address │Meaning │
┝━━━━━┿━━━━━┿━━━━━━━━━━━━━━━━━━━━━┥
│ 10H │D616:04A2 │CPU-generated (80286+) - COPROCESSOR ERROR│
│ 11H │F000:F84D │CPU-generated (80486+) - ALIGNMENT CHECK │
│ │ │BIOS - GET EQUIPMENT LIST │
│ 12H │F000:F841 │BIOS - GET MEMORY SIZE │
│ 13H │0259:0510 │DISK - OPERATION │
│ 14H │F000:E739 │SERIAL - INITIALIZE PORT │
│ 15H │0259:053A │Microsoft TSR Specification │
│ 16H │0007:042D │KEYBOARD - OPERATION │
│ 17H │C994:0A26 │PRINTER - OPERATION │
┕━━━━━┷━━━━━┷━━━━━━━━━━━━━━━━━━━━━┙Top
29 楼daineng(纸玉鸢尾)回复于 2005-03-15 10:35:19 得分 0
!!!强烈建议CSDN在技术论坛使用等间距的字体!!!Top
30 楼xxyifan(一帆)回复于 2005-03-15 13:20:59 得分 0
最早的Intel系列的CPU只存在一种操作模式,即现在所说的实模式(Real Mode,以下简称RM)。在Intel推出80286之后,为了增强CPU的处理能力,同时也为了适应当时的软件开发需求,Intel提出了保护模式(Protected Mode,以下简称PM),但在80286下的PM由于CPU本身设计的问题,并没有使其发挥出很大的功效。在80386推出之后,Intel完善了CPU的设计形成了最终的IA-32架构,并提出了另一种模式系统管理模式(System Management Mode)。本章我们的讨论就围绕着这三种模式进行展开,并重点讨论PM.
首先,对这三种模式做一简单概述。
RM:此模式是主机在加电或复位后自动进入的模式,在此模式下其可以执行16位指令,并可以切换到PM或者SMM。
PM:在此模式下,CPU能够支持其自身的32位特性,使自身处于最高性能表现。
这些特性主要包括:
1. 最大可访问4GB内存空间。事实上,在RM下通过一些未公开的特性,也可以达到同样的效果,但其对于代码段 和堆栈空间却是无效的。况且后面的所有特性都是基于PM的,对RM没有效果。
2. 虚拟存储。处于PM下的CPU其内存管理单元(MMU)支持这项特性。前面我已经说到,在PM下CPU最大寻址空 间为4GB,而在实际中,我们并没有如此大的物理内存空间。因此通过MMU,可以将外存设备(如:硬盘)的一部分 空间模拟成物理内存进行使用。
3. 地址映射。即MMU可以在地址使用前对其进行转换,即所谓的映射。
4. 改进的分段机制。本文后面将对此进行重点论述。
5. 内存保护与任务保护。即在PM状态下,引入了权限机制。通过权限控制可以达到保护相关代码和数据的目的。
6. 改进的寻址模式。在RM下,只有常数,BX或BP,SI或DI可以用来形成地址,而在RM下可以通过任意寄存器进行寻 址,并且可以包含一个为2,4或8的比例因子。
7. 多任务支持。在PM下,CPU提供了特殊的机制能够进行快速的上下文切换。
SMM:该模式为操作系统实现特定平台指定的功能提供了一种有效的机制。
值得注意的是,在PM下,CPU允许在受保护的情况下,执行RM程序,这个特性被称为虚拟8086模式(Virtual-8086 Mode),但其本质上却不是真正的RM。
对于三种模式关系的形象解释可以通过下图来描绘:
正如上面所说的,只有在PM下,CPU才能充分发挥其自身的所有特性,而计算机在启动之后,默认的CPU操作模式却是RM。因此摆在我们面前的一个主要问题就是如何在RM与PM之间相互切换。那么如何在RM和PM之间相互切换呢。核心步骤其实很简单,只要改变CPU中的CR0寄存器中PE标志位的值,就可以实现。在PE=1时,CPU进入PM,而在PE = 0时,则进入RM.但这仅仅是整个切换过程中的一小部分,在进入保护模式之前我们还需要做很多事情,其中最关键的就是建立好一个被称为GDT的表。
在谈到GDT之前,我们先回顾一下,在RM中,内存中寻址的方式---段:偏移量。其中段(Segment)表明了一个基地址,其最大长度固定为64KB(FFFFH),即16bit数所能表示的最大数值。而偏移量(Offset),就是指在指定段内的位置。由此可见,通过段+偏移量这种表示方式,就可以表示出内存中的绝对地址。需要指出的是,在CPU实际处理过程中,CPU会将段寄存器的 值左移动4位,再与偏移量相加,形成地址,放入20位的总线当中。
在PM中,对于段模式来讲,上面的寻址方式,在大部分上仍然是适用的。但由于PM是工作在32位下的,因此上面的各个值,也就都相应的变成了32位。与RM不同的是,在PM下,一个段的长度不再固定,其可以在CPU允许的规则下任意设置.并且CPU为段模式提供了保护机制,即增加了对自身的访问权限.因此在PM下,对于一个段,需要有三个变量给于描述,即基地址,段界限和访问权限.
事实上,CPU将这三个值保存为一个64位长的段描述符.但出于兼容性的考虑,Intel并没有将段寄存器改为64位可用--虽然,段寄存器在事实上确是64位,但对于程序来讲,高于16位的部分却是不可见的--因此,我们需要另一种方法去存放这些数据.Intel选择了将这些段描述符统统存入到一个全局数组中的方法,在访问段时,向相应的段寄存器填入该数组的下标值来实现间接引用。这个全局数组就称其为GDT(全局描述符表).由于GDT可以存放在内存中的任何位置,因此要引用它,就必须知道他的入口地址.Intel为我们提供了GDTR寄存器和LGDT指令.其中GDTR寄存器存放的是GDT的入口地址(32位)和其界限(16位),共48位.这里的入口地址是一个线性地址,界限则是表的字节长度减一.可见该表最多可以长达64KB,存储8192条描述符号,而LGDT指令的作用就是将GDT装载到放入GDTR寄存器当中.
顾名思义,GDT是全局描述符,因此其在内存中存在且仅存在一个,并且它的存在对于所有的任务来讲,都是可见的.显然,这种做法对于多任务来讲是不易管理的.因此,Intel又引入了LDT(局部描述符表),该描述符与GDT不同之处在于,LDT在系统中可以有许多个,但每个任务只允许有一个LDT,且其只能该任务自身可见.其与GDT的主要关系在于,每一个LDT都会作为一个段,存入GDT中.由于CPU在任何时刻只能执行一个任务的代码,因此存储LDT所需要的寄存器也就只需要一个,Intel将其命名为LDTR,与GDT相同,Intel为装入LDT设置了LLDT指令。与GDT不同的是,LLDT指令的操作数却是一个16位的段选择子,即前面说到的要装入的LDT在GDT中的索引值。这里需要指出的是,LDT并不是必须的,你的程序可以选择使用,或者不使用它。
Top
31 楼xxyifan(一帆)回复于 2005-03-15 13:21:38 得分 0
前面提到了一个新概念--段选择子。我们说段选择子是要引用段在GDT或LDT中的索引值,其实这种说法并不正确。因为段选择子除了含有索引值以外,它还包含了其他内容。
段选择子的结构如下图:
段选择子是一个16位的数据结构,其包含了三部分内容。其中,其高13位正是前面所说的索引值,TI用来指定是在GDT中索引,还是在LDT中索引(0 = GDT, 1 = LDT),RPL则是用来指明请求特权级的。
谈到这里,我们就已经阐明了在PM的段模式下,如何引用一个内存地址。首先,将段选择子装入相应的段寄存器中,然后CPU会自动根据段选择子找到相应的段描述符,并找出基地址,最后在加上偏移量,就得到了所需要的内存地址。
在本文开始的部分,我已经说过GDT是进入 PM所必需的数据结构,下面就详细的来讨论一下如何设置好GDT,并将其装入相应的寄存器.
首先必须注意的两点是:
1.GDT中的第一个描述符必须是空,即全为0。在程序中这个描述符不能用来进行内存访问,否则将产生General Protection异常。
2.由于GDT中的描述符都是64位长,因此为了让CPU的访问速度达到最快,需要将GDT的入口地址以8字节对齐,即放入8的倍数的位置.
下面,开始设置进入PM后的代码段和数据段的描述符.
其格式如下:
G – 粒度
D/B – 大小(0 = 16位段; 1 = 32位段)
D – 保留
AVL – 用户定义
P – 段是否存在
DPL – 描述符特权级
注意P位,这个位确定了段是否存在.这是什么意思呢.当该位被清除时,如果存在任务要访问这个段.那么CPU会产生一个错误,并会从外存(如:硬盘)中调入该段并再次尝试.当该位被清除时,描述符中的0到39位和48到63位能够包含任意值.你也可以用这些空间来存储该段在磁盘空间中的地址.
还有就是A位,CPU会在对其所在段写入数据后,将该位置1,这样在做段的磁盘交换时,可以决定是否将该段写入磁盘.
下面要说的就是G位.你会发现,在描述符中段界限仅仅为20位.那么其如何能够设置成1MB到4GB之间的范围呢.这里G位其了重要的作用.当G位被清零时,界限域就是段的最大合法偏移.而如果G位被置成1,那么会把描述符中的段界限左移12位形成32位界限,再将低12位全部填1.这样,实际上就能够指定1MB以下的任意长度,和以4K到4GB为单位的长度.
假定要在进入PM后,使代码段和数据段能够访问全部线性空间,于是可将GDT设置为:
gdt dd 00000000h, 00000000h ;空
gdt.Code32 dd 0000ffffh, 00cf9a00h ;代码段 读/执行 4GB空间 基地址 = 0 粒度 = 4096,386
gdt.Data32 dd 0000ffffh, 00cf9200h ;数据段 读/写 4GB空间 基地址 = 0 粒度 = 4096,386
这里你会发现在GDT中不同的描述符指向了同一块内存空间.这在系统中是允许的.在实际应用中,这也是经常要使用到的,例如:操作系统可以 将一个可执行文件装入数据段,然后再从同一位置开始执行.
在设置好GDT以后,需要将其装入相应的寄存器中.前面说过GDTR寄存器包含两段内容,因此我们需要先算出GDT的绝对物理地址.
GDTR的具体内容
gdtr dw gdtr - gdt – 1;界限
dd gdt;前面GDT的地址
实现代码如下:
mov eax, ds
shl eax, 4
add [gdtr+2], eax ; 生成绝对物理地址
lgdt [gdtr] ; 将gdtr装入寄存器
到此,就完成了进入保护模式的最主要工作,可以进入PM模式了.
实现代码如下:
mov eax, cr0
or al, 1
mov cr0, eax ; 修改CR0寄存器,置PE = 1
jmp dword 8:_premain32 ; 8为选择子
你可能会问为什么要在代码的最后添加一个jmp语句.这是因为,我们必须要清除CPU的指令预取队列(流水线),并以此来设置CS段寄存器. 不过这仅仅是其一,还有一个重要的原因就是,我前面谈到的那个段寄存器大于16位的不可见部分.需要指出的是,Intel对于这一点是未公开的,因此我下面对该问题的讨论仅仅是由推断得出来的。 事实上,当我们执行一条装载CS寄存器的指令时,操作数被装入了寄存器的可见部分,而CPU会自动根据操作数,去设置其不可见部分.CS段寄存器所处的状态与当前在哪个模式下并无关系。 在刚刚进PM后,CS仍然认为当前处于16位段,即当前的地址仍是16位地址。因此,必须通过 装载一条32位指令去切换到32位段,这也就是jmp在这里的意义.
虽然程序已经进入了PM,但需要做的事情还远没有做完,因为我们还没有配置IDT,即中断描述符表,而要理解这个表又要牵涉到许多内容,因此,我将在后面的文章中详细介绍,这里就不多谈了。
Intel之所以将这个模式起名为保护模式,其来源就在于特权保护。在PM下,每一个任务都拥有自己的特权级(PL)。Intel将其分为四个级别,由零到三。数字越低级别则越高。例如:PL3级的程序对于一些特定的指令,如:HLT,LGDT,LLDT等,没有执行的权限,并且其也不允许访问拥有高特权级程序的数据。
在PM下,I/O的访问同样也受到了特权保护。在EFLAGS中存在一个IOPL域。这个域的值决定了能够执行I/O操作的最低权限。例如,当IOPL为3的时候,表明所有特权级的程序都能够执行I/O操作。这个域的值仅允许PL0级的程序进行修改,其他级的程序修改无效。
同样,数据访问在PM下也是受到保护的。当数据段寄存器要被加载时,CPU会将该段的描述符特权级(DPL)与一个被称为有效特权级(EPL)的数值进行比较,如果DPL不小于EPL,则允许装载寄存器,否则将会产生一个错误。这里的EPL就是选择子的RPL和程序当前特权级(CPL)的数值较大的那一个。
对于堆栈,则有些不同,访问SS寄存器,其DPL要求必须和CPL相等
Top
32 楼W32API()回复于 2005-03-15 13:55:02 得分 0
首先,INTEL 对于上面所叙述的这些部分早就是公开的了。
看资料的时候记得看完全。
另外就是,不要人家说什么你们就跟着说什么。我看到 N 个人说这部分是 INTEL 不公开的,可 INTEL 明明在 SPEC 上已经把这部分说得详详细细的,为什么还是有这么多人在引用这段所谓不公开的资料?凸现某某人的分析能力?还是误人子弟?别人因为看到自己所需要的部分而没有关心其他部分而出现的笔误,你们是否都要全部继承下去?Top
33 楼daineng(纸玉鸢尾)回复于 2005-03-15 17:42:27 得分 0
大家有没有注意到启动时BIOS在结束时会将磁盘上的第一个扇区加载到0x7c00,然后在从这个地址处开始执行,一个扇区的大小是512个字节,也就是0x200个字节,加上0x7c00正好是0x8000,0x8000就是32KTop
34 楼daineng(纸玉鸢尾)回复于 2005-03-15 17:43:53 得分 0
算错了,呵呵,不好意思,加上512才是0x7e00,不过也在0x8000之内Top
35 楼ljhdi( )回复于 2005-03-15 18:04:54 得分 0
占个位,学习!Top
36 楼xxyifan(一帆)回复于 2005-03-15 18:18:31 得分 0
首先,大家不懂才问,再次,大家不懂才去查,然后贴出来让不知道的人知道,而不是在这里卖弄,如果高手在,并且他可以好好对这些小弟们说,我们感激不尽,如果我们走得错了,那么,高手指出来,我们更是。。。。,相信小弟们不只想听高手那种。。。Top
37 楼xxyifan(一帆)回复于 2005-03-16 08:09:18 得分 0
UP一下,看看那高手在不在Top
38 楼xxyifan(一帆)回复于 2005-03-16 09:07:50 得分 0
想不明白一件事,呵呵,既然这个不可见部分已经有基地址,为什么还要用到这个GDT或是LDT呢Top
39 楼daineng(纸玉鸢尾)回复于 2005-03-16 09:18:55 得分 0
同意楼上的楼上的楼上Top
40 楼xxyifan(一帆)回复于 2005-03-16 09:39:52 得分 0
所谓的高手吗?呵呵
真正的高手可能不敢进来了
上面那个问题有点笨,呵呵,见笑Top
41 楼daineng(纸玉鸢尾)回复于 2005-03-16 10:43:28 得分 0
看一段引导型病毒的资料
It's a simple matter to replace the code of
the partition table or boot record with your own. All your code has to do is
store the block somewhere else on the disk and replace the block with itself.
When the virus gains control, it needs to put itself in memory and then load
the original block into memory at 7C000 and then transfer control to this
code. Once it is in memory, it is free to infect any disks which come into
contact with the computer.
BIOS会把引导型病毒加载到0x7C00(我总觉得是7c00而不是7c000),病毒结束前要把原来的引导程序加载到7c00处,所以病毒的内存常驻部分一定在其他什么地方,但我觉得保存在其他地方容易被后来的系统或程序覆盖掉。一定有什么地方可以避免被覆盖,如果知道详细的情况,对了解机器启动以来的内存分配也是有帮助的Top
42 楼terry_followwind()回复于 2005-03-16 10:47:40 得分 0
daineng(纸玉鸢尾) :你说的哪个0x7c00的位置,是BIOS移交控制权给OS的地方,所以要把
HD的第一个sector copy到那里,然后执行,这个和这片帖子的题目有点远.而且,0x200是因为硬盘的一个sector就是0x200,可能不是你想的那样,可以boot的硬盘的boot sector里面会包含一些信息,有兴趣的话你可以去看关于硬盘操作那篇帖子,哪里我有说,你也可以到网上找INT13的Spec,或者去找DBR,或者搜索BOOT sector.
xxyifan(一帆) :我从来都没有说过我是高手,只是刚巧这个问题上知道的多了一点点而已(这几天工作有些忙,碰到比较棘手的问题!),在4GB access的时候,段寄存器是0,而我们平常用的时候,段寄存器都不是0,比如F000,而segment 不是0的时候,最大的寻址范围也就是,segment左移4位加上offset,我想一般的汇编书上都有吧,所以是access不到4GB的,要想access 到4GB是把segment设置为0,用offset去寻址.
内存的变化,上次说到在配置了内存的一些参数后,检测内存也ok后,这样堆栈可以用了,方便了很多,在POST快结束的时候,BIOS会告诉ACPI OS,memory到底是怎么样分配的,以256内存为例子,如果你有板载显卡,那么你就挖一段Memory给显卡用了,假设是8M的话,那么对OS和其他的程序,包含BIOS,是都不会认这段Memory的,也就是说,你插了一个256M的内存,如果你有板载显卡的话,那么OS会认为你只插了256-8=247M的内存,然后这样247M的内存,最下面的1M是reserved给DOS用的,当然这里面也会分的,这里先不说,想知道再说,那样会分的很细,可能分到每个byte都有自己的意义,这样就剩下了246M,这246M就是Extended Memory,Extended Memory还会分为几个type.
PS:我不是什么高手,我在这里只是个抛砖引玉的过程,也不要100%相信我,知识本来就是要怀疑的,如果一帆满意的话,那请结帖吧Top
43 楼daineng(纸玉鸢尾)回复于 2005-03-16 11:01:30 得分 0
terry_followwind() :偶们好像不是说你。你说的我早知道,就是不知道你什么意思。而我的意思是可以从机器启动后的程序流程来看内存的变化。
多谢回复Top
44 楼daineng(纸玉鸢尾)回复于 2005-03-16 11:08:55 得分 0
terry_followwind() :看了你给xxyifan(一帆)的回复,我觉得我最关心的旧是那个可以被分得很细的1M的内存使用情况,在哪里有资料可以查阅一下,希望可以告知一下Top
45 楼terry_followwind()回复于 2005-03-16 11:14:11 得分 0
一般0:9fc00是type 1(DOS 用),9fc00-a0000是 type 2(BIOS 的BDA),a0000-b0000,是VGA的frame buffer,c0000-d0000 是rom,e0000-f0000是BIOS用,比如DMI,
BDA:BIOS DATA AREATop
46 楼daineng(纸玉鸢尾)回复于 2005-03-16 11:15:41 得分 0
从哪里可以获得这些资料呢Top
47 楼terry_followwind()回复于 2005-03-16 11:40:03 得分 0
这个吗,你去看看能不能download ACPI specTop
48 楼daineng(纸玉鸢尾)回复于 2005-03-16 11:43:22 得分 5
3x,已经找到一个在载了Top
49 楼xxyifan(一帆)回复于 2005-03-16 13:08:35 得分 0
呵呵,我想题目不是问题,我们完全可以由一个题目引发好多的问题,我想是这样,TO:terry_followwind(),我可没说你是高手啊,呵呵,即使你是,呵呵
谢谢大家的回复,我感觉还可以GOON,许多不明白的地方还是存在的,比如:选择子不参与地址的运算,只是用来找到那个LDT在GDTR中的索引,是不是?寄存器中不可见的部分,便从这个GDTR中找到那个64位的GDT,是不是这样,看来寄存器不是32位的,至少是48位,也许资料中是不清楚的,或是不全面,可是我只能这样理解,还有,这个GDT中的BASE地址是什么时候写到寄存器中那不可见部分的?Top
50 楼terry_followwind()回复于 2005-03-16 13:24:09 得分 0
你说的不对,建议你去看,80x86保护模式的原理那本书,名字我记不太清了,好象是这个Top
51 楼xxyifan(一帆)回复于 2005-03-16 14:50:51 得分 0
哪里错了?我看的也是保护模式的书啊,呵呵Top
52 楼xxyifan(一帆)回复于 2005-03-17 07:57:26 得分 0
看来我的确要再开一贴了,这个贴子有点长了,我这里有个群,9631552,欢迎大家来讨论Top
53 楼W32API()回复于 2005-03-17 11:41:56 得分 5
to: xxyifan(一帆)
可以适当去看看
IA-32 Intel Architecture Software Developer Manual
验证那些说法
Top
54 楼xxyifan(一帆)回复于 2005-03-17 12:00:16 得分 0
to W32API() :
是的,正在看,我现在知道,国内的书是看不得的,谢谢Top
55 楼terry_followwind()回复于 2005-03-18 09:39:22 得分 0
W32API,你是做什么的?呵呵,你说这本书前段时间Intel在送,拿到了吗?Top
56 楼W32API()回复于 2005-03-18 12:55:31 得分 0
要了一套,不过丢在广州。最近没有在搞 INTEL 下的咚咚。
一般要看也看电子版的,省事,查起来也方便。
Top
57 楼terry_followwind()回复于 2005-03-18 14:01:32 得分 5
呵呵,最新的技术还是先有书然后再有电子档的,不过送的那种书早就有电子档了Top
58 楼adam2002(adam2002)回复于 2005-03-18 14:50:18 得分 0
mark硬盘扇区读写技Top




